template.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. <?php
  2. /*
  3. * Implements hook_preprocess_html().
  4. */
  5. function rubik_preprocess_html() {
  6. if (module_exists('views')) {
  7. drupal_add_css(drupal_get_path('module', 'views') . '/css/views-admin.seven.css', 'theme');
  8. }
  9. }
  10. /**
  11. * Implements hook_css_alter().
  12. * @TODO: Do this in .info once http://drupal.org/node/575298 is committed.
  13. */
  14. function rubik_css_alter(&$css) {
  15. if (isset($css['modules/overlay/overlay-child.css'])) {
  16. $css['modules/overlay/overlay-child.css']['data'] = drupal_get_path('theme', 'rubik') . '/overlay-child.css';
  17. }
  18. if (isset($css['modules/shortcut/shortcut.css'])) {
  19. $css['modules/shortcut/shortcut.css']['data'] = drupal_get_path('theme', 'rubik') . '/shortcut.css';
  20. }
  21. // This can be removed once http://drupal.org/node/1221560 is released
  22. if (isset($css['sites/all/modules/views/css/views-admin.rubik.css'])) {
  23. $css['sites/all/modules/views/css/views-admin.rubik.css']['data'] = drupal_get_path('theme', 'rubik') . '/views-admin.rubik.css';
  24. }
  25. }
  26. /**
  27. * Implementation of hook_theme().
  28. */
  29. function rubik_theme() {
  30. $items = array();
  31. // Content theming.
  32. $items['help'] =
  33. $items['node'] =
  34. $items['comment'] =
  35. $items['comment_wrapper'] = array(
  36. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  37. 'template' => 'object',
  38. );
  39. $items['node']['template'] = 'node';
  40. // Help pages really need help. See preprocess_page().
  41. $items['help_page'] = array(
  42. 'variables' => array('content' => array()),
  43. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  44. 'template' => 'object',
  45. 'preprocess functions' => array(
  46. 'template_preprocess',
  47. 'rubik_preprocess_help_page',
  48. ),
  49. 'process functions' => array('template_process'),
  50. );
  51. // Form layout: default (2 column).
  52. $items['block_add_block_form'] =
  53. $items['block_admin_configure'] =
  54. $items['comment_form'] =
  55. $items['contact_admin_edit'] =
  56. $items['contact_mail_page'] =
  57. $items['contact_mail_user'] =
  58. $items['filter_admin_format_form'] =
  59. $items['forum_form'] =
  60. $items['locale_languages_edit_form'] =
  61. $items['menu_edit_menu'] =
  62. $items['menu_edit_item'] =
  63. $items['node_type_form'] =
  64. $items['path_admin_form'] =
  65. $items['system_settings_form'] =
  66. $items['system_themes_form'] =
  67. $items['system_modules'] =
  68. $items['system_actions_configure'] =
  69. $items['taxonomy_form_term'] =
  70. $items['taxonomy_form_vocabulary'] =
  71. $items['user_profile_form'] =
  72. $items['user_admin_access_add_form'] = array(
  73. 'render element' => 'form',
  74. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  75. 'template' => 'form-default',
  76. 'preprocess functions' => array(
  77. 'rubik_preprocess_form_buttons',
  78. ),
  79. );
  80. // These forms require additional massaging.
  81. $items['confirm_form'] = array(
  82. 'render element' => 'form',
  83. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  84. 'template' => 'form-simple',
  85. 'preprocess functions' => array(
  86. 'rubik_preprocess_form_confirm'
  87. ),
  88. );
  89. $items['node_form'] = array(
  90. 'render element' => 'form',
  91. 'path' => drupal_get_path('theme', 'rubik') .'/templates',
  92. 'template' => 'form-default',
  93. 'preprocess functions' => array(
  94. 'rubik_preprocess_form_buttons',
  95. 'rubik_preprocess_form_node',
  96. ),
  97. );
  98. return $items;
  99. }
  100. /**
  101. * Preprocessor for theme('page').
  102. */
  103. function rubik_preprocess_page(&$vars) {
  104. // Show a warning if base theme is not present.
  105. if (!function_exists('tao_theme') && user_access('administer site configuration')) {
  106. drupal_set_message(t('The Rubik theme requires the !tao base theme in order to work properly.', array('!tao' => l('Tao', 'http://code.developmentseed.org/tao'))), 'warning');
  107. }
  108. // Set a page icon class.
  109. $vars['page_icon_class'] = ($item = menu_get_item()) ? implode(' ' , _rubik_icon_classes($item['href'])) : '';
  110. // Help pages. They really do need help.
  111. if (strpos($_GET['q'], 'admin/help/') === 0 && isset($vars['page']['content']['system_main']['main']['#markup'])) {
  112. $vars['page']['content']['system_main']['main']['#markup'] = theme('help_page', array('content' => $vars['page']['content']['system_main']['main']['#markup']));
  113. }
  114. // Clear out help text if empty.
  115. if (empty($vars['help']) || !(strip_tags($vars['help']))) {
  116. $vars['help'] = '';
  117. }
  118. // Process local tasks. Only do this processing if the current theme is
  119. // indeed Rubik. Subthemes must reimplement this call.
  120. global $theme;
  121. if ($theme === 'rubik') {
  122. _rubik_local_tasks($vars);
  123. }
  124. // Overlay is enabled.
  125. $vars['overlay'] = (module_exists('overlay') && overlay_get_mode() === 'child');
  126. }
  127. /**
  128. * Preprocessor for theme('fieldset').
  129. */
  130. function rubik_preprocess_fieldset(&$vars) {
  131. if (!empty($vars['element']['#collapsible'])) {
  132. $vars['title'] = "<span class='icon'></span>" . $vars['title'];
  133. }
  134. }
  135. /**
  136. * Preprocessor for handling form button for most forms.
  137. */
  138. function rubik_preprocess_form_buttons(&$vars) {
  139. if (!empty($vars['form']['actions'])) {
  140. $vars['actions'] = $vars['form']['actions'];
  141. unset($vars['form']['actions']);
  142. }
  143. }
  144. /**
  145. * Preprocessor for theme('confirm_form').
  146. */
  147. function rubik_preprocess_form_confirm(&$vars) {
  148. // Move the title from the page title (usually too big and unwieldy)
  149. $title = filter_xss_admin(drupal_get_title());
  150. $vars['form']['description']['#type'] = 'item';
  151. $vars['form']['description']['#value'] = empty($vars['form']['description']['#value']) ?
  152. "<strong>{$title}</strong>" :
  153. "<strong>{$title}</strong><p>{$vars['form']['description']['#value']}</p>";
  154. drupal_set_title(t('Please confirm'));
  155. }
  156. /**
  157. * Preprocessor for theme('node_form').
  158. */
  159. function rubik_preprocess_form_node(&$vars) {
  160. $vars['sidebar'] = isset($vars['sidebar']) ? $vars['sidebar'] : array();
  161. // Support nodeformcols if present.
  162. if (module_exists('nodeformcols')) {
  163. $map = array(
  164. 'nodeformcols_region_right' => 'sidebar',
  165. 'nodeformcols_region_footer' => 'footer',
  166. 'nodeformcols_region_main' => NULL,
  167. );
  168. foreach ($map as $region => $target) {
  169. if (isset($vars['form'][$region])) {
  170. if (isset($vars['form'][$region]['#prefix'], $vars['form'][$region]['#suffix'])) {
  171. unset($vars['form'][$region]['#prefix']);
  172. unset($vars['form'][$region]['#suffix']);
  173. }
  174. if (isset($vars['form'][$region]['actions'], $vars['form'][$region]['actions'])) {
  175. $vars['actions'] = $vars['form'][$region]['actions'];
  176. unset($vars['form'][$region]['actions']);
  177. }
  178. if (isset($target)) {
  179. $vars[$target] = $vars['form'][$region];
  180. unset($vars['form'][$region]);
  181. }
  182. }
  183. }
  184. }
  185. // Default to showing taxonomy in sidebar if nodeformcols is not present.
  186. elseif (isset($vars['form']['taxonomy']) && empty($vars['sidebar'])) {
  187. $vars['sidebar']['taxonomy'] = $vars['form']['taxonomy'];
  188. unset($vars['form']['taxonomy']);
  189. }
  190. }
  191. /**
  192. * Preprocessor for theme('button').
  193. */
  194. function rubik_preprocess_button(&$vars) {
  195. if (isset($vars['element']['#value'])) {
  196. $classes = array(
  197. t('Save') => 'yes',
  198. t('Submit') => 'yes',
  199. t('Add') => 'yes',
  200. t('Delete') => 'no',
  201. t('Cancel') => 'no',
  202. );
  203. foreach ($classes as $search => $class) {
  204. if (strpos($vars['element']['#value'], $search) !== FALSE) {
  205. $vars['element']['#attributes']['class'][] = 'button-' . $class;
  206. break;
  207. }
  208. }
  209. }
  210. }
  211. /**
  212. * Preprocessor for theme('help').
  213. */
  214. function rubik_preprocess_help(&$vars) {
  215. $vars['hook'] = 'help';
  216. $vars['attr']['id'] = 'help-text';
  217. $class = 'path-admin-help clear-block toggleable';
  218. $vars['attr']['class'] = isset($vars['attr']['class']) ? "{$vars['attr']['class']} $class" : $class;
  219. $help = menu_get_active_help();
  220. if (($test = strip_tags($help)) && !empty($help)) {
  221. // Thankfully this is static cached.
  222. $vars['attr']['class'] .= menu_secondary_local_tasks() ? ' with-tabs' : '';
  223. $vars['is_prose'] = TRUE;
  224. $vars['layout'] = TRUE;
  225. $vars['content'] = "<span class='icon'></span>" . $help;
  226. // Link to help section.
  227. $item = menu_get_item('admin/help');
  228. if ($item && $item['path'] === 'admin/help' && $item['access']) {
  229. $vars['links'] = l(t('More help topics'), 'admin/help');
  230. }
  231. }
  232. }
  233. /**
  234. * Preprocessor for theme('help_page').
  235. */
  236. function rubik_preprocess_help_page(&$vars) {
  237. $vars['hook'] = 'help-page';
  238. $vars['title_attributes_array']['class'][] = 'help-page-title';
  239. $vars['title_attributes_array']['class'][] = 'clearfix';
  240. $vars['content_attributes_array']['class'][] = 'help-page-content';
  241. $vars['content_attributes_array']['class'][] = 'clearfix';
  242. $vars['content_attributes_array']['class'][] = 'prose';
  243. $vars['layout'] = TRUE;
  244. // Truly hackish way to navigate help pages.
  245. $module_info = system_rebuild_module_data();
  246. $modules = array();
  247. foreach (module_implements('help', TRUE) as $module) {
  248. if (module_invoke($module, 'help', "admin/help#$module", NULL)) {
  249. $modules[$module] = $module_info[$module]->info['name'];
  250. }
  251. }
  252. asort($modules);
  253. $links = array();
  254. foreach ($modules as $module => $name) {
  255. $links[] = array('title' => $name, 'href' => "admin/help/{$module}");
  256. }
  257. $vars['links'] = theme('links', array('links' => $links));
  258. }
  259. /**
  260. * Preprocessor for theme('node').
  261. */
  262. function rubik_preprocess_node(&$vars) {
  263. $vars['layout'] = TRUE;
  264. $vars['submitted'] = _rubik_submitted($vars['node']);
  265. }
  266. /**
  267. * Preprocessor for theme('comment').
  268. */
  269. function rubik_preprocess_comment(&$vars) {
  270. $vars['layout'] = TRUE;
  271. $vars['submitted'] = _rubik_submitted($vars['comment']);
  272. }
  273. /**
  274. * Preprocessor for theme('comment_wrapper').
  275. */
  276. function rubik_preprocess_comment_wrapper(&$vars) {
  277. $vars['hook'] = 'box';
  278. $vars['layout'] = FALSE;
  279. $vars['title'] = t('Comments');
  280. $vars['attributes_array']['id'] = 'comments';
  281. $vars['title_attributes_array']['class'][] = 'box-title';
  282. $vars['title_attributes_array']['class'][] = 'clearfix';
  283. $vars['content_attributes_array']['class'][] = 'box-content';
  284. $vars['content_attributes_array']['class'][] = 'clearfix';
  285. $vars['content_attributes_array']['class'][] = 'prose';
  286. $vars['content'] = drupal_render_children($vars['content']);
  287. }
  288. /**
  289. * Preprocessor for theme('admin_block').
  290. */
  291. function rubik_preprocess_admin_block(&$vars) {
  292. // Add icon and classes to admin block titles.
  293. if (isset($vars['block']['href'])) {
  294. $vars['block']['localized_options']['attributes']['class'] = _rubik_icon_classes($vars['block']['href']);
  295. }
  296. $vars['block']['localized_options']['html'] = TRUE;
  297. if (isset($vars['block']['link_title'])) {
  298. $vars['block']['title'] = l("<span class='icon'></span>" . filter_xss_admin($vars['block']['link_title']), $vars['block']['href'], $vars['block']['localized_options']);
  299. }
  300. if (empty($vars['block']['content'])) {
  301. $vars['block']['content'] = "<div class='admin-block-description description'>{$vars['block']['description']}</div>";
  302. }
  303. }
  304. /**
  305. * Override of theme('breadcrumb').
  306. */
  307. function rubik_breadcrumb($vars) {
  308. $output = '';
  309. // Add current page onto the end.
  310. if (!drupal_is_front_page()) {
  311. $item = menu_get_item();
  312. $end = end($vars['breadcrumb']);
  313. if ($end && strip_tags($end) !== $item['title']) {
  314. $vars['breadcrumb'][] = "<strong>". check_plain($item['title']) ."</strong>";
  315. }
  316. }
  317. // Optional: Add the site name to the front of the stack.
  318. if (!empty($vars['prepend'])) {
  319. $site_name = empty($vars['breadcrumb']) ? "<strong>". check_plain(variable_get('site_name', '')) ."</strong>" : l(variable_get('site_name', ''), '<front>', array('purl' => array('disabled' => TRUE)));
  320. array_unshift($vars['breadcrumb'], $site_name);
  321. }
  322. $depth = 0;
  323. foreach ($vars['breadcrumb'] as $link) {
  324. $output .= "<span class='breadcrumb-link breadcrumb-depth-{$depth}'>{$link}</span>";
  325. $depth++;
  326. }
  327. return $output;
  328. }
  329. /**
  330. * Override of theme('filter_guidelines').
  331. */
  332. function rubik_filter_guidelines($variables) {
  333. return '';
  334. }
  335. /**
  336. * Override of theme('node_add_list').
  337. */
  338. function rubik_node_add_list($vars) {
  339. $content = $vars['content'];
  340. $output = "<ul class='admin-list'>";
  341. if ($content) {
  342. foreach ($content as $item) {
  343. $item['title'] = "<span class='icon'></span>" . filter_xss_admin($item['title']);
  344. if (isset($item['localized_options']['attributes']['class'])) {
  345. $item['localized_options']['attributes']['class'] += _rubik_icon_classes($item['href']);
  346. }
  347. else {
  348. $item['localized_options']['attributes']['class'] = _rubik_icon_classes($item['href']);
  349. }
  350. $item['localized_options']['html'] = TRUE;
  351. $output .= "<li>";
  352. $output .= l($item['title'], $item['href'], $item['localized_options']);
  353. $output .= '<div class="description">'. filter_xss_admin($item['description']) .'</div>';
  354. $output .= "</li>";
  355. }
  356. }
  357. $output .= "</ul>";
  358. return $output;
  359. }
  360. /**
  361. * Override of theme_admin_block_content().
  362. */
  363. function rubik_admin_block_content($vars) {
  364. $content = $vars['content'];
  365. $output = '';
  366. if (!empty($content)) {
  367. foreach ($content as $k => $item) {
  368. //-- Safety check for invalid clients of the function
  369. if (empty($content[$k]['localized_options']['attributes']['class'])) {
  370. $content[$k]['localized_options']['attributes']['class'] = array();
  371. }
  372. if (!is_array($content[$k]['localized_options']['attributes']['class'])) {
  373. $content[$k]['localized_options']['attributes']['class'] = array($content[$k]['localized_options']['attributes']['class']);
  374. }
  375. $content[$k]['title'] = "<span class='icon'></span>" . filter_xss_admin($item['title']);
  376. $content[$k]['localized_options']['html'] = TRUE;
  377. if (!empty($content[$k]['localized_options']['attributes']['class'])) {
  378. $content[$k]['localized_options']['attributes']['class'] += _rubik_icon_classes($item['href']);
  379. }
  380. else {
  381. $content[$k]['localized_options']['attributes']['class'] = _rubik_icon_classes($item['href']);
  382. }
  383. }
  384. $output = system_admin_compact_mode() ? '<ul class="admin-list admin-list-compact">' : '<ul class="admin-list">';
  385. foreach ($content as $item) {
  386. $output .= '<li class="leaf">';
  387. $output .= l($item['title'], $item['href'], $item['localized_options']);
  388. if (isset($item['description']) && !system_admin_compact_mode()) {
  389. $output .= "<div class='description'>{$item['description']}</div>";
  390. }
  391. $output .= '</li>';
  392. }
  393. $output .= '</ul>';
  394. }
  395. return $output;
  396. }
  397. /**
  398. * Override of theme('admin_drilldown_menu_item_link').
  399. */
  400. function rubik_admin_drilldown_menu_item_link($link) {
  401. $link['localized_options'] = empty($link['localized_options']) ? array() : $link['localized_options'];
  402. $link['localized_options']['html'] = TRUE;
  403. if (!isset($link['localized_options']['attributes']['class'])) {
  404. $link['localized_options']['attributes']['class'] = _rubik_icon_classes($link['href']);
  405. }
  406. else {
  407. $link['localized_options']['attributes']['class'] += _rubik_icon_classes($link['href']);
  408. }
  409. $link['description'] = check_plain(truncate_utf8(strip_tags($link['description']), 150, TRUE, TRUE));
  410. $link['description'] = "<span class='icon'></span>" . $link['description'];
  411. $link['title'] .= !empty($link['description']) ? "<span class='menu-description'>{$link['description']}</span>" : '';
  412. $link['title'] = filter_xss_admin($link['title']);
  413. return l($link['title'], $link['href'], $link['localized_options']);
  414. }
  415. /**
  416. * Preprocessor for theme('textfield').
  417. */
  418. function rubik_preprocess_textfield(&$vars) {
  419. if ($vars['element']['#size'] >= 30 && empty($vars['element']['#field_prefix']) && empty($vars['element']['#field_suffix'])) {
  420. $vars['element']['#size'] = '';
  421. if (!isset($vars['element']['#attributes']['class'])
  422. || !is_array($vars['element']['#attributes']['class'])) {
  423. $vars['element']['#attributes']['class'] = array();
  424. }
  425. $vars['element']['#attributes']['class'][] = 'fluid';
  426. }
  427. }
  428. /**
  429. * Override of theme('menu_local_task').
  430. */
  431. function rubik_menu_local_task($variables) {
  432. $link = $variables['element']['#link'];
  433. $link_text = $link['title'];
  434. if (!empty($variables['element']['#active'])) {
  435. // Add text to indicate active tab for non-visual users.
  436. $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
  437. // If the link does not contain HTML already, check_plain() it now.
  438. // After we set 'html'=TRUE the link will not be sanitized by l().
  439. if (empty($link['localized_options']['html'])) {
  440. $link['title'] = check_plain($link['title']);
  441. }
  442. $link['localized_options']['html'] = TRUE;
  443. $link_text = t('!local-task-title!active', array('!local-task-title' => $link['title'], '!active' => $active));
  444. }
  445. // Render child tasks if available.
  446. $children = '';
  447. if (element_children($variables['element'])) {
  448. $children = drupal_render_children($variables['element']);
  449. $children = "<ul class='secondary-tabs links clearfix'>{$children}</ul>";
  450. }
  451. return '<li' . (!empty($variables['element']['#active']) ? ' class="active"' : '') . '>' . l($link_text, $link['href'], $link['localized_options']) . $children . "</li>\n";
  452. }
  453. /**
  454. * Helper function for cloning and drupal_render()'ing elements.
  455. */
  456. function rubik_render_clone($elements) {
  457. static $instance;
  458. if (!isset($instance)) {
  459. $instance = 1;
  460. }
  461. foreach (element_children($elements) as $key) {
  462. if (isset($elements[$key]['#id'])) {
  463. $elements[$key]['#id'] = "{$elements[$key]['#id']}-{$instance}";
  464. }
  465. }
  466. $instance++;
  467. return drupal_render($elements);
  468. }
  469. /**
  470. * Helper function to submitted info theming functions.
  471. */
  472. function _rubik_submitted($node) {
  473. $byline = t('Posted by !username', array('!username' => theme('username', array('account' => $node))));
  474. $date = format_date($node->created, 'small');
  475. return "<div class='byline'>{$byline}</div><div class='date'>$date</div>";
  476. }
  477. /**
  478. * Generate an icon class from a path.
  479. */
  480. function _rubik_icon_classes($path) {
  481. $classes = array();
  482. $args = explode('/', $path);
  483. if ($args[0] === 'admin' || (count($args) > 1 && $args[0] === 'node' && $args[1] === 'add')) {
  484. // Add a class specifically for the current path that allows non-cascading
  485. // style targeting.
  486. $classes[] = 'path-'. str_replace('/', '-', implode('/', $args)) . '-';
  487. while (count($args)) {
  488. $classes[] = drupal_html_class('path-'. str_replace('/', '-', implode('/', $args)));
  489. array_pop($args);
  490. }
  491. return $classes;
  492. }
  493. return array();
  494. }
  495. function _rubik_local_tasks(&$vars) {
  496. if (!empty($vars['secondary_local_tasks']) && is_array($vars['primary_local_tasks'])) {
  497. foreach ($vars['primary_local_tasks'] as $key => $element) {
  498. if (!empty($element['#active'])) {
  499. $vars['primary_local_tasks'][$key] = $vars['primary_local_tasks'][$key] + $vars['secondary_local_tasks'];
  500. break;
  501. }
  502. }
  503. }
  504. }