How to Add Theme Settings for Drupal 7

You know that list of checkboxes on the theme settings page that let you turn on and off parts of the theme like the logo or slogan? Well, you can add your own options to that list really easily in Drupal 7. In D6, this was kind of a pain, because you had to write all sorts of functions to save and load your settings to the database and handle everything properly. In D7, that’s all done through the Form API, so the heavy lifting is done for you. All you need to do is tell it to add some form fields, and what the new setting is called!

You’ll need to create a theme-settings.php file in your theme, and add this code to it:

<?php
function themename_form_system_theme_settings_alter(&$form, &$form_state) {
  $form['theme_settings']['your_option'] = array(
    '#type' => 'checkbox',
    '#title' => t('Your Option'),
    '#default_value' => theme_get_setting('your_option'),
  );
}
  • ['theme_settings'] is the existing fieldset to add your option to. You can leave it off, but by pointing it to the theme_settings group, it’ll be added to the existing list of checkbox display options for your theme. Handy!
  • ['your_option'] is the name of your new option.
  • #type tells Drupal what kind of form element to create.
  • #title is the title (or in this case, label) text for the form element.
  • #default_value tells Drupal where to find the initial setting for the form element.

We set #default_value to theme_get_setting('your_option'), which tells Drupal to look for this setting in the database. But here’s the brilliant part — if it can’t find that setting in the database, it will check in your theme’s .info file! So add this line:

settings[your_option] = 1

Now your theme will use the default setting unless the admin overrides it on the theme settings page.

You’ll want to actually do something with this setting, so here’s the PHP call to load it.

theme_get_setting('your_option');

You can call this in from any of your .tpl.php files. For a simple checkbox option like this, you can build an if() statement around it, like so:

<?php if (theme_get_setting('your_option')): ?>
  <!-- Your code here! -->
<?php endif; ?>

In this example, we added a checkbox, but you can add just about any form elements you can think of, including radio buttons and text input fields. What sort of options will you add to your theme?

References

Note: This was originally posted on my work blog, and I’m re-posting it here for archival purposes.

How to Change the Content-Type Meta Tag in Drupal

I’m working on an HTML5 theme for Drupal 7 right now, and I needed to change the meta content-type tag. By default it looks like this: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />, and I needed the updated HTML5 version: <meta charset="utf-8" />. Normally, you can replace these things in one of the theme template files, but in this case, the meta tag was hard-coded in the Drupal source code somewhere, so I needed a programmatic solution. Here’s what I found for both Drupal 6 and 7.

Drupal 6

The meta tag is stored in the $vars['head'] array, so we can simply use the php str_replace() function to change it. Just drop this code into the template.php file for your theme.

// replace the meta content-type tag for Drupal 6
function YOURTHEME_preprocess_page(&$vars, $hook) {
  $vars['head'] = str_replace(
    '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
    '<meta charset="utf-8" />',
    $vars['head']
  );
}

Drupal 7

This is slightly more complicated in Drupal 7, because instead of storing the meta tag directly in a variable, the attributes for the tag are stored in an array, which is later converted into markup. Now, we could still edit that markup, but it’s more elegant to update the attributes in the array before it’s turned into markup, rather than rely on a string replace. Here’s how to do it. Again, just drop this code into your theme’s template.php file.

// replace the meta content-type tag for Drupal 7
function YOURTHEME_html_head_alter(&$head_elements) {
  $head_elements['system_meta_content_type']['#attributes'] = array(
    'charset' => 'utf-8'
  );
}

You can use this technique to update any setting stored in that array. To see what your options are, add print_r($head_elements); inside that function. It’ll display the contents of the array on your page (though you may need to view source to make any sense of it). To edit a different tag, just replace system_meta_content_type with the item you want to alter. You can even remove an item from the array entirely like this:

// remove a tag from the head for Drupal 7
function YOURTHEME_html_head_alter(&$head_elements) {
  unset($head_elements['system_meta_generator']);
}

This is a perfect example of one of my frustrations with Drupal. For the most part, the theme system is well thought out, but if you stray from the beaten path by trying to do something they didn’t think you would need to do, you have to do it programmatically. It’s hard for me to fathom why certain parts of the markup, like this meta tag, are locked away, instead of making everything available in the theme layer. Still, this code should give you the tools you need to gain access to them.

Note: This was originally posted on my work blog, and I’m re-posting it here for archival purposes.