Documente Academic
Documente Profesional
Documente Cultură
Drupal
Content
Absolute minimal requirements for a theme page 2
What is a themeable function and The Trick page 7
Template files you don’t need to tell Drupal about page 13
Template files you need to tell Drupal about page 15
When not to use template files page 15
PHP code style in template files page 16
Anatomy of a page[-something].tpl.php file page 17
Anatomy of a node[-something].tpl.php file page 22
What does a page[-something].tpl.php file know page 26
What does a node[-something].tpl.php file know page 29
How does one make a *.tpl.php file more knowledgeable page 31
Theming a ‘view’ page 34
CCK — what the hell is happening page 36
Theming precedence — the rules page 38
Adding regions — semantic or not page 40
Good design — proximity and strong alignment page 42
Browser-side theming : style.css page 48
Printer-friendly all the way page 56
Styling using jquery page 57
eet
All about menus page 58 Lean and sw
Theming the node form page 59
1/ea » Absolute minimal requirements for a theme
Since Drupal 4.7, the default theming engine that ships with Drupal is the PHPTemplate
engine. That engine is comprised of phptemplate.engine (the engine itself, written in
php) and a collection of default template files written in XHTML with embedded php.
You can find all these files in the folder themes/engines/phptemplate. The sole require-
ment for a PHPTemplate theme to show up on the page admin/build/themes is : *
Answer : 3. Each theme gets its name from its folder’s name, i.e. fuzzyland, cleancut
and crushed. The theme cleancut provides no template file. However, it’s a theme in its
own right (as per our second requirement), and it uses the page.tpl.php file of the theme
fuzzyland. It’s not using the fuzzyland style.css file though ; it uses the style.css
stylesheet that’s contained in its own folder, the “cleancut” folder. Conversely, fuzzyland
is not using the stylesheet of cleancut, even if it has no style.css file of its own.
The important thing to remember here is this : there can only be zero or one style.css file
per theme, and that stylesheet is to be found in that theme folder (and not in a subfolder).
Also, the style.css file — if it exists — will be linked automatically by typing the following
line of code in the page.tpl.php template file used by the theme :
<head> ... <?php print $styles ?> ... <head>
And as for themes based on an alternate style.css file, like the minnelli theme, nothing
special has to be done : we just have to place that stylesheet in a subfolder and we’re done.
Open that file and look up the function that includes that code. That function is :
phptemplate_page($content, $show_blocks = TRUE). This is the function that calls a
template file of the form : page[-something].tpl.php, and passes to it all variables needed
to build a Drupal page. In that function, the phptemplate engine is preparing an array
of values to pass to the appropriate page template. Look at all the variables it’s preparing
for that page template, besides $styles. Try and understand what’s going on here :
$styles is made available to any template file of the form page[-something].tpl.php. So,
if we created any of these templates : page.tpl.php, page-node.tpl.php, page-front.tpl.php
and page-node-45.tpl.php, the variable would be available to all four files. Later on, we’ll
see how these other page template files, such as page-front.tpl.php, can serve us. For now,
remember this : we are only required to provide a page.tpl.php file, or a style.css file if a
parent theme exists with a page.tpl.php file. Any other template file is extra.
The drupal_get_css() function is defined in includes/common.inc, at line 1448. How does
it work ? It returns the XHTML that links in all stylesheets used by activated modules,
as well as the default theme’s style.css file. Take a moment to consult the Drupal API.
The function is said to return a “themed representation of all stylesheets that should
be attached to the page. It loads the CSS in order, with ‘core’ CSS first, then ‘module’
CSS, then ‘theme’ CSS files. This ensures proper cascading of styles for easy overriding
in modules and themes.” The expression themed representation here means XHTML.
Theming is nothing else than writing XHTML.
What the API description is not saying though is that in Drupal 5 the function may serve
cached CSS, an “aggregation” of CSS
rules from many different *.css files,
served in one block, from a file.
While we’re creating a theme, we
really want to disable that. For as
long as we’re making modifications
to our style.css file, we cannot use
any cached version of it. To disable
that caching feature (or enable it), go
to admin/settings/performance.
</div>
collapse.js and textarea.js!
<div id="main_content">
<p>Welcome to my new theme which is in <?php print $directory ?>.
<?php if ($layout == 'left' or $layout == 'both') : print 'We have some
blocks to show on the left.'; endif; ?></p>
<?php if ($title) : print '<h1>'. $title .'</h1>'; endif; ?>
$is_front
</div> How did phptemplate.engine get all these variables ? What do these variables stand
for? Look at the function phptemplate_page($content, $show_blocks = TRUE).
</body> We’ll explain it all later in the section “what does page[-something].tpl.php know”.
</html>
http://www.11heavens.com/theming-drupal © 2007 Caroline Hill
page
Backing up your database and phpMyAdmin
Before you make your new theme your default theme in q=admin/build/themes, you should
backup your Drupal database. Let’s say you’ve forgotten to record that snapshot of your
database, and things go very wrong, for example you get the infamous “php blank screen of
death”, and you are unable to fix the error and you want to go back in time. In that case,
PhpMyAdmin becomes your best friend. In the database table {system}, two entries get a
status = 1 for a default phpTemplate theme :
themes/engines/phptemplate/phptemplate.engine and
For the theme funky
themes/funky/page.tpl.php
If your theme happens to be a style.css file, such as for the minnelli theme, then you get
these three entries instead :
themes/engines/phptemplate/phptemplate.engine and
For the theme funkier, which
themes/funky/page.tpl.php and uses the page.tpl.php file of its
themes/funky/funkier/style.css ‘parent’ theme.
Change the status of either themes/funky/page.tpl.php, or themes/funky/page.
tpl.php and themes/funky/funkier/style.css to 0, then choose an alternate page
template that you know work, such as themes/garland/page.tpl.php, and make that
other theme your new default theme by changing the status of its page template to 1. Then
refresh your web page.
In an ideal world, when things go wrong, you should be able to debug and fix the error
OR revert your database to its last saved version.
return $output;
}
A themeable function takes one or several arguments, that store the beef of what has to
be output to screen, that is, Drupal objects, content, raw data. And it returns a string. That
string is XHTML ready to be sent back to the browser, i.e. it’s delicatessen. It’s a themed
representation of some content. The name of the function must — always — start
with theme_ followed by a word or a sequence of words separated by an underscore, that
describe what it is that we’re theming.
The theming system defines a chunk of themeable functions, and all modules that output
content to screen define their own share as well. Themeable functions are defined
pretty much everywhere, in core and in contributed modules. If you search for the string
“function theme_” in includes/theme.inc, you’ll find 25 themeable functions, among
which we have theme_page($content) and theme_node($node, $teaser = FALSE, $page =
FALSE).
function theme_page ($content) {
...
return $output;
}
You’ll also find 3 functions that make the theming system work : theme_get_
function($function), theme_get_settings($key = NULL), and theme_get_setting($setting_
name, $refresh = FALSE). Although all themeable functions begin with theme_, not all
functions that begin with theme_ are themeable functions.
Using The Trick, which we’ll describe shortly, we’ll be able to determine what themeable
function is responsible for what markup on the web page. With that knowledge, we’ll be
able to determine which themeable function we need to override.
The first argument is called the hook in phptemplate engine “speak”. Keep that in mind.
To be fair, there may be a situation where it becomes useful to call the base theme
function directly. One situation in which we are defining an override for that function, and
want to output the same XHTML generated by the base function minus some change. A
situation in which we want to use the php function preg_replace, for example. Say we
have a themeable function that ouputs the XHTML for a table with an id attribute that has
the value discography, and let’s say that we dislike that value and want to replace it with
disk-data. We may define our override function this way (please do not worry about how
to override themeable functions for now, we will cover all of this shortly) :
function phptemplate_disks($arg1) {
$output = theme_disks($arg1);
return preg_replace('/discography/', '/disk-data/', $output);
}
Instead of copying all the code of the base function in the overriding function, and
modifying ONE line in it, we call the base function and using regular expressions we modify
its output to our liking. Although this solution may result in less code lines, and hence less
memory allocated to PHP, it doesn’t improve performance. Note : To override a function,
we have to understand what’s going on in the base theme function. If the function is
way too complex, or it’s not possible to edit the code to achieve what we want, we may
instead modify the resulting XHTML with regular expressions, the way we’ve just seen.
Our first stop will be to ask : does the function funky_dream_entry exists ? Bingo, let’s
use that function and we’re done. Or nope, it doesn’t. Ohhh-kaaay, second stop : does the
function phptemplate_dream_entry exists ? Yes ? Let’s use it. (That function would be
defined either in phptemplate.engine or in our theme template.php file.) Or no, it doesn’t
exist. If it doesn’t, we move on to our third and last chance terminus : is there a function
with name theme_dream_entry ? (That would the base theme function.) Yes. Finally.
Now, let’s look at the code. Open up includes/theme.inc at line 161 and follow along.
You’ll have noticed that the function theme() can be invoked with any number of
arguments, one or ten. To define a function that may be called with any number of
arguments of any type, we use empty parenthesis in the definition and invoke the php
function func_get_args() to retrieve the arguments and store them in an array :
function theme() {
static $functions;
$args = func_get_args();
For your information, the php keyword static is used to define a variable whose value does
not die when the function terminates, but survives (and is modifiable, of course) “over”
several calls to the function — until index.php with its truck load of included files is totally
parsed to its last shed of blood. Here, the static variable $functions will be an array that
stores function names. For each hook, there is one function to call, and $functions[hook]
will give us the name of that function. The very first time the theme() function will be
called, $functions will know nothing. With each call, we’ll teach it a new trick, and as we call
it more and more, it’ll become increasingly knowledgeable. Let’s retrieve our hook :
$function = array_shift($args);
Let’s pretend there has been a call to theme('page', $content). At this point, $function
should be equal to page and $args should contain only one element left : $content.
We’d like to know which function to call with that hook (page) and that data ($content).
$functions[$function] = theme_get_function($function);
That’s a very cool The function to be called, for The parameters to be passed
php function ! example “phptemplate_page” to that function as an in-
dexed array, i.e. the beef!
function theme()
_phptemplate_render($file, $variables)
We start here ->
[+ style.css, templates
+ default template files and template.php]
What is my theme engine ? PHPTemplate. If it had been defined for our phptemplate
theme, it’d be either in phptemplate.engine
Has the function phptemplate_page been defined ? or in our theme’s template.php file.
You will find a phptemplate_page function in phptemplate.engine and that function calls
NO in the page[-something].tpl.php file, in this instance the page.tpl.php file of our theme.
theme_page() is defined
Then call the base theme function theme_page($return) in includes/theme.inc
Don’t forget to eventually undo this change as it makes the web page heavier to download.
The theming system finds that an override is defined in phptemplate.engine on line 303, and
that override indicates that a template file has to be used with a list of variables :
function phptemplate_comment($comment, $links = 0) { .... }
What the hell, judging from how _phptemplate_callback() is called here, we can even offer
suggestions to the theme engine as to what files it can use with a third (optional) argument.
Say we want to override the themeable function theme_poll_results() defined by the (core)
poll module. And suppose that our default theme is funky. We would like to use a template
with name poll_results.tpl.php to generate the XHTML of the poll results.
Open your theme template.php file in a text editor. If such files doesn’t exist, create one. In it,
create the shell of your phptemplate override. That’s a piece of cake : copy and paste the shell
of the base theme function and change the word theme for phptemplate :
function phptemplate_poll_results($title, $results, $votes, $links, $block, $nid, $vote) {}
Within the brackets of the function’s definition, use the same return statement as the one
used in phptemplate_page() — but don’t provide $suggestions. Then change the first
argument from page to poll_results :
return _phptemplate_callback('poll_results', $variables);
The _phptemplate_callback function expects an associative array as 2nd argument, containing
all the variables to expose to the template with the file name specified as 1st argument.
Here’s our chance to pass more information, a few extra variables besides these received by
phptemplate_poll_results(). I am out of ideas now, so let’s stick to the variables we have. The
full-fledged function definition becomes :
function phptemplate_poll_results($title, $results, $votes, $links, $block,
$nid, $vote) {
return _phptemplate_callback('poll_results', array('title' => $title,
'results' => $results, 'votes' => $votes, 'links' => $links,
'block' => $block, 'nid' => $nid, 'vote' => $vote);
}
Finally, create a poll_results.tpl.php file in your theme folder and go nuts : write XHTML and
embed your variables using php. You can use all these : $title, $results, $votes, $links, etc.