Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
74
Добавлен:
14.03.2016
Размер:
13 Мб
Скачать
☆

CHAPTER 9 ■ THE THEME SYSTEM

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 details on 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 themable 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 themable, which means you can override the actual HTML that is generated for that item. We’ll look at some examples soon.

■ Tip For a list of themable items in Drupal, see http://api.drupal.org/api/group/themeable/7.

215

CHAPTER 9 ■ THE THEME SYSTEM

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 gives Drupal 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 template files. 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 telltale sign that they can be overridden. In particular, let’s examine theme_breadcrumb():

216

CHAPTER 9 ■ THE THEME SYSTEM

/**

*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 (*) instead 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 breadcrumb functions 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.

217

CHAPTER 9 ■ THE THEME SYSTEM

■ Note Don’t use Bartik as the active theme when doing these exercises, since Bartik already has a template.php file. Use Grayscale or Stark instead.

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. Be sure 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 passing all 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.

218

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]