4 * File which contains theme overrides for the Zen theme.
8 * The template.php file is one of the most useful files when creating or
9 * modifying Drupal themes. You can add new regions for block content, modify or
10 * override Drupal's theme functions, intercept or make additional variables
11 * available to your theme, and create custom PHP logic. For more information,
12 * please visit the Theme Developer's Guide on Drupal.org:
13 * http://drupal.org/theme-guide
15 * NOTE ABOUT ZEN'S TEMPLATE.PHP FILE
17 * The base Zen theme is designed to be easily extended by its sub-themes. You
18 * shouldn't modify this or any of the CSS or PHP files in the root zen/ folder.
19 * See the online documentation for more information:
20 * http://drupal.org/node/193318
25 * To make this file easier to read, we split up the code into managable parts.
26 * Theme developers are likely to only be interested in functions that are in
27 * this main template.php file.
31 include_once
'template-subtheme.php';
33 // Initialize theme settings
34 include_once
'theme-settings-init.php';
36 // Tabs and menu functions
37 include_once
'template-menus.php';
41 * Declare the available regions implemented by this theme.
43 * Regions are areas in your theme where you can place blocks. The default
44 * regions used in themes are "left sidebar", "right sidebar", "header", and
45 * "footer", although you can create as many regions as you want. Once declared,
46 * they are made available to the page.tpl.php file as a variable. For instance,
47 * use <?php print $header ?> for the placement of the "header" region in
50 * By going to the administer > site building > blocks page you can choose
51 * which regions various blocks should be placed. New regions you define here
52 * will automatically show up in the drop-down list by their human readable name.
55 * An array of regions. The first array element will be used as the default
56 * region for themes. Each array element takes the format:
57 * variable_name => t('human readable name')
59 function zen_regions() {
60 // Allow a sub-theme to define its own regions.
62 if ($theme_key != 'zen') {
63 $function = str_replace('-', '_', $theme_key) .
'_regions';
64 if (function_exists($function)) {
70 'left' => t('left sidebar'),
71 'right' => t('right sidebar'),
72 'navbar' => t('navigation bar'),
73 'content_top' => t('content top'),
74 'content_bottom' => t('content bottom'),
75 'header' => t('header'),
76 'footer' => t('footer'),
77 'closure_region' => t('closure'),
83 * Return a themed breadcrumb trail.
86 * An array containing the breadcrumb links.
88 * A string containing the breadcrumb output.
90 function phptemplate_breadcrumb($breadcrumb) {
91 $show_breadcrumb = theme_get_setting('zen_breadcrumb');
92 $show_breadcrumb_home = theme_get_setting('zen_breadcrumb_home');
93 $breadcrumb_separator = theme_get_setting('zen_breadcrumb_separator');
94 $trailing_separator = (theme_get_setting('zen_breadcrumb_trailing') || theme_get_setting('zen_breadcrumb_title')) ?
$breadcrumb_separator : '';
96 // Determine if we are to display the breadcrumb
97 if ($show_breadcrumb == 'yes' || $show_breadcrumb == 'admin' && arg(0) == 'admin') {
98 if (!$show_breadcrumb_home) {
99 // Optionally get rid of the homepage link
100 array_shift($breadcrumb);
102 if (!empty($breadcrumb)) {
103 // Return the breadcrumb with separators
104 return '<div class="breadcrumb">'.
implode($breadcrumb_separator, $breadcrumb) .
"$trailing_separator</div>";
107 // Otherwise, return an empty string
113 * CREATE OR MODIFY VARIABLES FOR YOUR THEME
115 * The most powerful function available to themers is _phptemplate_variables().
116 * It allows you to pass newly created variables to different template (tpl.php)
117 * files in your theme. Or even unset ones you don't want to use.
119 * It works by switching on the hook, or name of the theme function, such as:
125 * By switching on this hook you can send different variables to page.tpl.php
126 * file, node.tpl.php (and any other derivative node template file, like
127 * node-forum.tpl.php), comment.tpl.php, and block.tpl.php.
132 * Intercept template variables
135 * The name of the theme function being called (name of the .tpl.php file.)
137 * A copy of the array containing the variables for the hook.
139 * The array containing additional variables to merge with $vars.
141 function _phptemplate_variables($hook, $vars = array()) {
144 // Allow modules to add or alter variables.
145 // This construct ensures that we can keep a reference through
146 // call_user_func_array.
147 $args = array(&$vars, $hook);
148 foreach (module_implements('preprocess') as
$module) {
149 if ($module != 'search') { // Don't call search_preprocess().
150 $function = $module .
'_preprocess';
151 call_user_func_array($function, $args);
154 foreach (module_implements('preprocess_'.
$hook) as
$module) {
155 $function = $module .
'_preprocess_'.
$hook;
156 call_user_func_array($function, $args);
159 // Allow the Zen base theme to add or alter variables.
160 if ($theme_key != 'zen') {
161 zen_preprocess($vars, $hook);
162 $function = 'zen_preprocess_'.
$hook;
163 if (function_exists($function)) {
164 $function($vars, $hook);
168 // Allow a sub-theme to add or alter variables.
169 $function = $theme_key .
'_preprocess';
170 if (function_exists($function)) {
171 $function($vars, $hook);
174 $function = 'phptemplate_preprocess';
175 if (function_exists($function)) {
176 $function($vars, $hook);
179 $function = $theme_key .
'_preprocess_'.
$hook;
180 if (function_exists($function)) {
181 $function($vars, $hook);
184 $function = 'phptemplate_preprocess_'.
$hook;
185 if (function_exists($function)) {
186 $function($vars, $hook);
190 // The following is a deprecated function included for backwards compatibility
191 // with Zen 5.x-0.8 and earlier. New sub-themes should not use this function.
192 if (function_exists('zen_variables')) {
193 $vars = zen_variables($hook, $vars);
196 _zen_hook($hook); // Add support for sub-theme template files.
202 * Override or insert PHPTemplate variables into all templates.
205 * A sequential array of variables to pass to the theme template.
207 * The name of the theme function being called (name of the .tpl.php file.)
209 function zen_preprocess(&$vars, $hook) {
210 // Get the currently logged in user
213 // Set a new $is_admin variable. This is determined by looking at the
214 // currently logged in user and seeing if they are in the role 'admin'. The
215 // 'admin' role will need to have been created manually for this to work this
216 // variable is available to all templates.
217 $vars['is_admin'] = in_array('admin', $user->roles
);
219 // Send a new variable, $logged_in, to tell us if the current user is
220 // logged in or out. An anonymous user has a user id of 0.
221 $vars['logged_in'] = ($user->uid
> 0) ? TRUE
: FALSE
;
225 * Override or insert PHPTemplate variables into the page templates.
228 * A sequential array of variables to pass to the theme template.
230 function zen_preprocess_page(&$vars) {
231 global $theme, $theme_key;
233 // Allow sub-themes to have an ie.css or wireframes.css file.
234 $vars['subtheme_directory'] = path_to_subtheme();
236 // These next lines add additional CSS files and redefine
237 // the $css and $styles variables available to your page template
238 if ($theme == $theme_key) { // If we're in the main theme
239 // Load the stylesheet for a liquid layout
240 if (theme_get_setting('zen_layout') == 'border-politics-liquid') {
241 drupal_add_css($vars['directory'] .
'/layout-liquid.css', 'theme', 'all');
243 // Or load the stylesheet for a fixed width layout
245 drupal_add_css($vars['directory'] .
'/layout-fixed.css', 'theme', 'all');
247 drupal_add_css($vars['directory'] .
'/html-elements.css', 'theme', 'all');
248 drupal_add_css($vars['directory'] .
'/tabs.css', 'theme', 'all');
249 drupal_add_css($vars['directory'] .
'/zen.css', 'theme', 'all');
250 // Avoid IE5 bug that always loads @import print stylesheets
251 $vars['head'] = zen_add_print_css($vars['directory'] .
'/print.css');
253 // Optionally add the block editing styles.
254 if (theme_get_setting('zen_block_editing')) {
255 drupal_add_css($vars['directory'] .
'/block-editing.css', 'theme', 'all');
257 // Optionally add the wireframes style.
258 if (theme_get_setting('zen_wireframes')) {
259 if ($vars['subtheme_directory'] && file_exists($vars['subtheme_directory'] .
'/wireframes.css')) {
260 drupal_add_css($vars['subtheme_directory'] .
'/wireframes.css', 'theme', 'all');
263 drupal_add_css($vars['directory'] .
'/wireframes.css', 'theme', 'all');
266 $vars['css'] = drupal_add_css();
267 $vars['styles'] = drupal_get_css();
269 // Add an optional title to the end of the breadcrumb.
270 if (theme_get_setting('zen_breadcrumb_title') && $vars['breadcrumb']) {
271 $vars['breadcrumb'] = substr($vars['breadcrumb'], 0, -6) .
$vars['title'] .
'</div>';
274 // Don't display empty help from node_help().
275 if ($vars['help'] == "<div class=\"help\"><p></p>\n</div>") {
279 // Optionally disabled the primary and secondary links.
280 if (!theme_get_setting('zen_primary_links')) {
281 $vars['primary_links'] = '';
283 if (!theme_get_setting('zen_secondary_links')) {
284 $vars['secondary_links'] = '';
287 // Classes for body element. Allows advanced theming based on context
288 // (home page, node of certain type, etc.)
290 $classes[] = ($vars['is_front']) ?
'front' : 'not-front';
291 $classes[] = ($vars['logged_in']) ?
'logged-in' : 'not-logged-in';
292 if ($vars['node']->type
) {
293 // If on an individual node page, put the node type in the body classes
294 $classes[] = 'node-type-'.
$vars['node']->type
;
296 if ($vars['sidebar_left'] && $vars['sidebar_right']) {
297 $classes[] = 'two-sidebars';
299 elseif ($vars['sidebar_left']) {
300 $classes[] = 'one-sidebar sidebar-left';
302 elseif ($vars['sidebar_right']) {
303 $classes[] = 'one-sidebar sidebar-right';
306 $classes[] = 'no-sidebars';
308 if (!$vars['is_front']) {
309 // Add unique class for each page.
310 $path = drupal_get_path_alias($_GET['q']);
311 $classes[] = zen_id_safe('page-'.
$path);
312 // Add unique class for each website section.
313 list($section, ) = explode('/', $path, 2);
314 if (arg(0) == 'node') {
315 if (arg(1) == 'add') {
316 $section = 'node-add';
318 elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
319 $section = 'node-'.
arg(2);
322 $classes[] = zen_id_safe('section-'.
$section);
324 $vars['body_classes_array'] = $classes;
325 $vars['body_classes'] = implode(' ', $classes); // Concatenate with spaces.
329 * Override or insert PHPTemplate variables into the node templates.
332 * A sequential array of variables to pass to the theme template.
334 function zen_preprocess_node(&$vars) {
337 // Special classes for nodes
338 $node_classes = array();
339 if ($vars['sticky']) {
340 $node_classes[] = 'sticky';
342 if (!$vars['node']->status
) {
343 $node_classes[] = 'node-unpublished';
344 $vars['unpublished'] = TRUE
;
347 $vars['unpublished'] = FALSE
;
349 if ($vars['node']->uid
&& $vars['node']->uid
== $user->uid
) {
350 // Node is authored by current user
351 $node_classes[] = 'node-mine';
353 if ($vars['teaser']) {
354 // Node is displayed as teaser
355 $node_classes[] = 'node-teaser';
357 // Class for node type: "node-type-page", "node-type-story", "node-type-my-custom-type", etc.
358 $node_classes[] = 'node-type-'.
$vars['node']->type
;
359 $vars['node_classes'] = implode(' ', $node_classes); // Concatenate with spaces
363 * Override or insert PHPTemplate variables into the comment templates.
366 * A sequential array of variables to pass to the theme template.
368 function zen_preprocess_comment(&$vars) {
371 // We load the node object that the current comment is attached to
372 $node = node_load($vars['comment']->nid
);
373 // If the author of this comment is equal to the author of the node, we
374 // set a variable so we can theme this comment uniquely.
375 $vars['author_comment'] = $vars['comment']->uid
== $node->uid ? TRUE
: FALSE
;
377 $comment_classes = array();
380 static
$comment_odd = TRUE
;
381 $comment_classes[] = $comment_odd ?
'odd' : 'even';
382 $comment_odd = !$comment_odd;
384 if ($vars['comment']->status
== COMMENT_NOT_PUBLISHED
) {
385 $comment_classes[] = 'comment-unpublished';
386 $vars['unpublished'] = TRUE
;
389 $vars['unpublished'] = FALSE
;
391 if ($vars['author_comment']) {
392 // Comment is by the node author
393 $comment_classes[] = 'comment-by-author';
395 if ($vars['comment']->uid
== 0) {
396 // Comment is by an anonymous user
397 $comment_classes[] = 'comment-by-anon';
399 if ($user->uid
&& $vars['comment']->uid
== $user->uid
) {
400 // Comment was posted by current user
401 $comment_classes[] = 'comment-mine';
403 $vars['comment_classes'] = implode(' ', $comment_classes);
405 // If comment subjects are disabled, don't display 'em
406 if (variable_get('comment_subject_field', 1) == 0) {
412 * Override or insert PHPTemplate variables into the block templates.
415 * A sequential array of variables to pass to the theme template.
417 function zen_preprocess_block(&$vars) {
418 $block = $vars['block'];
420 // Special classes for blocks
421 $block_classes = array();
422 $block_classes[] = 'block-'.
$block->module
;
423 $block_classes[] = 'region-'.
$vars['block_zebra'];
424 $block_classes[] = $vars['zebra'];
425 $block_classes[] = 'region-count-'.
$vars['block_id'];
426 $block_classes[] = 'count-'.
$vars['id'];
427 $vars['block_classes'] = implode(' ', $block_classes);
429 $vars['edit_links'] = '';
430 if (theme_get_setting('zen_block_editing') && user_access('administer blocks')) {
431 // Display 'edit block' for custom blocks
432 if ($block->module
== 'block') {
433 $edit_links[] = l('<span>'.
t('edit block') .
'</span>', 'admin/build/block/configure/'.
$block->module .
'/'.
$block->delta
, array('title' => t('edit the content of this block'), 'class' => 'block-edit'), drupal_get_destination(), NULL
, FALSE
, TRUE
);
435 // Display 'configure' for other blocks
437 $edit_links[] = l('<span>'.
t('configure') .
'</span>', 'admin/build/block/configure/'.
$block->module .
'/'.
$block->delta
, array('title' => t('configure this block'), 'class' => 'block-config'), drupal_get_destination(), NULL
, FALSE
, TRUE
);
440 // Display 'administer views' for views blocks
441 if ($block->module
== 'views' && user_access('administer views')) {
442 $edit_links[] = l('<span>'.
t('edit view') .
'</span>', 'admin/build/views/'.
$block->delta .
'/edit', array('title' => t('edit the view that defines this block'), 'class' => 'block-edit-view'), drupal_get_destination(), 'edit-block', FALSE
, TRUE
);
444 // Display 'edit menu' for menu blocks
445 elseif (($block->module
== 'menu' || ($block->module
== 'user' && $block->delta
== 1)) && user_access('administer menu')) {
446 $edit_links[] = l('<span>'.
t('edit menu') .
'</span>', 'admin/build/menu', array('title' => t('edit the menu that defines this block'), 'class' => 'block-edit-menu'), drupal_get_destination(), NULL
, FALSE
, TRUE
);
448 $vars['edit_links_array'] = $edit_links;
449 $vars['edit_links'] = '<div class="edit">'.
implode(' ', $edit_links) .
'</div>';
454 * Converts a string to a suitable html ID attribute.
456 * http://www.w3.org/TR/html4/struct/global.html#h-7.5.2 specifies what makes a
457 * valid ID attribute in HTML. This function:
459 * - Ensure an ID starts with an alpha character by optionally adding an 'n'.
460 * - Replaces any character except A-Z, numbers, and underscores with dashes.
461 * - Converts entire string to lowercase.
466 * The converted string
468 function zen_id_safe($string) {
469 // Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
470 $string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
471 // If the first character is not a-z, add 'id' in front.
472 if (!ctype_lower($string{0})) { // Don't use ctype_alpha since its locale aware.
473 $string = 'id' .
$string;
479 * Adds a print stylesheet to the page's $head variable.
481 * This is a work-around for a serious bug in IE5 in which it loads print
482 * stylesheets for screen display when using an @import method, Drupal's default
483 * method when using drupal_add_css().
486 * The URL of the print stylesheet
488 * All the rendered links for the $head variable
490 function zen_add_print_css($url) {
492 return drupal_set_html_head(
496 'rel' => 'stylesheet',
497 'href' => $base_path .
$url,
498 'type' => 'text/css',