Updated README and zen_classic with new STARTERKIT verbiage.
[project/zen.git] / template.php
CommitLineData
0c91c6b4 1<?php
8c1acf80 2// $Id$
0c91c6b4
JR
3
4/**
8c1acf80
AB
5 * @file
6 * File which contains theme overrides for the Zen theme.
0ba252e1 7 *
7081db43 8 * ABOUT
960bac1c 9 *
0ba252e1
J
10 * The template.php file is one of the most useful files when creating or
11 * modifying Drupal themes. You can add new regions for block content, modify or
12 * override Drupal's theme functions, intercept or make additional variables
13 * available to your theme, and create custom PHP logic. For more information,
14 * please visit the Theme Developer's Guide on Drupal.org:
15 * http://drupal.org/theme-guide
2502b3b4
J
16 *
17 * NOTE ABOUT ZEN'S TEMPLATE.PHP FILE
18 *
19 * The base Zen theme is designed to be easily extended by its sub-themes. You
20 * shouldn't modify this or any of the CSS or PHP files in the root zen/ folder.
21 * See the online documentation for more information:
22 * http://drupal.org/node/193318
960bac1c
TS
23 */
24
0ba252e1 25
cc27397e
J
26/*
27 * To make this file easier to read, we split up the code into managable parts.
28 * Theme developers are likely to only be interested in functions that are in
29 * this main template.php file.
30 */
31
32// Sub-theme support
33include_once 'template-subtheme.php';
34
d26b527c
J
35// Initialize theme settings
36include_once 'theme-settings-init.php';
37
cc27397e
J
38// Tabs and menu functions
39include_once 'template-menus.php';
40
25a65128 41
0ba252e1 42/**
25a65128 43 * Declare the available regions implemented by this theme.
960bac1c 44 *
0ba252e1
J
45 * Regions are areas in your theme where you can place blocks. The default
46 * regions used in themes are "left sidebar", "right sidebar", "header", and
47 * "footer", although you can create as many regions as you want. Once declared,
48 * they are made available to the page.tpl.php file as a variable. For instance,
49 * use <?php print $header ?> for the placement of the "header" region in
50 * page.tpl.php.
51 *
52 * By going to the administer > site building > blocks page you can choose
53 * which regions various blocks should be placed. New regions you define here
54 * will automatically show up in the drop-down list by their human readable name.
55 *
960bac1c 56 * @return
0ba252e1
J
57 * An array of regions. The first array element will be used as the default
58 * region for themes. Each array element takes the format:
59 * variable_name => t('human readable name')
960bac1c 60 */
6ff9b7bb 61function zen_regions() {
2502b3b4 62 // Allow a sub-theme to define its own regions.
3e60ccbd
J
63 global $theme_key;
64 if ($theme_key != 'zen') {
65 $function = str_replace('-', '_', $theme_key) .'_regions';
66 if (function_exists($function)) {
15cfacdb 67 return $function();
3e60ccbd
J
68 }
69 }
70
0c91c6b4 71 return array(
88b869ae
J
72 'left' => t('left sidebar'),
73 'right' => t('right sidebar'),
74 'navbar' => t('navigation bar'),
75 'content_top' => t('content top'),
76 'content_bottom' => t('content bottom'),
77 'header' => t('header'),
78 'footer' => t('footer'),
79 'closure_region' => t('closure'),
0c91c6b4 80 );
0ba252e1
J
81}
82
960bac1c 83
908497bd
J
84/**
85 * Return a themed breadcrumb trail.
86 *
87 * @param $breadcrumb
88 * An array containing the breadcrumb links.
89 * @return
90 * A string containing the breadcrumb output.
91 */
7d803240
J
92function phptemplate_breadcrumb($breadcrumb) {
93 $show_breadcrumb = theme_get_setting('zen_breadcrumb');
94 $show_breadcrumb_home = theme_get_setting('zen_breadcrumb_home');
95 $breadcrumb_separator = theme_get_setting('zen_breadcrumb_separator');
25a65128
J
96 $trailing_separator = theme_get_setting('zen_breadcrumb_trailing') ? $breadcrumb_separator : '';
97
98 // Determine if we are to display the breadcrumb
7d803240
J
99 if ($show_breadcrumb == 'yes' || $show_breadcrumb == 'admin' && arg(0) == 'admin') {
100 if (!$show_breadcrumb_home) {
25a65128 101 // Optionally get rid of the homepage link
7d803240
J
102 array_shift($breadcrumb);
103 }
104 if (!empty($breadcrumb)) {
25a65128
J
105 // Return the breadcrumb with separators
106 return '<div class="breadcrumb">'. implode($breadcrumb_separator, $breadcrumb) ."$trailing_separator</div>";
7d803240 107 }
908497bd 108 }
25a65128 109 // Otherwise, return an empty string
7d803240 110 return '';
908497bd 111}
0ba252e1
J
112
113
114/*
7081db43 115 * CREATE OR MODIFY VARIABLES FOR YOUR THEME
960bac1c 116 *
0ba252e1
J
117 * The most powerful function available to themers is _phptemplate_variables().
118 * It allows you to pass newly created variables to different template (tpl.php)
119 * files in your theme. Or even unset ones you don't want to use.
960bac1c 120 *
0ba252e1
J
121 * It works by switching on the hook, or name of the theme function, such as:
122 * - page
123 * - node
124 * - comment
125 * - block
960bac1c 126 *
0ba252e1
J
127 * By switching on this hook you can send different variables to page.tpl.php
128 * file, node.tpl.php (and any other derivative node template file, like
129 * node-forum.tpl.php), comment.tpl.php, and block.tpl.php.
960bac1c
TS
130 */
131
0ba252e1 132
960bac1c
TS
133/**
134 * Intercept template variables
135 *
136 * @param $hook
25a65128 137 * The name of the theme function being executed (name of the .tpl.php file)
960bac1c 138 * @param $vars
25a65128
J
139 * A copy of the array containing the variables for the hook.
140 * @return
141 * The array containing additional variables to merge with $vars.
960bac1c 142 */
0ba252e1
J
143function _phptemplate_variables($hook, $vars = array()) {
144 // Get the currently logged in user
15fe5a55 145 global $user, $theme_key;
089b43c7 146
0ba252e1
J
147 // Set a new $is_admin variable. This is determined by looking at the
148 // currently logged in user and seeing if they are in the role 'admin'. The
149 // 'admin' role will need to have been created manually for this to work this
150 // variable is available to all templates.
089b43c7
JR
151 $vars['is_admin'] = in_array('admin', $user->roles);
152
c4bd1c00
J
153 // Send a new variable, $logged_in, to tell us if the current user is
154 // logged in or out. An anonymous user has a user id of 0.
155 $vars['logged_in'] = ($user->uid > 0) ? TRUE : FALSE;
156
960bac1c 157 switch ($hook) {
39fa6d35 158 case 'page':
15fe5a55 159 global $theme;
0ba252e1 160
8afee8f6
J
161 // These next lines add additional CSS files and redefine
162 // the $css and $styles variables available to your page template
163 if ($theme == $theme_key) { // If we're in the main theme
164 // Load the stylesheet for a liquid layout
dbffdf9b 165 if (theme_get_setting('zen_layout') == 'border-politics-liquid') {
8afee8f6
J
166 drupal_add_css($vars['directory'] .'/layout-liquid.css', 'theme', 'all');
167 }
168 // Or load the stylesheet for a fixed width layout
169 else {
170 drupal_add_css($vars['directory'] .'/layout-fixed.css', 'theme', 'all');
171 }
88b869ae 172 drupal_add_css($vars['directory'] .'/html-elements.css', 'theme', 'all');
1c3aa4dd 173 drupal_add_css($vars['directory'] .'/tabs.css', 'theme', 'all');
88b869ae 174 drupal_add_css($vars['directory'] .'/zen.css', 'theme', 'all');
a3e25d2e
J
175 // Avoid IE5 bug that always loads @import print stylesheets
176 $vars['head'] = zen_add_print_css($vars['directory'] .'/print.css');
9935964e 177 }
d9439c8b
J
178 // Optionally add the block editing styles.
179 if (theme_get_setting('zen_block_editing')) {
180 drupal_add_css($vars['directory'] .'/block-editing.css');
181 }
8afee8f6
J
182 // Optionally add the wireframes style.
183 if (theme_get_setting('zen_wireframes')) {
184 drupal_add_css($vars['directory'] .'/wireframes.css', 'theme', 'all');
185 }
186 $vars['css'] = drupal_add_css();
187 $vars['styles'] = drupal_get_css();
0ba252e1 188
a567dd64
J
189 // Allow sub-themes to have an ie.css file
190 $vars['subtheme_directory'] = path_to_subtheme();
191
a11e2675
J
192 // Don't display empty help from node_help().
193 if ($vars['help'] == "<div class=\"help\"><p></p>\n</div>") {
194 $vars['help'] = '';
195 }
196
0ba252e1
J
197 // Classes for body element. Allows advanced theming based on context
198 // (home page, node of certain type, etc.)
894a5a6d 199 $body_classes = array();
894a5a6d
JR
200 $body_classes[] = ($vars['is_front']) ? 'front' : 'not-front';
201 $body_classes[] = ($vars['logged_in']) ? 'logged-in' : 'not-logged-in';
202 if ($vars['node']->type) {
0ba252e1 203 // If on an individual node page, put the node type in the body classes
f886f85d 204 $body_classes[] = 'node-type-'. $vars['node']->type;
894a5a6d 205 }
74cd0291 206 if ($vars['sidebar_left'] && $vars['sidebar_right']) {
8740bfbd 207 $body_classes[] = 'two-sidebars';
74cd0291
J
208 }
209 elseif ($vars['sidebar_left']) {
8740bfbd 210 $body_classes[] = 'one-sidebar sidebar-left';
74cd0291
J
211 }
212 elseif ($vars['sidebar_right']) {
8740bfbd
J
213 $body_classes[] = 'one-sidebar sidebar-right';
214 }
215 else {
216 $body_classes[] = 'no-sidebars';
894a5a6d 217 }
b0bce55d
J
218 if (!$vars['is_front']) {
219 // Add unique classes for each page and website section
b58a7acf 220 $path = drupal_get_path_alias($_GET['q']);
b0bce55d 221 list($section,) = explode('/', $path, 2);
b58a7acf 222 $body_classes[] = zen_id_safe('page-'. $path);
b0bce55d 223 $body_classes[] = zen_id_safe('section-'. $section);
26c710ba
J
224 if (arg(0) == 'node') {
225 if (arg(1) == 'add') {
226 if ($section == 'node') {
227 array_pop($body_classes); // Remove 'section-node'
228 }
229 $body_classes[] = 'section-node-add'; // Add 'section-node-add'
230 }
231 elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
232 if ($section == 'node') {
233 array_pop($body_classes); // Remove 'section-node'
234 }
235 $body_classes[] = 'section-node-'. arg(2); // Add 'section-node-edit' or 'section-node-delete'
236 }
237 }
b0bce55d 238 }
26c710ba 239 $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
0ba252e1 240
39fa6d35 241 break;
0ba252e1 242
39fa6d35 243 case 'node':
0ba252e1 244 // Special classes for nodes
4aa359bc 245 $node_classes = array();
4dd0f1bf 246 if ($vars['sticky']) {
0ba252e1 247 $node_classes[] = 'sticky';
4dd0f1bf
JR
248 }
249 if (!$vars['node']->status) {
0ba252e1 250 $node_classes[] = 'node-unpublished';
981ee087
J
251 $vars['unpublished'] = TRUE;
252 }
253 else {
254 $vars['unpublished'] = FALSE;
4dd0f1bf 255 }
3133c27b 256 if ($vars['node']->uid && $vars['node']->uid == $user->uid) {
0ba252e1 257 // Node is authored by current user
3133c27b
JR
258 $node_classes[] = 'node-mine';
259 }
6566ad23
J
260 if ($vars['teaser']) {
261 // Node is displayed as teaser
262 $node_classes[] = 'node-teaser';
263 }
8740bfbd 264 // Class for node type: "node-type-page", "node-type-story", "node-type-my-custom-type", etc.
f886f85d 265 $node_classes[] = 'node-type-'. $vars['node']->type;
26c710ba 266 $vars['node_classes'] = implode(' ', $node_classes); // Concatenate with spaces
0ba252e1 267
39fa6d35 268 break;
0ba252e1 269
39fa6d35 270 case 'comment':
0ba252e1 271 // We load the node object that the current comment is attached to
39fa6d35 272 $node = node_load($vars['comment']->nid);
0ba252e1
J
273 // If the author of this comment is equal to the author of the node, we
274 // set a variable so we can theme this comment uniquely.
39fa6d35 275 $vars['author_comment'] = $vars['comment']->uid == $node->uid ? TRUE : FALSE;
67b2f71a 276
4aa359bc 277 $comment_classes = array();
0ba252e1
J
278
279 // Odd/even handling
f0041df5
JR
280 static $comment_odd = TRUE;
281 $comment_classes[] = $comment_odd ? 'odd' : 'even';
282 $comment_odd = !$comment_odd;
0ba252e1 283
67b2f71a 284 if ($vars['comment']->status == COMMENT_NOT_PUBLISHED) {
0ba252e1 285 $comment_classes[] = 'comment-unpublished';
981ee087
J
286 $vars['unpublished'] = TRUE;
287 }
288 else {
289 $vars['unpublished'] = FALSE;
67b2f71a
JR
290 }
291 if ($vars['author_comment']) {
0ba252e1
J
292 // Comment is by the node author
293 $comment_classes[] = 'comment-by-author';
67b2f71a
JR
294 }
295 if ($vars['comment']->uid == 0) {
0ba252e1
J
296 // Comment is by an anonymous user
297 $comment_classes[] = 'comment-by-anon';
67b2f71a 298 }
3133c27b 299 if ($user->uid && $vars['comment']->uid == $user->uid) {
0ba252e1
J
300 // Comment was posted by current user
301 $comment_classes[] = 'comment-mine';
3133c27b 302 }
67b2f71a 303 $vars['comment_classes'] = implode(' ', $comment_classes);
0ba252e1
J
304
305 // If comment subjects are disabled, don't display 'em
67b2f71a
JR
306 if (variable_get('comment_subject_field', 1) == 0) {
307 $vars['title'] = '';
308 }
0ba252e1 309
39fa6d35 310 break;
39bce758
J
311
312 case 'block':
c4bd1c00
J
313 $block = $vars['block'];
314
315 // Special classes for blocks
316 $block_classes = array();
b30bb468 317 $block_classes[] = 'block-'. $block->module;
c4bd1c00
J
318 $block_classes[] = 'region-'. $vars['block_zebra'];
319 $block_classes[] = $vars['zebra'];
320 $block_classes[] = 'region-count-'. $vars['block_id'];
321 $block_classes[] = 'count-'. $vars['id'];
322 $vars['block_classes'] = implode(' ', $block_classes);
323
d9439c8b
J
324 if (theme_get_setting('zen_block_editing') && user_access('administer blocks')) {
325 // Display 'edit block' for custom blocks
326 if ($block->module == 'block') {
327 $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);
328 }
329 // Display 'configure' for other blocks
330 else {
331 $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);
332 }
333
334 // Display 'administer views' for views blocks
335 if ($block->module == 'views' && user_access('administer views')) {
336 $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);
337 }
338 // Display 'edit menu' for menu blocks
339 elseif (($block->module == 'menu' || ($block->module == 'user' && $block->delta == 1)) && user_access('administer menu')) {
340 $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);
341 }
342 $vars['edit_links_array'] = $edit_links;
343 $vars['edit_links'] = '<div class="edit">'. implode(' ', $edit_links) .'</div>';
344 }
345
39bce758 346 break;
960bac1c 347 }
0ba252e1 348
5663e4da
J
349 // Allow a sub-theme to add or alter variables.
350 $function = $theme_key .'_preprocess_'. $hook;
351 if (function_exists($function)) {
352 $function($vars);
353 }
354 else {
355 $function = 'phptemplate_preprocess_'. $hook;
356 if (function_exists($function)) {
357 $function($vars);
358 }
359 }
360
15fe5a55
J
361 // The following is a deprecated function included for backwards compatibility
362 // with Zen 5.x-0.8 and earlier. New sub-themes should not use this function.
9935964e
JR
363 if (function_exists('zen_variables')) {
364 $vars = zen_variables($hook, $vars);
365 }
0ba252e1 366
2502b3b4 367 _zen_hook($hook); // Add support for sub-theme template files.
027e9d2a 368
960bac1c
TS
369 return $vars;
370}
4dd0f1bf
JR
371
372/**
0ba252e1
J
373 * Converts a string to a suitable html ID attribute.
374 *
375 * - Preceeds initial numeric with 'n' character.
e9b12d63 376 * - Replaces any character except A-Z, numbers, and underscores with dashes.
0ba252e1
J
377 * - Converts entire string to lowercase.
378 * - Works for classes too!
379 *
2502b3b4 380 * @param $string
0ba252e1
J
381 * The string
382 * @return
383 * The converted string
384 */
4dd0f1bf
JR
385function zen_id_safe($string) {
386 if (is_numeric($string{0})) {
0ba252e1 387 // If the first character is numeric, add 'n' in front
4dd0f1bf
JR
388 $string = 'n'. $string;
389 }
e9b12d63 390 return strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
9935964e 391}
a3e25d2e
J
392
393/**
394 * Adds a print stylesheet to the page's $head variable.
395 *
396 * This is a work-around for a serious bug in IE5 in which it loads print
397 * stylesheets for screen display when using an @import method, Drupal's default
398 * method when using drupal_add_css().
399 *
2502b3b4 400 * @param $url
a3e25d2e
J
401 * The URL of the print stylesheet
402 * @return
403 * All the rendered links for the $head variable
404 */
405function zen_add_print_css($url) {
406 global $base_path;
407 return drupal_set_html_head(
408 '<link'.
409 drupal_attributes(
410 array(
411 'rel' => 'stylesheet',
412 'href' => $base_path . $url,
413 'type' => 'text/css',
414 'media' => 'print',
415 )
416 ) ." />\n"
417 );
418}