The next template file we’ll examine is the page.tpl.php file. This template file focuses on the elements that are displayed
between the <body> and </body> tags and includes the HTML structure of the page, including DIV tags and snippets of
PHP code. Ifyou look back at the html.tpl.php template, you’ll see <?php print $page; ?> where the value of $page
is the contents of page.tpl.php.
This template file defines the structure of the page as it is displayed to the user. If you look back at the example that we
started this chapter with, all of the elements that we styled in the Grayscale theme were elements that are rendered by the
page.tpl.php template. In the following code, you’ll see all of the elements that are rendered on the page and the
conditional logic that drives what is displayed on a page and how that page is structured. Like the html.php.tpl file, the
page.tpl.php file consistsof a mixture of HTML and PHP snippets, where the PHP snippets include conditional logic to
determine whether a value is set and displaying the values associated with several variables, where variables may contain
anything from a simple value like “42” to acomplex HTML structure including JavaScript. An example is the first
variable contained in the page.tpl.php file, $logo. This variable holds the HTML necessary to render the site’s logo if
one was supplied, which is why there’s conditional logic to test to seewhether a logo was supplied.
The structure of the page.tpl.php file that resides in /modules/system is as follows:
<div id="page-wrapper"><div id="page">
<div id="header"><div class="section clearfix">
<?php if ($logo): ?>
<a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo">
<img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" />
</a>
<?php endif; ?>
<?php if ($site_name || $site_slogan): ?>
<div id="name-and-slogan">
<?php if ($site_name): ?>
<?php if ($title): ?>
<div id="site-name"><strong>
<a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span>
<?php print $site_name; ?></span></a>
</strong></div>
<?php else: /* Use h1 when the content title is empty */ ?>
<h1 id="site-name">
<a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home">
<span><?php print $site_name; ?></span></a>
</h1>
<?php endif; ?>
<?php endif; ?>
<?php if ($site_slogan): ?>
<div id="site-slogan"><?php print $site_slogan; ?></div>
<?php endif; ?>
</div> <!-- /#name-and-slogan -->
<?php endif; ?>
<?php print render($page['header']); ?>
</div></div> <!-- /.section, /#header -->
<?php if ($main_menu || $secondary_menu): ?>
<div id="navigation"><div class="section">
<?php print theme('links system_main_menu', array('links' => $main_menu, 'attributes' => array('id' => 'main-menu', 'class' => array('links', 'clearfix')), 'heading'=> t('Main menu'))); ?>
<?php print theme('links system_secondary_menu', array('links' => $secondary_menu, 'attributes'
=> array('id' => 'secondary-menu', 'class' => array('links', 'clearfix')), 'heading' => t('Secondary menu'))); ?
</div></div> <!-- /.section, /#navigation -->
<?php endif; ?>
<?php if ($breadcrumb): ?>
<div id="breadcrumb"><?php print $breadcrumb; ?></div>
<?php endif; ?>
<?php print $messages; ?>
<div id="main-wrapper"><div id="main" class="clearfix">
<div id="content" class="column"><div class="section">
<?php if ($page['highlighted']): ?><div id="highlighted"><?php print render($page['highlighted']); ?>
</div><?php endif; ?>
<a id="main-content"></a>
<?php print render($title_prefix); ?>
<?php if ($title): ?><h1 class="title" id="page-title">
<?php print $title;?></h1><?php endif; ?>
<?php print render($title_suffix); ?>
<?php if ($tabs): ?><div class="tabs"><?php print render($tabs); ?></div><?php endif; ?>
<?php print render($page['help']); ?>
<?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
<?php print render($page['content']); ?>
<?php print $feed_icons; ?>
</div></div> <!-- /.section, /#content -->
<?php if ($page['sidebar_first']): ?>
<div id="sidebar-first" class="column sidebar"><div class="section">
<?php print render($page['sidebar_first']); ?></div></div> <!-- /.section, /#sidebar-first -->
<?php endif; ?>
<?php if ($page['sidebar_second']): ?>
<div id="sidebar-second" class="column sidebar"><div class="section">
<?php print render($page['sidebar_second']); ?>
</div></div> <!-- /.section, /#sidebar-second -->
<?php endif; ?>
</div></div> <!-- /#main, /#main-wrapper -->
<div id="footer"><div class="section">
<?php print render($page['footer']); ?>
</div></div> <!-- /.section, /#footer -->
</div></div> <!-- /#page, /#page-wrapper -->
The default variables that are available to the page.tpl.php file are shown in Table 9-3.
Table 9-3. Standard
Variables Available to page.tpl.php
|
|
Variable
|
Description of contents
|
$base_path
|
The base URL path of the Drupal installation; at the
very least, this will always default to /.
|
$directory
|
The directory the template is located in, e.g.,
modules/system or themes/bartik
|
$is_front
|
TRUE if the current
page is the front
page
|
$logged_in
|
TRUE if the user is registered and signed in
|
$is_admin
|
TRUE if the user has
permission to access administration pages
|
$front_page
|
The URL of the front page; use this
instead of $base_path when linking to the front page. This includes the language domain or prefix.
|
$logo
|
The path to the logo image,
as defined in the theme’s configuration
|
$site_name
|
The name of the site,
empty when it has been disabled in theme settings
|
$site_slogan
|
The slogan of the site, empty when
it has been disabled in theme settings
|
$main_menu (array)
|
An array containing the main menu links for the site, if they have been configured
|
$secondary_menu (array)
|
An array containing
the secondary menu
links for the site, if they
have been configured
|
$breadcrumb
|
The breadcrumb trail for the current page
|
$title_prefix
|
An array containing additional output populated
by modules, intended to be displayed in front of the main title tag that appears in the template
|
$title
|
The page title, for use in the actual HTML content
|
$title_suffix (array)
|
An array containing additional output populated by modules, intended to be displayed after the main title tag that appears in the template
|
$message
|
Status and
error messages that should be displayed prominently
|
$tabs (array)
|
Tabs linking to any sub-pages beneath the current page
|
$action_links
(array)
|
Actions local to the page,
such as “Add menu” on the menu administration interface
|
$feed_icons
|
A string of all the feed icons for
the current page
|
$node
|
The node object, if there is an automatically
loaded node associated with the page, and the
node ID is the second argument in the page’s path (e.g., node/12345 and node/12345/revisions, but not comment/reply/12345).
|
The variables $page['help'], $page['highlighted'], $page['content'], $page['sidebar_first'],
$page['sidebar_second'], $page['header'], and $page['footer'] represent regions on the page. A region represents the
physical containers that a site administrator can assign any block-level element to (e.g., the log on form, the search block,
a node, a view, or a menu). If you don’t specify any regions in your theme’s .info file, you get the regions just listed by default. I’ll show you how to create additional regions in the upcoming section that describes how to construct your
theme’s .info file.
The region.tpl.php File
This template file focuses on how regions are displayed on your site. The default region.tpl.php file is pretty simple—essentially just displaying the content that is assigned to a region.
<?php if ($content): ?>
<div class="<?php print $classes; ?>">
<?php print $content; ?>
</div><?php endif; ?>
The variables available to this template file by default are as shown in Table 9-4.
Table 9-4. Standard
Variables Available to region.tpl.php
|
|
Variable
|
Description of contents
|
$content
|
The content
for this region, typically
blocks
|
$classes
|
A string of classes that can be used to style contextually through CSS; it can be manipulated through the variable $classes array from preprocess functions. The default values can be one
or more of the following regions.
The current template type, i.e., “theming
hook”
region-[name]: The name of the region with underscores replaced with dashes; for example, the page_top region
would have a region-page-top
class.
|
$region
|
The name of the region variable as defined in the theme’s .info file
|
$classes
|
Array of HTML class attribute values; it is flattened into a string
within the variable $classes.
|
$is_admin
|
Flags TRUE when the current user is an administrator
|
$is_front
|
Flags TRUE
when presented in the front
page
|
$logged_in
|
Flags true when the current user is a logged-in member
|
The node.tpl.php File
This template file defines how individual nodes are displayed on your site. The default node.tpl.php file can be found in
the modules/node directory on your site. In the following listing, you’ll see elements that are similar to the other templatefiles discussedpreviously; predominantly HTML and PHP snippets that perform conditional logic and printing the value
assigned to variables. In node.tpl.php you’ll also see that the template prints out the value assigned to the variable
$content—which in this case is an individual node. You’ll also note that the template uses “hide” to remove two
elements that would normally be shown on the page when a node is rendered—the comments and links associated with a node. The template accomplishes this throughhide($content['comments']) and hide($content['links']). The reason the
template does this is that we typically want to control where comments and links are rendered when a node is displayed
by hiding them and then later displaying them (using print render($content['comments']) and print render($content
['links'])). You can use this approach to hide any element of anything that would normally be displayed using the hide()
function, and if you want to later show that element, you can use the printrender() function.
The default node.tpl.php file is as follows.
<div id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"
<?php print $attributes; ?>>
<?php print $user_picture; ?>
<?php print render($title_prefix); ?>
<?php if (!$page): ?>
<h2<?php print $title_attributes; ?>><a href="<?php print $node_url; ?>">
<?php print $title; ?></a></h2>
<?php endif; ?>
<?php print render($title_suffix); ?>
<?php if ($display_submitted): ?>
<div class="submitted">
<?php print t('Submitted by !username on !datetime', array('!username' => $name, '!datetime' => $date));?
</div>
<?php endif; ?>
<div class="content"<?php print $content_attributes; ?>>
<?php
// We hide the comments and links now so that we can render them later.
hide($content['comments']); hide($content['links']); print render($content);?>
</div>
<?php print render($content['links']); ?>
<?php print render($content['comments']); ?>
</div>
The variables that are available by default in the node.tpl.php file include those shown in Table 9-5.
Table 9-5. Standard
Variables Available to node.tpl.php
|
|
Variable
|
Description of contents
|
$title
|
The (sanitized) version of the title
|
$content (array)
|
An array of the elements that make
up the node being displayed; if you want
to display the entire node,
use render($content), or as explained previously with the hide() and
show() functions, you can display individual elements of a node object.
|
$user_picture
|
The node author’s picture from user-picture.tpl.php
|
$date
|
Formatted creation date; preprocess functions can reformat it by calling format_date() with the desired parameters on the $created variable.
|
$name
|
Themed username of node author output from theme_username()
|
$node_url
|
Direct
URL of the current node
|
$display_submitted
|
A flag (TRUE or FALSE) that specifies whether submission information should be displayed
|
$classes
|
String of classes that can be used to style contextually
through CSS; it can be manipulated through the variable $classes_array from preprocess functions. The default values can be one or more of the following:
node: The current template type, i.e., “theming hook”
node-[type]: The current node
type. For example,
if the node is a “Blog entry” it would result in “node-blog”. Note that the machine name will often be in a short
form of the human-readable label.
node-teaser: Nodes in teaser form
node-preview: Nodes in preview mode
The following are controlled through
the node publishing
options.
node-promoted: Nodes promoted to the front page
node-sticky: Nodes ordered above other non-sticky nodes in teaser listings
node-unpublished: Unpublished nodes
visible only to administrators
|
$title_prefix (array)
|
An array containing additional output populated
by modules, intended to be displayed in front
of the main title
tag that appears
in the template
|
$title_suffix (array)
|
An array containing additional output
populated by modules,
intended to be displayed immediately after the main title tag that appears in the template
|
$node
|
The full
node object
|
$type
|
Node
type, i.e., story,
page, blog, etc.
|
$comment_count
|
Number of
comments attached to a node
|
$uid
|
The UID of the node’s author
|
$created
|
Time the node was published in Unix timestamp
format
|
$classes_array
|
Array of HTML class attribute values; it is flattened into a string with the variable
$classes.
|
$zebra
|
Outputs either
“even” or “odd”; useful for zebra
striping in teaser listings
|
$id
|
Position of the node; increments each time it’s output
|
$view_mode
|
View mode, e.g., “full” or “teaser”
|
$page
|
Flag for the full
page state (TRUE or FALSE)
|
$promote
|
Flag for front page
promotion state (TRUE or FALSE)
|
$sticky
|
Flags for sticky post
setting
|
$status
|
Flag for published status
|
$comment
|
State of comment settings for the node
|
$readmore
|
Flag that is set to TRUE if the
teaser content of the node cannot
hold the main body
content
|
$is_front
|
Flag that is set to TRUE when the content is presented on the front
page of the site
|
$logged_in
|
Flag that is set to TRUE when the current user is a logged-in member
|
$is_admin
|
Flag that is set to TRUE when the current user is an administrator
|
The field.tpl.php File
This template file is used for theming fields and, unlike the previous templates, isn’t automatically called by Drupal when
rendering fields. If you wish to use this template, you’ll need to copy it from /modules/fields/templates into your theme’s directory.
<div class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
<?php if (!$label_hidden) : ?>
<div class="field-label"<?php print $title_attributes; ?>>
<?php print $label ?>: </div>
<?php endif; ?>
<div class="field-items"<?php print $content_attributes; ?>>
<?php foreach ($items as $delta => $item) : ?>
<div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"
<?php print $item_attributes[$delta]; ?>>
<?php print render($item); ?></div>
<?php endforeach; ?>
</div></div>
The variables that are available by default to the field.tpl.php file are shown in Table 9-6.
Table 9-6. Standard
Variables Available to field.tpl.php
|
|
Variable
|
Description of contents
|
$items
|
An
array of field values; use render() to output them.
|
$label
|
The item’s label
|
$label_hidden
|
A flag (TRUE or FALSE) that can be used to set whether the label should be displayed
|
$classes
|
A string
of classes that can be used to style contextually through CSS; it can be manipulated
through CSS. It can be manipulated through the variable $classes array from preprocess functions. The default
values can be one
or more of the following:
field: The current template type, i.e., “theming hook”
field-name-[field_name]: The current fieldname; for example, if the fieldname is “field_description”, it would result in “field-name-
field-description”.
field-type-[field_type]: The current field type; for example, if the field type
is “text”, it would result
in “field-type-text”.
field-label-[label_display]: The current label position; for example, if the label position is “above”, it would result in “field-label-above”.
|
$element['#object']
|
The entity
that the field is attached to
|
$element['#view_mode']
|
The view mode of the entity that the field is attached to, e.g., “full” or “teaser”
|
$element['#field_name']
|
The field name
|
$element['#field_type']
|
The field type
|
$element['#field_language']
|
The field language
|
$element['#field_translatable']
|
Whether the field
is translatable
|
$element['#label_display']
|
Position of label display: inline, above,
or hidden
|
$field_name_css
|
The CSS-compatible fieldname
|
$field_type_css
|
The CSS-compatible field type
|
$classes_array
|
Array of HTML class
attribute values; it
is flattened into a string with in the variable $classes.
|
The block.tpl.php File
The block-level theming template, block.tpl.php, can be found in the modules/block directory. By this point,
you should be seeing a definitive pattern of how template files are constructed.
<div id="<?php print $block_html_id; ?>" class="<?php print $classes; ?>"<?php print $attributes; ?>>
<?php print render($title_prefix); ?>
<?php if ($block->subject): ?>
<h2<?php print $title_attributes; ?>><?php print $block->subject ?></h2>
<?php endif;?>
<?php print render($title_suffix); ?>
<div class="content"<?php print $content_attributes; ?>>
<?php print $content ?>
</div>
</div>
The variables that are available by default to the block.tpl.php file are shown in Table 9-7.
Table 9-7. Standard
Variables Available to block.tpl.php
|
|
Variable
|
Description of contents
|
$block->subject
|
The block
title
|
$content
|
The block’s content
|
$block->module
|
The module that generated the block
|
$block->delta
|
An ID for the block,
unique within each module
|
$block->region
|
The block
region embedding the current block
|
$classes
|
A string
of classes that can be used to style contextually through CSS; it can be manipulated through the variable $classes array from preprocess functions. The default values
can be one
or more of the following:
block: The current template type, i.e., “theming hook”
block-[module]: The module generating the block; for example,
the user module is responsible for handling the default
user navigation block. In that case, the class would be “block-user”.
|
$title_prefix (array)
|
An array containing additional output populated
by modules, intended to be displayed in front
of the main title
tag that appears
in the template
|
$title_suffix (array)
|
An array containing additional output
populated by modules,
intended to be displayed after the main title tag that appears in the template
|
#classes_array (array)
|
An array of HTML class attribute values; it is flattened into a string
within the variable $classes.
|
$block_zebra
|
Outputs “odd” and “even” dependent on each block region
|
$block_id
|
Dependent on each block region
|
$id
|
Same output as $block_id but independent of any block
region
|
$is_front
|
A flag (TRUE
or FALSE) that indicates whether the current page is the home page of the site
|
$logged_in
|
A flag (TRUE or FALSE) that indicates
whether the visitor is logged
in
|
$is_admin
|
A flag (TRUE or FALSE) that indicates
whether the visitor is logged in as an admin user
|
$block_html_id
|
A valid HTML ID that is guaranteed unique
|
Overriding Template Files
There will likely come a time where you need to change how page.tpl.php, node.tpl.php, or any of the other standard template
files display elements on your site. Let’s step back to our Grayscale theme that we created at the beginning of the chapter and
customize the page.tpl.php file so that when a visitor is on the front page of the site, a welcome message is displayed. If the visitor isn’t on the front page, we won’t display the welcome message. To begin the process, copy the page.tpl.php file from the
modules/system directory into the sites/all/themes/grayscale/templates directory. By copying the file into our theme’s directory, Drupal will now use that version of page.tpl.php rather than the one in the modules/system directory.
The modification that we’ll make is relatively simple. We’ll use the $is_front variable that is exposed to the page template, and usinga conditional phrase, check to see if the visitor is on the front page. If so, we will display a “Welcome to My Site” message at thetop of the page. Open the file and look for the following line:
<div id="content" class="column"><div class="section">
Immediately after that line, insert the following line of code, which uses the $is_front variable to see if the visitor is on the front page of your site, and if so, prints out a welcome message.
<?php
if ($is_front): ?><div id="welcome_message">
<?php print "Welcome to My Site!"; ?></div>
<?php endif; ?>
The result is that “Welcome to My Site!” is printed right under the secondary menu. It is nothing spectacular, but it demonstrates theconcept of leveraging the standard page.tpl.php file and customizing.
You can also create custom .tpl files for specific pages of your site; for example, you could copy page.tpl.php and create a
page--front.tpl.php file. This new template would be applied only to the front page of your site. You can also do the same thing with node.tpl.php. Let’s say you want to theme articles differently than other node types, like a basic page. You can copy
node.tpl.php from the modules/node directory to your theme directory and rename that file to node--article.tpl.php.
This newtemplate file will override the standard node.tpl.php file for any node that is an article. For additional details, visit the
theming guide on Drupal.org at http://drupal.org/documentation/theme.
Other Template Files
You will find several other template files as you browse through the module and theme directories of your site. For example, the
comment module uses comment.tpl.php for rendering comments. The comment module creates a number of variables and exposes those variables to the comment.tpl.php file. The designation of the comment.tpl.php file as the template file for comments is
made through a call to hook_theme() by passing 'template' => 'comment' as one of the values in the array (see the following
code). There’s no need to specify the .tpl.php file extension as Drupal assumes that’s what you mean. I’ll cover additional detailson how to create and expose variables to your template in a bit.
/**
* Implements hook_theme().
*/
function comment_theme() { return array('comment_block' => array( 'variables' => array(),),
'comment_preview' => array('variables' => array('comment' => NULL),),'comment' => array( 'template' => 'comment',
'render element' => 'elements',),'comment_post_forbidden' => array( 'variables' => array('node' => NULL),),
'comment_wrapper' => array( 'template' => 'comment-wrapper', 'render element' => 'content',),);}
Introducing the theme() Function
When Drupal wants to generate some HTML output for a them able item (like a node, a block, a breadcrumb trail, a comment, or a user signature), it looks for a theme function or template file that will generate HTML for that item. Almost all parts of Drupal are
them able, which means you can override the actual HTML that is generated for that item. We’ll look at some examples soon.
An Overview of How theme() Works
Here’s a high-level overview of what happens when a simple node page, such as http://example.com/?q=node/3, is displayed:
1. Drupal’s menu system receives the request and hands off control to the node module.
2. After building the node data structure, theme('node', $variables) is called. This finds the correct theme function or template
file, defines variables that the template may use, and applies the template, resulting in finished HTML for the node. (If multiple
nodes are being displayed, as happens with a blog, this process happens for each node.)
3. An HTML structure is returned (you can see it as the $return variable in index.php)
and passed to the theme() function again as theme('page', $return).
4. Before processing the page template, Drupal does some preprocessing, such as discovering which regions are available and
which blocks should be shown in each region. Each block is turned into HTML by calling theme('blocks', $region), which
defines variables and applies a block template. You should be starting to see a pattern here.
5. Finally, Drupal defines variables for the page template to use and applies the page template.
You should be able to discern from the preceding list that the theme() function is very important to Drupal. It is in charge of
running preprocessing functions to set variables that will be used in templates and dispatching a theme call to the correct function or finding the appropriate template file. The result is HTML. We will take an in-depth look at how this function works later.
Right now, it is enough to understand that when Drupal wants to turn a node into HTML, theme('node', $variables = array()) is
called. Depending on which theme is enabled, the theme_node() function will generate the HTML or a template file named
node.tpl.php will do it. This process can be overridden at many levels. For example, themes can override built-in theme
functions, so when theme('node', $variables = array()) is called, a function called grayscale_node() might handle it instead of theme_node(). Template files have naming conventions that we’ll explore later too, so that a node--story.tpl.php
template file would target only nodes of type story.
Overriding Themable Items
As you’ve seen, themable items are identifiable by their function names, which all begin with theme_, or by the presence of a
template file (see http://api.drupal.org/api/group/themeable/7 for a list of all standard themable items). This naming convention
givesDrupal the ability to create a function-override mechanism for all themable functions. Designers can instruct Drupal to
execute an alternative function, which takes precedence over the theme functions that module developers expose or over
Drupal’s default templatefiles. For example, let’s examine how this process works when building the site’s breadcrumb trail.
Open includes/theme.inc, and examine the functions inside that file. Many functions in there begin with theme_, which is the tell
tale sign that they can be overridden. In particular, let’s examine theme_breadcrumb():
/**
* Returns HTML for a breadcrumb trail.
*
* @param $variables
* An associative array containing:
* - breadcrumb: An array containing the breadcrumb links.
*/
function theme_breadcrumb($variables) {
$breadcrumb = $variables['breadcrumb'];
if (!empty($breadcrumb)) {
// Provide a navigational heading to give context for breadcrumb links to
// screen-reader users. Make the heading invisible with .element-invisible.
$output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';
$output .= '<div class="breadcrumb">' . implode(' » ', $breadcrumb) . '</div>'; return $output;
}}
This function controls the HTML for the breadcrumb navigation within Drupal. Currently, it adds a right-pointing double-arrow separator between each item of the trail. Suppose you want to change the div tag to a span and use an asterisk (*) in stead of a double arrow. How should you go about it? One solution would be to edit this function within theme.inc, save it, and
call it good. (No! No! Do not do this!) There are better ways.
Have you ever seen how these theme functions are invoked within core? You’ll never see theme_breadcrumb() called directly.
Instead, it’s always wrapped inside the theme() helper function. You’d expect the function to be called as follows:
theme_breadcrumb($variables)
But it’s not. Instead, you’ll see developers use the following invocation:
theme('breadcrumb', $variables);
This generic theme() function is responsible for initializing the theme layer and dispatching function calls to the appropriate places, bringing us to the more elegant solution to our problem. The call to theme() instructs Drupal to look for the breadcrumbfunctions
in the following order. Assuming the theme you’re using is Grayscale, which is a PHPTemplate based theme, Drupal would look for the following (we’ll ignore breadcrumb.tpl.php for a moment):
grayscale_breadcrumb() sites/all/themes/grayscale/breadcrumb.tpl.php theme_breadcrumb()
Easy—your theme’s template.php file is the place to override Drupal’s default theme functions, and intercept and create
custom variables to pass along to template files.
To tweak the Drupal breadcrumbs, create (or update if you created one in the previous example on setting theme options) a sites/all/themes/grayscale/template.php file, and copy and paste the theme_breadcrumb() function in there from theme.inc. Besure to
include the starting <?php tag. Also, rename the function from theme_breadcrumb to grayscale_breadcrumb.
Next, click the Modules link in the menu at the top of the page to rebuild the theme registry so Drupal will detect your new
function.
<?php
/**
* Returns HTML for a breadcrumb trail.
*
* @param $variables
* An associative array containing:
* - breadcrumb: An array containing the breadcrumb links.
*/
function grayscale_breadcrumb($variables) {
$breadcrumb = $variables['breadcrumb'];
if (!empty($breadcrumb)) {
// Provide a navigational heading to give context for breadcrumb links to
// screen-reader users. Make the heading invisible with .element-invisible.
$output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';
$output .= '<div class="breadcrumb">' . implode(' * ', $breadcrumb) . '</div>'; return $output;}}
Next, if you’re using the Grayscale theme, add the following CSS to css/style.css.
.breadcrumb {
margin-top:10px; clear:both; height: 15px;
background-color: #fff; width: 960px;
margin-right: auto; margin-left: auto;
}
The next time Drupal is asked to format the breadcrumb trail, it’ll find your function first and use it instead of the default theme_breadcrumb() function, and breadcrumbs will contain your asterisks instead of Drupal’s double arrows. Pretty slick, eh? By passingall theme function calls through the theme() function, Drupal will always check if the current theme has overridden any of the
theme_ functions and call those instead.
Overriding with Template Files
If you’re working with a designer, telling him or her to “just go in the code and find the themable functions to override” is out of the question. Fortunately, there’s another way to make this more accessible to designer types. You can instead mapthemable items to their own template files. I’ll demonstrate with our handy breadcrumb example.
Before we begin, make sure that no theme function is overriding theme_breadcrumb(). So if you created a grayscale_
breadcrumb() function in your theme’s template.php file in the preceding section, comment it out. Then, create a file atsites/all/
themes/grayscale/breadcrumb.tpl.php. This is the new template file for breadcrumbs. Because we wanted to change the <div> tagto a <span> tag, go ahead and populate the file with the following:
<?php if (!empty($breadcrumb)): ?>
<span class="breadcrumb"><?php print implode(' ! ', $breadcrumb) ?></span>
<?php endif; ?>
That’s easy enough for a designer to edit. Now you need to let Drupal know to call this template file when looking to render its
breadcrumbs. To do that, rebuild the theme registry by clearing the site’s cache files. To clear the cache, visitadmin/config/development/performance and click the “Clear all caches” button. While rebuilding the theme registry, Drupal will discover your
breadcrumb.tpl.php file and map the breadcrumb themable item to that template file. Now you know how to override any them
able item in Drupal in a way that will make your designers happy.
Adding and Manipulating Template Variables
In this example, we’ll look at manipulating or adding variables that are being passed into page and node templates. Let’s continue
with our example of using the breadcrumb trail. First, let’s modify sites/all/themes/grayscale/breadcrumb.tpl.php to use
avariable called $breadcrumb_delimiter for the breadcrumb delimiter:
<?php if (!empty($breadcrumb)): ?>
<span class="breadcrumb">
<?php print implode(' '. $breadcrumb_delimiter .' ', $breadcrumb) ?>
</span>
<?php endif; ?>
To set the value of $breadcrumb_delimiter, one option would be in a module. We could create sites/all/modules/crumbpicker.
info:
name = Breadcrumb Picker
description = Provide a character for the breadcrumb trail delimiter.
package = Pro Drupal Development core = 7.x
The module at sites/all/modules/crumbpicker.module would be tiny:
<?php
/**
* @file
* Provide a character for the breadcrumb trail delimiter.
*/
/**
* Implements $modulename_preprocess_$hook().
*/
function crumbpicker_preprocess_breadcrumb(&$variables) {
$variables['breadcrumb_delimiter'] = '/';}
After enabling the module, your breadcrumb trail should look like Home / Administer / Site building.
The preceding example illustrates a module setting a variable for a template file to use. But there must be an easier way than
creating a module every time a variable needs to be set. Sure enough, it’s template.php to the rescue. Let’s write a function to
set the breadcrumb delimiter. Add the following to your theme’s template.php file:
/**
* Implements $themeenginename_preprocess_$hook().
* Variables we set here will be available to the breadcrumb template file.
*/
function grayscale_preprocess_breadcrumb(&$variables) {
$variables['breadcrumb_delimiter'] = '#';
}
That’s easier than creating a module, and frankly, the module approach is usually best for existing modules to provide variables to
templates; modules are not generally written solely for this purpose. Now, we have a module providing a variable and a function
in template.php providing a variable. Which one will actually be used
Actually, a whole hierarchy of preprocess functions run in a certain order, each one with the potential to overwrite variables that
have been defined by previous preprocess functions. In the preceding example, the breadcrumb delimiter will be # because
phptemplate_preprocess_breadcrumb() will be executed after crumbpicker_preprocess_breadcrumb(), and thus its variable
assignment will override any previous variable assignment for $breadcrumb_delimiter. For the theming of a breadcrumb trail using the Grayscale theme, the actual order of precedence (from first called to last called) would be:
template_preprocess() template_preprocess_breadcrumb() crumbpicker_preprocess() crumbpicker_preprocess_breadcrumb() phptemplate_preprocess()phptemplate_preprocess_breadcrumb() grayscale_preprocess() grayscale_preprocess_breadcrumb() template_process()
Thus grayscale_preprocess_breadcrumb() can override any variable that has been set; it’s called last before the variables are
handed to the template file. Calling all those functions when only some of them are implemented may seem to you like a waste
of time. If so, you are correct, and when the theme registry is built, Drupal determines which functions are implemented and callsonly those.
Using the Theme Developer Module
An invaluable resource for working with Drupal themes is the theme developer module. It is part of devel.module and can be
downloaded at http://drupal.org/project/devel_themer. The theme developer module lets you point to an element on a page and
discover which templates or theme functions were involved in creating that element as well as the variables (and their values)
available to that element.
Summary
After reading this chapter, you should be able to
• Create template files.
• Override theme functions.
• Manipulate template variables.
• Create new page regions for blocks.
For additional details about theming in Drupal 7, please check the theme handbook page at http://drupal.org/documentation/theme.
Không có nhận xét nào:
Đăng nhận xét