1 of 44

Advanced Theming

Techniques

Trevor Twining & Bevan Rudge

4 March 2009�DrupalCon DC 2009

Follow along http://tinyurl.com/dcdc-theming

2 of 44

Trevor Twining

  • Themer at CivicActions
  • Amnesty.org, WITNESS Video Hub
  • Niagara, Canada
  • trevortwining.com
  • twitter.com/TrevorTwining

 

Trevor works on themes for some of CivicActions' largest sites; Amnesty International, WITNESS Video Hub.  Trevor has been working with CivicActions for almost a year, and works from his family home in Niagara, Canada.

3 of 44

Bevan Rudge

  • Developer at CivicActions
  • Christchurch, New Zealand 
  • drupal.geek.nz
  • twitter.com/BevanR 

 

Bevan has been theming Drupal for 3 years, and theming other web frontends for longer than that.  Bevan has been working with CivicActions for over 1.5 years, and works from his home office in Christchurch, New Zealand.

4 of 44

CivicActions

  • 40 team members, one of the largest
  • 10 countries
  • 10 time zones
  • 8 different languages
  • civicactions.com

 

CivicActions is one of the largest Drupal-specific shops around, with 30 to 40 internet professionals in about 10 different countries, 10 different time zones, covering 8 different languages.

5 of 44

Some of CivicActions' clients

  • Free Software Foundation
  • Creative Commons
  • Amnesty International
  • WITNESS Video Hub
  • ACLU
  • Sony

CivicActions is changing the world, one node at a time, by empowering non-profits, NGOs and progressive political organisations with powerful internet tools for the modern web.�

6 of 44

Anatomy of a Theme

  • .info file
  • template override
  • function override
  • theme at module level

7 of 44

.info files

Perfect place to

  • Add stylesheets
  • Add regions
  • Provide default settings
  • Include javascripts

8 of 44

Template overrides

  • useful for people more comfortable with markup than code
  • provides flexibilty for subtheming (copy template into subtheme and customize)

9 of 44

Function overrides

  • Useful for work where more logic is required. (mitigated by preprocess)
  • Better performance. (function 5 times more efficient (docs))

10 of 44

Theming at module level

Needed for theming new functionality.

11 of 44

 

 

12 of 44

Overriding

It's what Drupal theming is all about

13 of 44

How to override

  • Template files
    • HOOK.tpl.php
    • e.g. block.tpl.php
  • Theme functions
    • theme_HOOK()
    • e.g. theme_user_link()

14 of 44

How to override

  • Template files
    • HOOK.tpl.php
    • e.g. block.tpl.php
  • Theme functions
    • theme_HOOK()
    • e.g. theme_user_link()

15 of 44

Overriding Template Files

  • Find the original template in
    • the base (parent) theme
    • the contrib module providing the theme hook
    • modules/system/ and other core modules
    • api.drupal.org

HINT: Use theme developer module to find where the original template file is.

16 of 44

Overriding Template Files

  • Find the original template in
  • Copy it to your theme
  • Consider using a variant, e.g. block-menu.tpl.php
    • Variants must be next to the base template file!
  • Clear the theme registry

Work out how to use NAME_preprocess_HOOK() instead! 

17 of 44

Preprocess functions are better than template files!

  • Separate logic (PHP) from appearance (HTML)
  • Less code, less bugs, less maintenance
  • Better handling of errors

 

DEMO (1 minute):  How to use a preprocess function instead of a template file

18 of 44

How to override

  • Template files
    • HOOK.tpl.php
    • e.g. block.tpl.php
  • Theme functions
    • theme_HOOK()
    • e.g. theme_user_link()

19 of 44

Overriding theme functions

  • Find the original theme function
    • in the contrib module
    • includes/theme.inc 
    • api.drupal.org
  • Copy and paste into template.php
  • Rename from theme_HOOK() to NAME_HOOK()
  • e.g. theme_username() becomes ca09_username()

Lots of duplicate code!

20 of 44

Preprocessing theme functions

There is no preprocess for theme hooks, but...

21 of 44

Preprocessing theme functions

There is no preprocess for theme hooks, but you can modify the function arguments, then call the original theme function.  E.g.�// Overrides theme_links()// http://api.drupal.org/api/function/theme_links/6function ca09_links($links, $attributes = array('class' => 'links')) {  // Do something to $links or $attributes here  return theme_links($links, $attributes);}

DEMO? (1 minute): How to pseudo-preprocess a theme function.

22 of 44

Preprocessing theme functions

Warning!

 

A module may have already overridden the original theme_HOOK() function. 

