The State of Drupal theming: Down the rabbit hole
Tags:
Preface
Today I'm going to conduct an exercise in Drupal theming. The challenge is to produce some custom markup for an article. Easy, right? Let's find out.
Why am I doing this? Recently I gave a Drupal theming training to a university staff who are building a new site in Drupal. They had a static HTML file as their initial design, and they wanted to know how to convert it to a Drupal theme. The exercise below is an exact example of the page they wanted to learn how to build. Spoiler alert: We weren't able to finish. It quickly became very difficult to show how to theme one article.
I want to recall the feeling of newness to Drupal theming. Prior to learning PHP (and eventually Drupal) my background on the web started with HTML and CSS. It's how I think about websites and for many newcomers to Drupal a familiar foothold upon which to start.
But seasoned Drupalistas have forgotten what its like to dip their toes into Drupal for the first time. Today, I'm hoping to rekindle some of those feelings and demonstrate the challenges newcomers face—perhaps more challenges than we realize in our day-to-day lives. I'd like to remark that this is not intended for a beginner audience (though beginners may get some useful tidbits), it is intended for people who've been working with Drupal for a while. We're going to explore What We Must Do. Grab some popcorn.
The exercise
Suppose I'm building my first Drupal site, and I've been provided a static HTML file that describes the markup the CMS should produce. Here's what the page looks like:
And here's some of the markup I want to produce: (we'll just focus on the markup regarding the article)
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="date">June 6, 2011</div><h2>Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</h2><img class="left" src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="Adipiscing jumentum modo paratus ratis velit."><p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
...
So, being that this is my first Drupal site, and based on my experience developing custom PHP websites, I might anticipate that the template for the article might look something like this:
...<h1>{$article.title}</h1> <div class="date">{$article.date|date_format}</div><h2>{$article.subtitle}</h2><img src="{$article.img.src}" alt="{$article.img.alt}" class="{$article.img.class}" />
{$article.text}
...
The above syntax is Smarty, which is what I used to build templates prior to Drupal. Disclaimer: Usage of Smarty is merely illustrative of my previous experience—I'm not advocating it as an alternative to PHPTemplate. Smarty has many other problems of its own, and I definitely prefer PHPTemplate. On the face of it, building templates is a simple task: using available data inject the appropriate variables into the respective tags and attributes.
Initial configuration
Let's see what Drupal provides us as markup. I'm starting with a clean Drupal 7 site with the standard install profile. I've taken a few steps to prepare the content:
- Disabled comments on the Article content type and disabled the RDF module.
- Added a Subtitle text field to the Article content type.
- Configured the field display for Articles such that the Subtitle appears first without a label and the Image field used the "medium" image style preset.
- Created the first Article node with given title, subtitle, body, and image.
Now that I've got my content set, I've created a new blank theme with simply an mytheme.info file (this means that all the markup is coming from Drupal core, and is essentially identical to the stark theme). I've enabled this theme. Here's what the article markup looks like:
...<h1 class="title" id="page-title">University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="tabs"></div><div class="region region-content">
<div id="block-system-main" class="block block-system">
<div class="content">
<div id="node-1" class="node node-article node-promoted clearfix">
<div class="submitted">Submitted by <span class="username">root</span> on Fri, 06/06/2011 - 09:28</div>
<div class="content">
<div class="field field-name-field-subtitle field-type-text field-label-hidden">
<div class="field-items">
<div class="field-item even">Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</div>
</div>
</div>
<div class="field field-name-field-image field-type-image field-label-hidden">
<div class="field-items">
<div class="field-item even">
<img src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" />
</div>
</div>
</div>
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div></div>
...
Well now. I've got some work to do.
page.tpl.php
I'll start at the top. I need to remove the class and ID from the <h1>. This heading is not contained in the node template, it is in page.tpl.php. To override the template I copy page.tpl.php from modules/system into my theme directory and clear the Drupal cache to reset the theme registry.
While I'm editing page.tpl.php, I notice on the next line after the heading is an empty <div class="tabs"></div> which is a known issue (since the render array is not empty but renders as an empty string) solved by prerendering the variable.
<?php if ($tabs = render($tabs)): ?><div class="tabs"><?php print $tabs; ?></div><?php endif; ?>
Unfortunately this isn't likely to get fixed in Drupal 7. Let's keep going. Here's our markup now:
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="region region-content">
<div id="block-system-main" class="block block-system">
<div class="content">
<div id="node-1" class="node node-article node-promoted clearfix">
<div class="submitted">Submitted by <span class="username">root</span> on Fri, 06/06/2011 - 09:28</div>
<div class="content">
<div class="field field-name-field-subtitle field-type-text field-label-hidden">
<div class="field-items">
<div class="field-item even">Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</div>
</div>
</div>
<div class="field field-name-field-image field-type-image field-label-hidden">
<div class="field-items">
<div class="field-item even">
<img src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" />
</div>
</div>
</div>
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div></div>
...
Next, we have a few <div>s to deal with
region.tpl.php and block.tpl.php
The two next wrapping <div>s correspond to region.tpl.php and block.tpl.php respectively. I'll copy both region.tpl.php from modules/system and block.tpl.php from modules/block into my theme directory and then I can remove the extra divs. The contents of the original and revised copies are show below.
Original region.tpl.php:
<?php if ($content): ?>
<div class="<?php print $classes; ?>">
<?php print $content; ?>
</div><?php endif; ?>
Revised region.tpl.php:
<?php if ($content): ?>
<?php print $content; ?><?php endif; ?>
Original block.tpl.php:
<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>
Revised block.tpl.php:
<?php if ($block->subject): ?>
<h2><?php print $block->subject ?></h2><?php endif;?><?php print $content ?>
Remark: Contextual links
These are fairly drastic changes, and they aren't completely innocuous. We'll leave in the block title so that other block titles don't break. However, removing the $classes and $title_suffix will break the contextual links module for editing purposes. There are a few workarounds for this, which could include implementing $vars['has_contextual'] = isset($vars['title_suffix']['contextual_links']) in mytheme_preprocess() and rewriting block.tpl.php as follows:
<?php if ($has_contextual): ?><div class="contextual-links-region"><?php endif ?><?php if ($block->subject): ?>
<h2<?php print $title_attributes; ?>><?php print $block->subject ?></h2><?php endif;?><?php if ($has_contextual): ?><?php print render($title_suffix); ?><?php endif ?><?php print $content ?><?php if ($has_contextual): ?></div><?php endif ?>
Furthermore, having wrapper <div>s are indeed useful for sidebar blocks and regions (suppose you want to apply CSS to each block for consistent margins and borders). From a practicality standpoint, leaving in the wrapper <div>s may be something we'd like to keep. We could use different file names such as block--system--main.tpl.php and region--content.tpl.php to simply target these areas in question for the purposes of the exercise and leave the other regions and blocks as-is.
Here's the markup after making these changes:
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div id="node-1" class="node node-article node-promoted clearfix">
<div class="submitted">Submitted by <span class="username">root</span> on Fri, 06/06/2011 - 09:28</div>
<div class="content">
<div class="field field-name-field-subtitle field-type-text field-label-hidden">
<div class="field-items">
<div class="field-item even">Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</div>
</div>
</div>
<div class="field field-name-field-image field-type-image field-label-hidden">
<div class="field-items">
<div class="field-item even">
<img src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" />
</div>
</div>
</div>
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div>
</div>
</div></div>
...
node.tpl.php
The next markup items are part of the node template. I copy node.tpl.php from modules/node into my theme directory.
Original node.tpl.php:
<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 $submitted; ?>
</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>
Revised node.tpl.php:
<?php if (!$page): ?>
<h2><a href="<?php print $node_url; ?>"><?php print $title; ?></a></h2><?php endif; ?><?php if ($display_submitted): ?>
<div class="date"><?php print $date; ?></div><?php endif; ?><?php print render($content); ?>
The $date variable will be in the format of whatever the 'medium' date settings are, which we could override in the UI, or override $vars['date'] = format_date($vars['node']->created, 'custom', 'F n, Y'); via mytheme_preprocess_node()
More contextual links remarks
So, a wrapper might actually be useful here (if only to implement clearfix). Again, because node templates support contextual links, I run into the same problem we have with the block template, and could implement a similar solution to fix this.
<?php if ($has_contextual): ?><div class="contextual-links-region"><?php endif ?><?php if (!$page): ?>
<h2><a href="<?php print $node_url; ?>"><?php print $title; ?></a></h2><?php endif; ?><?php if ($has_contextual): ?><?php print render($title_suffix); ?><?php endif ?><?php if ($display_submitted): ?>
<div class="date"><?php print $date; ?></div><?php endif; ?><?php print render($content); ?><?php if ($has_contextual): ?></div><?php endif ?>
Here's the markup again:
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="date">June 6, 2011</div><div class="field field-name-field-subtitle field-type-text field-label-hidden">
<div class="field-items">
<div class="field-item even">Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</div>
</div></div><div class="field field-name-field-image field-type-image field-label-hidden">
<div class="field-items">
<div class="field-item even">
<img src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" />
</div>
</div></div><div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div></div>
...
Onward!
field.tpl.php
To cure the final bout of divitis, I have to override field.tpl.php, which I copy from modules/field/theme into my theme directory.
I have a few options here. I could (A) copy the field.tpl.php as separately named files to target each field with a separate template file, and adjust the markup of each file accordingly from there, or I could (B) simply copy field.tpl.php as-is and use hide() and render() within node.tpl.php to show the fields them in specific wrapping markup. Using the former solution A, it requires more per-field tpl files, but allows Field UI to still reorder the display of the fields, and will have consistent rendering if fields are shared between different content types. Using the latter solution B, only needs one tpl file copy but requires copying node.tpl.php as node--article.tpl.php since other content types may not have subtitles and images. Having one field.php.php also risks problems with multi-value fields. Field UI reordering also breaks for individually rendered fields, but solution B is closer to the previous Smarty example.
Subtitle: field--field-subtitle.tpl.php
Let's do option A just for kicks. First, I'll address the subtitle field. I copy field.tpl.php as field--field-subtile.tpl.php (since the field was created via field UI, we need to use field--field-subtitle, instead of field--subtitle). Here's field--field-subtitle.tpl.php
<h2><?php print render($items[0]); ?></h2>
That's it. Markup:
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="date">June 6, 2011</div><h2>Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</h2><div class="field field-name-field-image field-type-image field-label-hidden">
<div class="field-items">
<div class="field-item even">
<img src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" />
</div>
</div></div><div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div></div>
...
Those of you looking for extra credit may have noticed that the field improperly renders the first items as being "even" classed instead of "odd" this is another known issue with a pending patch from Yours Truly. Let's hope it gets into D8.
Image: field--field-image.tpl.php
The image field is slightly tricky in that it requires an HTML class on the <img> tag. We'll add this attribute to the attributes array for the image in question. Feasibly, we could manually dissect the parameters of the variable and manually build the <img> tag, but this prevents Field UI changes (i.e. image style, other attributes, etc). (A better method for this might be to instead use the Insert module to put the image in the body instead).
The below code is for field--field-image.tpl.php. At the moment, there is another known issue to get attributes working on rendered image fields. (I've overridden theme_image_formatter() to compensate.
<?php $items[0]['#item']['attributes'] = array('class' => array('left'));print render($items[0]); ?>
And markup:
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="date">June 6, 2011</div><h2>Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</h2><img class="left" src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" /><div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p>
<p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p>
<p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p>
<p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
</div>
</div></div>
...
Body: field--body.tpl.php
The body field simply requires we remove the wrapper <div>s. Because the body field isn't generated by Field UI, the template name is simply field--body.tpl.php:
<?php print render($items[0]); ?>
Final markup
...<h1>University Doctoral Candidates Discover New Species of Raptor Dinosaur</h1><div class="date">June 6, 2011</div><h2>Near Complete Skeleton Will Help Further Describe Pre-Historic Relatives.</h2><img class="left" src="http://example.com/sites/default/files/styles/medium/public/field/image/..." alt="" /><p>Abbas adipiscing damnum iusto luctus neque ratis suscipit tincidunt validus. Commoveo elit enim humo loquor quae quia sit torqueo tum. Capto consectetuer eros mauris modo occuro te. Defui eum gilvus jugis lobortis paratus te velit ymo. Bene dolus meus neque valetudo vindico wisi. Blandit cogo pertineo refoveo rusticus usitas utrum.</p><p>Abluo diam distineo ea facilisi nunc pagus pala sagaciter validus. Abico acsi conventio dolus proprius typicus vulpes. Ad iaceo nutus. Appellatio defui facilisis iriure ludus mauris nimis singularis torqueo.</p><p>Appellatio cui eros ludus nobis sudo veniam. Appellatio causa humo voco. Antehabeo facilisi ideo interdico saluto sudo suscipit veniam. Conventio eros ex iusto si tego voco ymo. Genitus importunus neo neque refoveo si validus.</p><p>Acsi adipiscing roto tego vulpes. Decet in nostrud velit. Inhibeo pneum populus praemitto quia refoveo sagaciter valetudo vel virtus. Consectetuer iaceo melior obruo paulatim pertineo sit. Abbas scisco tum. Aptent defui gemino lobortis secundum utinam. Enim in paulatim tation utinam. Capto et ex macto neque. Fere pagus refero suscipit. Aliquip dolor hos voco.</p>
...
The markup now matches our initial goal.
Let's review
Here's everything we had to do in order to gain control of the page markup:
- Override page.tpl.php to change heading classes, read-up on issue to fix tabs until Drupal 8 comes out.
- Override region.tpl.php and block.tpl.php to remove wrapper <div>s, understand preprocessors, theme hook suggestions, and contextual.module to preserve contextual links.
- Override node.tpl.php, make same contextual links fix, alter $date format via template_preprocess_node()
- Consider options on field rendering, whether to override each template separately, or take care of markup in node.tpl.php via hide() and render(), understanding implications of Field UI with regard to ordering, field sharing across content types.
- Copy field.tpl.php as specific names which vary depending on whether fields were created via Field UI or are native to the entity. Read-up on issue to understand why odd classes are even and vice-versa, and another to figure out why attributes aren't working on images—patch core or override theme function in template.php to compensate.
- Have a good grasp of PHP, Drupal APIs, and Drupal file organization.
- Clear cache all the while :)
Back to the training class. It is a tremendous expectation to teach Drupal theming in one day, and I certainly don't expect to be able to teach everything. But I'd like to think that I can provide HTML/CSS folks an idea of where to start. The above exercise is where we start.
What we have to work with
As you know, you go to war with the Army you have. They're not the Army you might want or wish to have at a later time. —Donald Rumsfeld
This post sat dormant for a long time (given that I'm not much of a blogger). But had a recent spark to reignite.
I've been on the sidelines for many years as a Drupal themer and developer, and participated in a certain tacit decorum shared by others but we often are skirting our own APIs for the sake of simplicity. I've decided to speak up. Drupal is getting more powerful, but it is also getting more difficult, and I'm not sure the depth of this sacrifice is entirely understood.
This post was influenced by recent discussion of others in the community, first put on my radar via chx and jenlampton. I've recently caught-up on the original remarks here and previously here. Some of this discussion is from 2009, which is when I first got into Drupal. I didn't know enough about Drupal at the time to know that I cared about this. But I care now.
The intent of this post was to show a real-world exercise of what I see as a difficulty. There may be a way around the difficulty—there may not. But we need to define the problem we're having, and the venue for this extends beyond the individual issues. It took several hours of "fierce" discussion to even realize the problem in jenlampton's and chx's original post.
We need realization, not inspection. Let's put down the microscope and look at the entire landscape. ■