Specifying Structure

Drupal comes with the Garland theme enabled by default. How does the Garland theme specify the structure (layout and positioning of structural elements) of the rendered page? Well, actually, you already know a bit about this. Figure 7-1 shows our On-line Literary Workshop in all its structural glory. Notice the shiny new footer message! To include it, go to Administer > Site configuration > Site information, and paste something like the following into the Footer message field:

Powered by<a href="http://www.drupal.org" target="_blank"><img src="/images/drupal-favicon.ico" alt="Drupal rocks!" title="Drupal rocks!" />Drupal</a>

You can see that the page consists of several structural elements (each with its own dynamic content) placed in a series of regions (available using the PHPTemplate engine since Drupal 4.7).

You can easily identify these elements and regions if you take a look at the page template file ./themes/garland/page.tpl.php, in the Garland theme directory (see Listing 7-1).

Genre parade


peav Free verse 11


Haiku ümend Sonnet


e tags



c Croups

My t;liig

' Create content

My unread

xecent costs


c Loo out



My account

Post a literary piece

' í'ñ'.T" .i forum tnpic

1 Pn'.l ,i tilug »mir y

Private messages

c' Browse by aenre

° Logout

Welcome to our on-line literary workshop I

Add new comment


M'f Groups


M'f Groups

Literary Workshop

Welcome to our on-line literary workshop I

Add new comment

Browse genre





Clegy to the tired Eal.es





PVOedOffl ihOUt ntght nmil lwti

free verse




freedom shout eight seven five

Frmi *wr>n




Haiku red

Hail.u Hjliku

jjiriBs james

07/16/30DH 0//1Ù/20Q8

33:59 22:S?

Figure 7-1

Listing 7-1: The Annotated page.tpl.php (Garland) page template.

The DOCTYPE (document type declaration) says "XHTML 1.0 Strict, Transitional,

Frameset" and has a proper non-relative link to www.w3.org <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

xmlns attribute required in XHTML; standard attribute lang sets the language code

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language ?>" lang="<?php print $language ?>">

$head_title for dynamic content of title tag

<title><?php print $head_title ?></title>

HTML generated by the theme for the head tag, with Drupal core and enabled modules having their chance to add in whatever is necessary

Invocation of all CSS styles and Javascript inclusions, again with each module getting their chance to alter things.

<?php print $styles ?> <?php print $scripts ?>

The theme adds in its print media stylesheet.

<style type="text/css" media="print">@import "<?php print base_path() . path_to_theme() ?>/print.css";</style> <!--[if lt IE 7]>

<style type="text/css" media="all">@import "<?php print base_path() . path_to_theme() ?>/fix-ie.css";</style> <![endif] —>

Special classes added to body tag as handles for designer styling.

<body<?php print phptemplate_body_class($sidebar_left, $sidebar_right); ?>> The layout nitty gritty. <!-- Layout -->

The header is printed out, the first region to be dealt with, including the blocks enabled for that region.

<div id="header-region" class="clear-block"><?php print $header; ?></div> <div id="wrapper">

<div id="container" class="clear-block">

// Prepare header $site_fields = array(); if ($site_name) {

$site_title = implode(' ', $site_fields); $site_fields[0] = '<span>'. $site_fields[0] .'</span>'; $site_html = implode(' ', $site_fields);