Find out from the theme registry or test with function_exists()

23 of 44

Subtheming

it just makes theming easier

24 of 44

Why a subtheme?

  • Exaggerate the defaults 
  • Get closer to final goal before writing any code
  • Inherit, inherit, inherit, then override

 

In Drupal 6, subthemes go in sites/default/themes/ and not sites/default/themes/zen/

25 of 44

Use Zen for subtheming

  • Is there any good reason not to?
  • Even for complex themes
  • Framework

 

Using Zen's body classes

// Preprocesses variables for page.tpl.php

function ca09_preprocess_page(&$vars) {

  $body_classes = explode(' ', $vars['body_classes']);  // Add or remove some classes from $body_classes (an array)  $vars['body_classes'] = implode(' ', $body_classes);}

 

DEMO? (1 minute): adding more body classes.

26 of 44

Theme Settings

  • Override which default ones are available by setting list in THEMENAME.info
  • only those specified will appear in admin/build/themes/THEMENAME/settings

27 of 44

Custom Theme Settings

  • Why?
  • Visually oriented settings: Strings, images
  • Good example: Zen custom-settings.php

28 of 44

Custom Theme Settings

  • How?
  • create theme-settings.php file
  • add THEMENAME_settings($saved_settings) function
  • use FormAPI to generate form elements

29 of 44

Avoiding code bloat

Keep your theme sustainable, extensible, maintainable

Code bloat costs you more $$$ when you need to change stuff

It makes it harder for another person to jump in and take over a theme.

30 of 44

How to avoid code bloat

  • AVOID variation templates, e.g. node-story.tpl.php 
    • Creates duplicate code
    • Use preprocess functions instead

31 of 44

How to avoid code bloat

  • AVOID variation templates, e.g. node-story.tpl.php 
    • Creates duplicate code
    • Use preprocess functions instead
  • Keep template files simple
    • Only allow print and if statements
      • NO SQL
      • NO function calls
      • NO loops
    • That's what preprocess functions (or modules) are for!
    • Template files are for HTML;  appearance, not logic

32 of 44

How to avoid code bloat

  • AVOID variation templates, e.g. node-story.tpl.php 
    • Creates duplicate code
    • Use preprocess functions instead
  • Keep template files simple
    • Only allow print and if statements
      • NO SQL, function calls, loops
    • That's what preprocess functions (or modules) are for!
    • Template files are for HTML;  appearance, not logic
  • Don't change any code outside of your theme's directory, AKA "Don't Hack Core"
  • Check for dependencies with function_exists() and module_exists()

33 of 44

Theme Registry

  • 94.8% of theme work never notices the registry except to clear it.
  • The other 5.2% is what keeps us awake at night.

34 of 44

Theming forms

  • forms are a special case
  • if no custom theming is provided

35 of 44

Theming forms

  • Work around entire form
  • http://drupal.org/node/228189#comment-1130909

36 of 44

Theming forms

  • if a form is rendered by formAPI then it is left to theme_form.
  • all forms are then rendered identically
  • to provide a custom theme we’ll need to hook_theme in our template.php

37 of 44

Modules for theming

  • Theme registry hooks and preprocess functions are executed before a theme's preprocess functions
  • Multisite: Expose themable hooks to multiple different themes
  • hook_form_alter()
  • hook_user()E.g. set a  user's username to their profile's CCK field site-wide, not just in theme_username().
  • hook_nodeapi() E.g. load calculated properties early so that they're available elsewhere.
  • hook_boot()
  • hook_init()
  • ...
  • The list goes on

38 of 44

This is where the Dark Art of Theming meets the Black Magic of Module development

39 of 44

Module Development

This is where the Dark Art of Theming meets the Black Magic of Module development

See api.drupal.org, and learn Drupal module development.�

40 of 44

Resources that help you theme faster

 

41 of 44

Resources

  • Zen – especially in Drupal 5
  • api.drupal.org
  • Theme Developer
    • Find override candidates
    • Breaks CSS & JS
  • Devel
  • dpm() / krumo

42 of 44

Useful contrib modules for themers

  • Theme developer & Devel
  • Themer
  • Cache disable
  • Devel form inspect
  • Retease

43 of 44

Firebug

  • Finding CSS properties
  • Determining CSS precedence
  • Adding and modifying CSS
  • Incrementing numeric properties
  • Adding classes and attributes to HTML
  • Deleting DOM
  • Javascript debugging

 

Firebug is my primary theme development too, even before my text editor.  You can almost use firebug for prototyping.

 

DEMO (2 minutes): Using firebug for the above tasks.

44 of 44

Questions