PageRenderTime 122ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/profiles/openatrium/themes/ginkgo/template.php

https://gitlab.com/endomorphosis/aegir
PHP | 502 lines | 325 code | 60 blank | 117 comment | 57 complexity | f844ff5699a2ac457d0dd520309f03c7 MD5 | raw file
  1. <?php
  2. /**
  3. * Implementation of hook_theme().
  4. */
  5. function ginkgo_theme() {
  6. $items = array();
  7. // Use simple form.
  8. $items['comment_form'] =
  9. $items['user_pass'] =
  10. $items['user_login'] =
  11. $items['user_register'] = array(
  12. 'arguments' => array('form' => array()),
  13. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  14. 'template' => 'form-simple',
  15. 'preprocess functions' => array(
  16. 'rubik_preprocess_form_buttons',
  17. 'rubik_preprocess_form_legacy'
  18. ),
  19. );
  20. return $items;
  21. }
  22. /**
  23. * Add an href-based class to links for themers to implement icons.
  24. */
  25. function ginkgo_icon_links(&$links) {
  26. if (!empty($links)) {
  27. foreach ($links as $k => $v) {
  28. if (empty($v['attributes'])) {
  29. $v['attributes'] = array('class' => '');
  30. }
  31. else if (empty($v['attributes']['class'])) {
  32. $v['attributes']['class'] = '';
  33. }
  34. $v['attributes']['class'] .= ' icon-'. _ginkgo_icon_class($v['href']);
  35. // Detect and replace counter occurrences with markup.
  36. $start = strpos($v['title'], '(');
  37. $end = strpos($v['title'], ')');
  38. if ($start !== FALSE && $end !== FALSE && $start < $end) {
  39. $v['title'] = strtr($v['title'], array('(' => "<span class='count'>", ')' => "</span>"));
  40. }
  41. $v['title'] = filter_xss_admin("<span class='icon'></span><span class='label'>". $v['title'] ."</span>");
  42. $v['html'] = TRUE;
  43. $links[$k] = $v;
  44. }
  45. }
  46. }
  47. /**
  48. * Preprocess overrides ===============================================
  49. */
  50. /**
  51. * Preprocessor for theme_page().
  52. */
  53. function ginkgo_preprocess_page(&$vars) {
  54. // Switch layout for 404/403 pages.
  55. $headers = drupal_get_headers();
  56. if ((strpos($headers, 'HTTP/1.1 403 Forbidden') !== FALSE) || strpos($headers, 'HTTP/1.1 404 Not Found') !== FALSE) {
  57. $vars['template_files'][] = 'layout-wide';
  58. }
  59. // Add body class for layout.
  60. $vars['attr']['class'] .= !empty($vars['template_files']) ? ' '. end($vars['template_files']) : '';
  61. // Don't show the navigation in the admin section.
  62. // Otherwise add icon markup to main menu.
  63. if (arg(0) === 'admin') {
  64. $vars['primary_links'] = '';
  65. }
  66. else {
  67. ginkgo_icon_links($vars['primary_links']);
  68. }
  69. // If tabs are active, the title is likely shown in them. Don't show twice.
  70. $vars['title_attr'] = array('class' => 'page-title');
  71. $vars['title_attr']['class'] .= (!empty($vars['tabs']) || menu_get_object()) ? ' page-title-hidden' : '';
  72. // Show mission text on login page for anonymous users.
  73. global $user;
  74. $vars['mission'] = (!$user->uid && arg(0) == 'user') ? filter_xss_admin(variable_get('site_mission', '')) : '';
  75. // Fallback logo.
  76. $vars['logo'] = !empty($vars['logo']) ? $vars['logo'] : l(check_plain(variable_get('site_name', 'Drupal')), '<front>', array('attributes' => array('class' => 'logo')));
  77. // Footer links
  78. $vars['footer_links'] = isset($vars['footer_links']) ? $vars['footer_links'] : array();
  79. $item = menu_get_item('admin');
  80. if ($item && $item['access']) {
  81. $vars['footer_links']['admin'] = $item;
  82. }
  83. // IE7 CSS
  84. // @TODO: Implement IE styles key in tao.
  85. $ie = base_path() . drupal_get_path('theme', 'ginkgo') .'/ie.css';
  86. $vars['ie'] = "<!--[if lte IE 8]><style type='text/css' media='screen'>@import '{$ie}';</style><![endif]-->";
  87. // Help text toggler link.
  88. $vars['help_toggler'] = !empty($vars['help']) ? l(t('Help'), $_GET['q'], array('fragment' => 'block-atrium-help', 'attributes' => array('id' => 'help-toggler', 'class' => 'palette-toggle'))) : '';
  89. }
  90. /**
  91. * Preprocessor for theme_block().
  92. */
  93. function ginkgo_preprocess_block(&$vars) {
  94. // If block is in a toggleable region and does not have a subject, mark it as a "widget,"
  95. // i.e. show its contents rather than a toggle trigger label.
  96. if (in_array($vars['block']->region, array('header', 'page_tools', 'space_tools'))) {
  97. if (empty($vars['block']->subject)) {
  98. $vars['attr']['class'] .= ' block-widget';
  99. }
  100. else {
  101. $vars['attr']['class'] .= ' block-toggle';
  102. // Add invisible link element for toggling block via keyboard.
  103. $vars['title'] = l(t('Toggle'), $_GET['q'], array('fragment' => $vars['attr']['id'], 'attributes' => array('class' => 'toggle element-invisible'))) . $vars['title'];
  104. }
  105. }
  106. if ($vars['block']->region === 'palette') {
  107. // Palette region requires module-level jQuery UI, Cookie, JSON includes.
  108. // Note that drupal_add_js() only works here because blocks are rendered
  109. // prior to the retrieval of javascript files in template_preprocess_page().
  110. module_exists('admin') ? drupal_add_js(drupal_get_path('module', 'admin') .'/includes/jquery.cookie.js') : '';
  111. module_exists('jquery_ui') ? jquery_ui_add(array('ui.draggable')) : '';
  112. module_exists('context_ui') ? drupal_add_js(drupal_get_path('module', 'context_ui') .'/json2.js') : '';
  113. // Add close button to palette region blocks.
  114. $vars['title'] = "<span class='close'></span>{$vars['title']}";
  115. }
  116. $vars['attr']['class'] .= empty($vars['block']->subject) ? ' block-notitle' : '';
  117. }
  118. /**
  119. * Preprocessor for theme_context_block_editable_region().
  120. */
  121. function ginkgo_preprocess_context_block_editable_region(&$vars) {
  122. if (in_array($vars['region'], array('header', 'page_tools', 'space_tools', 'palette'))) {
  123. $vars['editable'] = FALSE;
  124. }
  125. }
  126. /**
  127. * Preprocessor for theme_help().
  128. */
  129. function ginkgo_preprocess_help(&$vars) {
  130. $vars['layout'] = FALSE;
  131. $vars['links'] = '';
  132. }
  133. /**
  134. * Preprocessor for theme_node().
  135. */
  136. function ginkgo_preprocess_node(&$vars) {
  137. if (!empty($vars['terms'])) {
  138. $label = t('Tagged');
  139. $terms = "<div class='field terms clear-block'><span class='field-label-inline-first'>{$label}:</span> {$vars['terms']}</div>";
  140. $vars['content'] = $terms . $vars['content'];
  141. }
  142. $vars['title'] = check_plain($vars['node']->title);
  143. $vars['layout'] = FALSE;
  144. // Add node-page class.
  145. $vars['attr']['class'] .= $vars['node'] === menu_get_object() ? ' node-page' : '';
  146. // Don't show the full node when a comment is being previewed.
  147. $vars = context_get('comment', 'preview') == TRUE ? array() : $vars;
  148. // Clear out catchall template file suggestions like those made by og.
  149. // TODO refactor
  150. if (!empty($vars['template_files'])) {
  151. foreach ($vars['template_files'] as $k => $f) {
  152. if (strpos($f, 'node-'.$vars['type']) === FALSE) {
  153. unset($vars['template_files'][$k]);
  154. }
  155. }
  156. }
  157. }
  158. /**
  159. * Preprocessor for theme_comment().
  160. */
  161. function ginkgo_preprocess_comment(&$vars) {
  162. // Add a time decay class.
  163. $decay = _ginkgo_get_comment_decay($vars['node']->nid, $vars['comment']->timestamp);
  164. $vars['attr']['class'] .= " decay-{$decay['decay']}";
  165. // If subject field not enabled, replace the title with a number.
  166. if (!variable_get("comment_subject_field_{$vars['node']->type}", 1)) {
  167. $vars['title'] = l("#{$decay['order']}", "node/{$vars['node']->nid}", array('fragment' => "comment-{$vars['comment']->cid}"));
  168. }
  169. // We're totally previewing a comment... set a context so others can bail.
  170. if (module_exists('context')) {
  171. if (empty($vars['comment']->cid) && !empty($vars['comment']->form_id)) {
  172. context_set('comment', 'preview', TRUE);
  173. }
  174. else if (context_isset('comment', 'preview')) {
  175. $vars = array();
  176. }
  177. }
  178. }
  179. /**
  180. * Preprocessor for theme_node_form().
  181. */
  182. function ginkgo_preprocess_node_form(&$vars) {
  183. // Add node preview to top of the form if present
  184. $preview = theme('node_preview', NULL, TRUE);
  185. $vars['form']['preview'] = array('#type' => 'markup', '#weight' => -1000, '#value' => $preview);
  186. if (!empty($vars['form']['archive'])) {
  187. $vars['sidebar']['archive'] = $vars['form']['archive'];
  188. unset($vars['form']['archive']);
  189. }
  190. }
  191. /**
  192. * Function overrides =================================================
  193. */
  194. /**
  195. * Make logo markup overridable.
  196. */
  197. function ginkgo_designkit_image($name, $filepath) {
  198. if ($name === 'logo') {
  199. $title = variable_get('site_name', '');
  200. if (module_exists('spaces') && $space = spaces_get_space()) {
  201. $title = $space->title();
  202. }
  203. $url = imagecache_create_url("designkit-image-{$name}", $filepath);
  204. $options = array('attributes' => array('class' => 'logo', 'style' => "background-position:100% 50%; background-image:url('{$url}')"));
  205. return l($space->title, '<front>', $options);
  206. }
  207. return theme_designkit_image($name, $filepath);
  208. }
  209. /**
  210. * More link theme override.
  211. */
  212. function ginkgo_more_link($url, $title) {
  213. return '<div class="more-link">'. t('<a href="@link" title="@title">View more</a>', array('@link' => check_url($url), '@title' => $title)) .'</div>';
  214. }
  215. /**
  216. * Override of theme_breadcrumb().
  217. */
  218. function ginkgo_breadcrumb($breadcrumb) {
  219. $breadcrumb = empty($breadcrumb) ? array(l(t('Home'), '<front>')) : $breadcrumb;
  220. $i = 0;
  221. foreach ($breadcrumb as $k => $link) {
  222. $breadcrumb[$k] = "<span class='link link-{$i}'>{$link}</span>";
  223. $i++;
  224. }
  225. $breadcrumb = implode("<span class='divider'></span>", $breadcrumb);
  226. // Marker for this group as public or private.
  227. $space = spaces_get_space();
  228. if ($space && $space->type === 'og') {
  229. $attr = $space->group->og_private ?
  230. array('title' => t('Private'), 'class' => 'private') :
  231. array('title' => t('Public'), 'class' => 'public');
  232. $link = l('', $_GET['q'], array('attributes' => $attr));
  233. $breadcrumb .= "<span class='space'>{$link}</span>";
  234. }
  235. return "<div class='breadcrumb'>{$breadcrumb}</div>";
  236. }
  237. /**
  238. * Override of theme_pager(). Tao has already done the hard work for us.
  239. * Just exclude last/first links.
  240. */
  241. function ginkgo_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
  242. $pager_list = theme('pager_list', $tags, $limit, $element, $parameters, $quantity);
  243. $links = array();
  244. $links['pager-previous'] = theme('pager_previous', ($tags[1] ? $tags[1] : t('Prev')), $limit, $element, 1, $parameters);
  245. $links['pager-next'] = theme('pager_next', ($tags[3] ? $tags[3] : t('Next')), $limit, $element, 1, $parameters);
  246. $pager_links = theme('links', $links, array('class' => 'links pager pager-links'));
  247. if ($pager_list) {
  248. return "<div class='pager clear-block'>$pager_list $pager_links</div>";
  249. }
  250. }
  251. /**
  252. * Override of theme_views_mini_pager().
  253. * Wrappers, tao handles the rest.
  254. */
  255. function ginkgo_views_mini_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
  256. $tags[1] = t('Prev');
  257. $tags[3] = t('Next');
  258. $minipager = tao_views_mini_pager($tags, $limit, $element, $parameters, $quantity);
  259. return $minipager ? "<div class='pager minipager clear-block'>{$minipager}</div>" : '';
  260. }
  261. /**
  262. * Override of theme_node_preview().
  263. * We remove the teaser check / view here ... for nearly all use cases
  264. * this is more confusing and overbearing than anything else. We also
  265. * add a static variable as a trigger so that we can render node_preview
  266. * inside our form, rather than separate.
  267. */
  268. function ginkgo_node_preview($node = NULL, $show = FALSE) {
  269. static $output;
  270. if (!isset($output) && $node) {
  271. $element = array(
  272. '#title' => t('Preview'),
  273. '#children' => node_view($node, 0, FALSE, 0),
  274. '#collapsed' => FALSE,
  275. '#collapsible' => TRUE,
  276. '#attributes' => array('class' => 'node-preview'),
  277. );
  278. $output = theme('fieldset', $element);
  279. }
  280. return $show ? $output : '';
  281. }
  282. /**
  283. * Override of theme_content_multiple_values().
  284. * Adds a generic wrapper.
  285. */
  286. function ginkgo_content_multiple_values($element) {
  287. $output = theme_content_multiple_values($element);
  288. $field_name = $element['#field_name'];
  289. $field = content_fields($field_name);
  290. if ($field['multiple'] >= 1) {
  291. return "<div class='content-multiple-values'>{$output}</div>";
  292. }
  293. return $output;
  294. }
  295. /**
  296. * Override of theme('node_submitted').
  297. */
  298. function ginkgo_node_submitted($node) {
  299. $byline = theme('username', $node);
  300. $date = module_exists('reldate') ? reldate_format_date($node->created) : format_date($node->created, 'small');
  301. return "<div class='byline'>{$byline}</div><div class='date'>$date</div>";
  302. }
  303. /**
  304. * Override of theme('comment_submitted').
  305. */
  306. function ginkgo_comment_submitted($comment) {
  307. $comment->created = $comment->timestamp;
  308. return ginkgo_node_submitted($comment);
  309. }
  310. /**
  311. * Preprocessor for theme('views_view_fields').
  312. */
  313. function ginkgo_preprocess_views_view_fields(&$vars) {
  314. foreach ($vars['fields'] as $field) {
  315. if ($class = _ginkgo_get_views_field_class($field->handler)) {
  316. $field->class = $class;
  317. }
  318. }
  319. // Write this as a row plugin to allow modules/features to define this stuff.
  320. if (get_class($vars['view']->style_plugin) == 'views_plugin_style_list') {
  321. $enable_grouping = TRUE;
  322. // Override arrays for grouping
  323. $view_id = "{$vars['view']->name}:{$vars['view']->current_display}";
  324. $overrides = array(
  325. "profile_display:page_1" => array(),
  326. "blog_comments:block_1" => array(
  327. 'meta' => array('date', 'user-picture', 'username', 'author'),
  328. ),
  329. );
  330. if (isset($overrides[$view_id])) {
  331. $groups = $overrides[$view_id];
  332. }
  333. else {
  334. $groups = array(
  335. 'meta' => array('date', 'user-picture', 'username', 'related-title', 'author'),
  336. 'admin' => array('edit', 'delete'),
  337. );
  338. }
  339. foreach ($vars['fields'] as $id => $field) {
  340. $found = FALSE;
  341. foreach ($groups as $group => $valid_fields) {
  342. if (in_array($field->class, $valid_fields)) {
  343. $grouped[$group][$id] = $field;
  344. $found = TRUE;
  345. break;
  346. }
  347. }
  348. if (!$found) {
  349. $grouped['content'][$id] = $field;
  350. }
  351. }
  352. // If the listing doesn't have any fields that will be grouped
  353. // fallback to default (non-grouped) formatting.
  354. $enable_grouping = count($grouped) <= 1 ? FALSE : TRUE;
  355. $vars['classes'] = isset($vars['classes']) ? $vars['classes'] : '';
  356. foreach (array_keys($grouped) as $group) {
  357. $vars['classes'] .= " grouping-{$group}";
  358. }
  359. }
  360. else {
  361. $enable_grouping = FALSE;
  362. $grouped = array('content' => $vars['fields']);
  363. }
  364. $vars['enable_grouping'] = $enable_grouping;
  365. $vars['grouped'] = $grouped;
  366. }
  367. /**
  368. * Preprocessor for theme('views_view_table').
  369. */
  370. function ginkgo_preprocess_views_view_table(&$vars) {
  371. $view = $vars['view'];
  372. foreach ($view->field as $field => $handler) {
  373. if (isset($vars['fields'][$field]) && $class = _ginkgo_get_views_field_class($handler)) {
  374. $vars['fields'][$field] = $class;
  375. }
  376. }
  377. }
  378. /**
  379. * Helper function to get the appropriate class name for Views field.
  380. */
  381. function _ginkgo_get_views_field_class($handler) {
  382. $handler_class = get_class($handler);
  383. $search = array(
  384. 'project' => 'project',
  385. 'priority' => 'priority',
  386. 'status' => 'status',
  387. 'history_user' => 'new',
  388. 'date' => 'date',
  389. 'timestamp' => 'date',
  390. 'user_picture' => 'user-picture',
  391. 'username' => 'username',
  392. 'name' => 'username',
  393. 'markup' => 'markup',
  394. 'xss' => 'markup',
  395. 'spaces_feature' => 'feature',
  396. 'group_nids' => 'group',
  397. 'numeric' => 'number',
  398. 'count' => 'count',
  399. 'edit' => 'edit',
  400. 'delete' => 'delete',
  401. );
  402. foreach ($search as $needle => $class) {
  403. if (strpos($handler_class, $needle) !== FALSE) {
  404. return $class;
  405. }
  406. }
  407. // Fallback
  408. if (!empty($handler->relationship) && ($handler->view->base_table !== 'users')) {
  409. return "related-{$handler->field}";
  410. }
  411. return $handler->field;
  412. }
  413. /**
  414. * Return both an order (e.g. #1 for oldest to #n for the nth comment)
  415. * and a decay value (0 for newest, 10 for oldest) for a given comment.
  416. */
  417. function _ginkgo_get_comment_decay($nid, $timestamp) {
  418. static $timerange;
  419. if (!isset($timerange[$nid])) {
  420. $range = array();
  421. $result = db_query("SELECT timestamp FROM {comments} WHERE nid = %d ORDER BY timestamp ASC", $nid);
  422. $i = 1;
  423. while ($row = db_fetch_object($result)) {
  424. $timerange[$nid][$row->timestamp] = $i;
  425. $i++;
  426. }
  427. }
  428. if (!empty($timerange[$nid][$timestamp])) {
  429. $decay = max(array_keys($timerange[$nid])) - min(array_keys($timerange[$nid]));
  430. $decay = $decay > 0 ? ((max(array_keys($timerange[$nid])) - $timestamp) / $decay) : 0;
  431. $decay = floor($decay * 10);
  432. return array('order' => $timerange[$nid][$timestamp], 'decay' => $decay);
  433. }
  434. return array('order' => 1, 'decay' => 0);
  435. }
  436. /**
  437. * Generate an icon class from a path.
  438. */
  439. function _ginkgo_icon_class($path) {
  440. $path = drupal_get_path_alias($path);
  441. return str_replace('/', '-', $path);
  442. }