if ($logo || $site_title) { // element "A"

The logo ("A") and site title ("B") are displayed in the header if enabled.

print '<h1><a href="'. check_url($base_path) .'" title="'. $site_title if ($logo) {

print '<img src="'. check_url($logo) .'" alt="'. $site_title .'"


The primary ("C") and secondary menus are displayed if enabled.

<?php if (isset($primary_links)) : ?> <?php print theme('links', $primary_links, array('class' => 'links primary-links')) ?>

<?php print theme('links', $secondary_links, array('class' => 'links secondary-

The left sidebar is displayed, containing those blocks ("D-E-F-G") enabled for this region.

<div id="sidebar-left" class="sidebar">

<?php if ($search_box): ?><div class="block block-theme"><?php print $search_box ?></div><?php endif; ?>

<?php print $sidebar_left ?> </div> <?php endif; ?>

<div id="center"> <div id="squeeze">

<div class="right-corner"> <div class="left-


The breadcrumb (not shown on front page).

<?php if ($breadcrumb): print $breadcrumb; endif; ?> The mission statement ("H").

<?php if ($mission): print '<div id="mission">'. $mission .'</div>';

The tabs (View | Edit | etc.) (not shown on the front page or for non-authenticated users) and the Title for the content.

<?php if ($tabs): print '<div id="tabs-wrapper" class="clear-block">';

<?php if ($title): print '<h2'. ($tabs ? ' class="with-tabs"' : '') .'>'. $title .'</h2>'; endif; ?>

<?php if ($tabs): print $tabs .'</div>'; endif; ?> <?php if (isset($tabs2)): print $tabs2; endif; ?>

On some pages a help text is shown.

Info area for system messages (when content is saved, for example, or if obligatory fields are missing on forms).

<?php if ($messages): print $messages; endif; ?>

The content itself! ("I")

<?php print $content ?> <span class="clear"></span>

RSS Feed icons ("K") for content (main site feed since this is front page).

<div id="footer"><?php print $footer_message ?></div> </div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center -->

The right sidebar is displayed, containing those blocks enabled for this region.

<div id="sidebar-right" class="sidebar">

<?php if (!$sidebar_left && $search_box): ?><div class="block block-theme"><?php print $search_box ?></div><?php endif; ?> <?php print $sidebar_right ?> </div> <?php endif; ?>

</div> <!-- /container --> </div> <!-- /layout -->

This contains any HTML which a module wants to include just before the closing body tag. Useful sometimes for javascript and for placing certain CSS id's and classes.

<?php print $closure ?> </body> </html>

In this way, structural elements are positioned in a given layout and printed out as the content of certain variables. For a complete list of variables available in the page.tpl.php template, see


To see the various regions available, simply go to Administer > Site building > Blocks, which is where you enabled the views-generated genre_browser block in the Content region. See Figure 7-2.

Now, how are these regions created, exactly, and what determines their layout? Well, a few things, which are related in the following sections.

Creating Additional Regions

The default regions are defined in the PHPTemplate theme engine itself (other theme engines, much less commonly used, may or may not support regions, but PHPTemplate is the default and the most often used), specifically in the following snippet taken from around line 20 from the file

./home / victorkane / Work/ Wiley/litworkshop / themes/ engines/phptemplate /:

* Declare the available regions implemented by this engine.

* An array of regions. The first array element will be used as the default region for themes.

function phptemplate_regions() { return array(

'left' => t('left sidebar'), 'right' => t('right sidebar'), 'content' => t('content'), 'header' => t('header'), 'footer' => t('footer')




augs Croups Forums

Publications Join i

** On-line literary workshop

Humr ■ Admimil'i • Sita building

Genre parade ilea. Free verse mitun Haikui,„.„,ri Sonnet mm ii t .jy v

Blocks J Add block

— bluemarine settings chameleon settings pushbutton settings


n «actinps

minneJIi settings

right sidebar

0loci .s are botfes of content that may be rendered into certain regions of your web pages, for example, into sidebars.


Ih-ev are usually generated automatically by modules, but administrators can create blod;s manually.


'■' Groups

Only enabled blocks are shown. You can position blocks by specifying which area of the page they should appear in

0 MyWog

(n.g-r >i mili't>.ii), Hiyhliyhl inJ l.il >►•!'. an tins p>igi'; Shaw 1 hn inyinriv mln which blacks cjll hn rnnrlnr nil. You r.iri '.¡inuly

Hi Groups

New forum topics <none> New gröups | <none>

JU -

1« 1*1

configure Configure

Unread posts

Piiiu.uy linLs t <nann >


1« Kl


Ptivjlir niiv.s.iyiir. <nonn»


1» l-l


left sidebar

Ri'airit hing po'it'; ftnono»


1" !-!


Recarct comnwntj | <nonc>



Recent comments <none>

f° Kl


«ecefit comments <nöne>




Syndiute <r»ne>



Whtfi new j <none>


r» -


Wlio's arduiii enorm»

1» Kl


tjgs Im Ihn ciirfnnl pasl cnuriii»


1» Kl


tag? in Forums <none>


lö F-1


tags «i User stories bv Aotor <none>

1» Fl


tags in User Stories by Iteration <none>




| Save blod.s |


PniV'-Mi'd t.vdr.iiNii.il


Now, if you want to add custom regions, you edit this file, right? Wrong! You override the regions with your own definition, in your own theme. Honoring the same self-styled ''Drupal Way'' polymorphism based on naming conventions, as seen in the case of theming functions, the theme can override the specification of regions by copying it and pasting it into the file template.php, and renaming the function with the name of the theme as prefix.

Let's do that keeping in mind that you don't want to go hacking the Garland theme shipped with the system either. The best practice is to copy the whole theme directory and rename it as your very own.

Copy the Garland theme (./themes/garland) to a suitable directory in our own versioned project area, for example, ./sites/all/themes/litgarland. Either copy the Garland theme directory directly, or do the following, as a quick and dirty way of copying and doing away with all the CVS subdirectories (if you checked out Drupal core from the Drupal CVS repository, as recommended, so as to upgrade more easily):

[email protected]: ~/litworkshop/themes$ cp -R garland ../sites/all/themes/ [email protected]: ~/litworkshop/sites/all/themes$ mv garland litgarland [email protected]: ~/litworkshop/sites/all/themes$ find litgarland \( \( -name CVS -type d \) -o -name .cvsignore \) -exec rm -rf {} \;

Let's switch over to our very own newly created Garland-based litgarland theme by logging in as user dev, going to Administer > Site building > Themes, and enabling and finally making it default and hitting the ''Save configuration'' button, as shown in Figure 7-3.

Figure 7-3

Well, nothing much has changed, but you can change that right away by interactively picking a color. Pam was talking about Royal Blue the last time we mentioned the question of color scheme, so do the following:

1. Go to a color scheme site, such as the ''[ws] Color Scheme Generator'' (http://wellstyled .com/tools/colorscheme2/index-en.html), and specify Royal Blue (#3333FF) after clicking on ''Enter RGB.'' Nice. That gives you a four-color coordinated scheme: #5050FF, #3838B3, #D3D3FF, and #A7A7FF.

2. After clicking on the ''Reduce to 'safe' colors ''checkbox, you get #6666FF, #3333CC, #CCC-CFF, and #9999FF.

3. Now, in Drupal, click on the Configure link corresponding to the litgarland theme, and you will be taken to the configuration screen for litgarland, as seen in Figure 7-4. W00t! An interactive color picker (courtesy of Steve Wittens, coauthor of the theme; see http://drupal.org/node/919 64 for details on the Garland theme and its features)!

4. I put #3333CC as both the Base color and the Link color, #6666FF for the Header top, and #CCCCFF for the Header bottom. Then, I entered my favor Text color #444444 and clicked on the ''Save configuration'' button. Now, graphic design is not my strong suit, so you might want to pick one of the 15 garish-to-subtle pre-defined Color sets. The interesting thing is that, when you list all the themes, the new color scheme shows up as the theme preview! Very cool.


yisQs 5roues Forums Publications Join'

fe* On-line literary workshop

Home - Aditlinifctrr - Sit* building

Genre parade

Themes List |.„ .,:.i,

aeav Free verse i laibun Haiku umerick Son net

Global settings bluemanne oartand marvin

more tags

Thi-!.'" [tpluinS cmili. 1 Clin i lr.pl.ly '.rllings fcir Urn J i f gur .'.i/iiiIhrnn'. Whnn fdul *.ilrr ir. displ.ifnrl living this thnrii«, Ihiv.n irvgr. will 11li'iihJ- fty

eluding "R'",c| to iM.mlK." you c.ui tiitniMi to usir Ihn glaböl 'Klings for this lhnm»».


9 Croup» My blog

Color scheme Color set: P.luc L .ignciri (OifI.iuII )|*

Create content

Bast color; ^^^r

Mr unread Kecent posts

Link color: BBWIa M

1 Content management

site bulding Blocl.s

H issilcr Ii oll um: | (f SabSM


'**«<■* BEECa

Moduli!*. ° Themes


UW .111.»!«

1 Srtn Luniiijiji.itirni

Garland - Fluid Width

1 U-iilr ni.in.»gnnuml

u u

1 Logs Help

Lorem ipsum dolor

Figure 7-4

Adding a Quote Region

So let's add our own region. Pam has mentioned that she would like a ''quote of the day from a famous author'' for all pages except the front page, and that it should go where the front-page Mission statement goes.

Well, there is a Quotes module (http://drupal.org/project/quotes) that looks active and cool, and that generates blocks. But, hey, roll your own by listing a random quote with a nodequeue. The Node-queue module is also part of the quiet revolution of modules revolutionizing Drupal (CCK, Views 2, Panels 2, Nodequeue, OG, etc., etc., etc.):

1. Create a content type for the quotes so that Pam can create some of them herself. To make this Agile, instead of making one of the fields of type text, you can create a new free-tagging multiple-select Vocabulary called Authors. So create a content type called Quote, using the title field itself for the quote (change the label to Quote), and use the default body field for a description and background (change the label to Background).

2. Deselect ''Promoted to front page'' (because even though you want it on the front page, you don't want it as a node but, rather, as part of a block inside our new region), and select ''Create New Revision.''

3. Disable comments, and make it non-postable to any group. This should be fine for what Pam is looking for. (The content type is included in the downloadable material for this chapter, both as part of the Drupal instance and as an exported content type.)

4. To create the Authors vocabulary so that terms (''authors'') can be selected for various quotes, go to Administer > Content management > Categories, and click ''Add vocabulary.'' For the vocabulary name, enter Authors. Enter Authors of quotes, as used in quote of the day in the description field. Enter Multiple authors can be selected in the Help text field. Select Quote as the only Type that authors can be applied to (so while creating or modifying a Quote, the dropdown selection box will appear for authors).

5. Finally, select the ''Free tagging,'' ''Multiple select,'' and ''Required'' checkboxes, and press the Submit button.

I ran into a problem after creating my first quote, though. The URL was http://litworkshop .victorkane/content/i-love-deadlines-i-whooshing-sound-they-make-they-fly. But I would like the word content to be replaced by quote, so that all my quotes are recognizable right in the URL. To fix this, go to Administer > Site configuration > Pathauto, and open up the Node path settings section. In the ''Pattern for all Quote paths'' field, enter content/[title-raw]

After re-editing, the result should look like Figure 7-5.

So create a few more quotes, just to get the ball rolling. What is cool is that when you reuse an author, you get an automatic dropdown selection list as soon as you type in the first couple of letters in the Author field. That's because in free-tagging vocabularies, the automatic completion widget is used. Figure 7-6 shows this when I added my second Brian Aldiss quote.

Then create a quick View to simply list all your quotes on a page:

1. Go to Administer > Site building > Administer views, click on the Add tab, and enter quotes into the Name field.

2. Put List all quotations into the Description field. Open up the Page section, select the ''Provide Page View'' checkbox, and enter valist-quotes into the URL field. Select ''List View'' for View Type.

3. Now open up the Fields section, and add the Node title and Taxonomy Terms for Authors.

4. Next, open the Filters section, and add a Node-type filter. Specify that ''Node: Type'' Is One Of Quote. Click ''Save.''

5. Click on the list-quotes link, and you should see something like Figure 7-7.

Now, because the idea is to create a new region and to stick a random quote in it on every page except the front one, you need to do two things: create the block, then create the region and stick the block there.

O ! love deadlines

1 like the whooshing sound they make as they tly by | On-line literary worksl _ n X

File Edit View Hi

story Bookmarks Toole Help

« - © E2>

^ http://ütworkchop .victorkano/quotc/i love deadline w Sooglc


i >

Biggs Groups Foiums Publication:» Juin!

On-line literary workshop



Genre parade

1 love deadlines. 1 like the whooshing sound they

elegy Free verse Haibun

make as they fly by.

Haiku ümerick Sonnet

| hriir outline

mora tags

Wed, Q7/30/20OB 10:38 dev


From http://www.lngiralcreativitv.cnm/jnn/gunres.hrml


Douglas Adams

My hlog

Create content My unread

Browse Literary Pieces

Roccnt posts Administer Log out

Name* Genre Author Date

Elegy to trie bred lakes ticgy joyce



X Find:

Prpvious ■ Next Highlighr all v Match case


Figure 7-6

On-line literary workshop | Publish or perlshi - Mozilla Flrefox

Hie fcdit View History Hookmarke lools Help

^ ^ T È ' & | hLLp ://liiworkshop .viclui kar le/lisl-quules i - i iq^gu^i*

Bloqs Groups Horums publications Join I

fe« On-line literary workshop

Gerire parade bioov Free verse Haibun Haiku um«hei; Sonnet dev

Gi uujjb My blog create content My unroad Kocont posts 1 Administer Loo out


My account Post a literary piece Post a forum topic Post a hlog entry Done

Edit CJgne Expoil

I love deadlines, I like the whooshing sound they mal:e as they tly by. Douglas Adam«;

There are two kinds nt writer: those that" make you think, and those that ma I. ft you wonder.

Brian Aldiss»

A writer should say to himself, not, How can I get more money?, but How can I reach more readers (without lowerinq standards)? Brian Aldiss

I lave something to say, and say it as clearly as you can. That is the only secret. Matthew Arnold

There are thrift rules tnr writing. Unfortunately, no on* ran agree what they are. Somerset Maugham

We Ho not write because we want to; we write because we have to. Sorrierstfl Mauyl idin

All the words I use in my stories can He found in the dictionary—it's just a matter of arranging them into the right sentences. Somerset Maugham Browse Literary Pieces mä

Figure 7-7

Populating the Quote Region with a Custom Block

First, then, you need the Nodequeue module. You can install it by using the methods presented in earlier chapters, or your own favorite. I used Drush in the following way:

[email protected]: ~/litworkshop$ drush pm install nodequeue --svnsync svncommit

Project nodequeue successfully installed (version 5.x-2.2). Project committed to Subversion successfully [email protected]: ~/litworkshop$

Next you follow these steps:

1. Go to Administer > Site building > Modules, and enable the module. Now go to Administer > User management > Access control, assign administer nodequeue permissions to the Admin role, and manipulate all queues and manipulate queues permissions to both the Admin and Workshop Leader roles.

2. Now to create the block containing a single random quote, go to Administer > Content management > Node queue, and hit the ''Add node queue'' tab.

3. In the Title field, enter Random Quotation, then use 0 as the Queue Size (no limit). Inside the ''Link for 'add to queue' Text'' field, type Add this quote. Similarly, for the field called ''Link For 'remove from queue' Text,'' enter Remove this quote entry.

4. Enable the appropriate roles so you can add nodes to the queue, and select ''Quote'' as the type of node to be added to the queue. Click on the Submit button. The queue has now been created. [If the Nodequeue module has just been installed, be sure to visit Administer > User management > Permissions (Access Control in Drupal 5), and grant permission to manipulate queues.]

5. Now, at Administer > Content management > Node queue > View (tab), use the automatic-completion (thank goodness) ''Select title to add field'' to add all your quote nodes to the queue. Or, as you add quotes, once you create them, you can click on the Node Queue tab that now appears alongside the View, Edit, and other node access tags, and then click the ''Add to queue'' link for the Random Quotation nodequeue.

6. Go to Administer > Site building > Blocks, and click on the ''Add block'' tab. Enter Random Quotation in the ''Block description,'' and the following PHP code exactly as written into the Block body (it simply instructs the Nodequeue module to fetch a random content item from nodequeue 1, which we have just created):

<?php print nodequeue_fetch_random(1); ?>

7. Open the Input format section just below the text area, and select the PHP code input format (otherwise the PHP will not get executed). Then click on the ''Save Block'' button. You will now see the Random Quotation block listed with the other disabled blocks.

8. For texting purposes, enable the block in the header region, and click on ''Save Blocks.''

Now, every time you refresh your browser, you'll get a different quote in the header region. It's not where you want it, and it's not formatted like you want it, but it works! Great start.

Enabling the Block in a New Region

In a moment, you will see various ways to control the formatting. For now, the objective is to create a new region on the page and enable this block there.

To register the new block, you need to copy the following code from ./litworkshop/themes/engines/ phptemplate/phptemplate.engine:

* Declare the available regions implemented by this engine.

* An array of regions. The first array element will be used as the default

* region for themes.

function phptemplate_regions() { return array(

'left' => t('left sidebar'), 'right' => t('right sidebar'), 'content' => t('content'), 'header' => t('header'), 'footer' => t('footer')

and paste it at the end of the ./litworkshop/sites/all/themes/litgarland/template.php file, then modify it as follows (note change to function name):

function litgarland_regions() { return array(

'left' => t('left sidebar'), 'right' => t('right sidebar'), 'content' => t('content'), 'content_top' => t('content top'), 'header' => t('header'), 'footer' => t('footer')

This means that the region ''content top'' will now be made available to the page template as the variable $content_top. So now, when you go to Administer > Site building > Blocks, you are able to directly assign the Random Quotation block to the newly created content top region for the litgarland theme!

Do so, and hit ''Save blocks.'' Of course, the immediate result is for the block to disappear completely because nowhere is it specified where the region should be positioned. You saw earlier in the Annotated page.tpl.php file how the HTML generated for the $header, $footer, $content, and other regions are positioned. So you now need to do the same for $content_top!

Around line 66 of ./litworkshop/sites/all/themes/litgarland/page.tpl.php, simply specify this with a single PHP statement, just below the printing of the breadcrumb and mission elements, as follows:

<?php if ($breadcrumb): print $breadcrumb; endif; ?> <?php if ($mission): print '<div id="mission">'. $mission .\ '</div>'; endif; ?>

The block will now appear just before the title of the current node, so if you log off, and visualize /texts/james/sonnet-two, every time you refresh the browser, you will get a random quotation just above the content item. You should be seeing something similar to Figure 7-8.

0 0

Post a comment