How To: Add custom settings to Drupal 7 theme

Aug

19

2011


Drupal 7 has made it very easy to add custom 'settings' to an existing theme. I have been using the Minimalist theme by Midwestern Mac but wanted to spice things up a little bit. The date display in the submitted section was my first target. In this tutorial, I will walk through adding a custom setting that allows you add fancy dates to your theme.
 
A few preliminary things before we get into it. For the purposes of this tutorial, let's assume that my theme is "foo". If you want to modify a template file and are using a sub-theme, as I am, it is advised that you create a "foo/templates" directory and copy the template file that you wish to modify to it (so its not overwritten during an upgrade!). In my case, I copied Boron's node.tpl.php to the sub-directory. Also, don't forget to clear caches so the new template file is recognized.
 
Let's get started. The first thing you need to do is declare the new setting in the theme's info file (foo.info). I am using a checkbox setting so the line item would read:
 
settings[foo_fancydates] = 1
 
It is also important to set a default value since many people don't ever go into the theme configuration section after installing. I have set the value to 1, or true, or active (take your pick). Once complete, it's time to tell your theme about this new setting. This is done via a theme-settings.php located in the theme home (foo/). Don't worry if your theme doesn't have one, just create it.  Let's examine the contents of mine:
<?php // $Id$

function foo_form_system_theme_settings_alter(&$form, $form_state) {
  $form['foo_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Foo settings')
   );
  $form['foo_settings']['foo_fancydates'] = array(
    '#type'          => 'checkbox',
    '#title'         => t('Fancydates'),
    '#default_value' => theme_get_setting('foo_fancydates'),
    '#description'   => t("Fancydates for nodes and teasers"),
  );
}
I won't go into too much detail about each key/pair value. It is suggested that you read over Drupal's documentation on adding settings here. Most fields are pretty self explanatory. What should be paid close attention to is "foo_fancydates" - which is the setting configured in the foo.info file. These must match up!! Save & Refresh. If all is well, you will see the following in foo's settings page (notice that it is checked by default):
 
foo_settings.png
 
Now that we have our new setting, it's time to do something with it. This is accomplished through a couple of functions in the theme's template.php file:
function foo_preprocess_node(&$vars) {

      $node = $vars['node'];
      // Let's process fancydates if it is set
      $vars['fancydates'] = theme_get_setting('foo_fancydates','foo');
      if ($vars['fancydates'] == '1'):
        $vars['fancydates_output'] = foo_fancydate($node);
      endif;
}

function foo_fancydate($node) {

  $output = '<H1>'. $vars['month'] = format_date($node->created, 'custom', "M").'</H1>';
  $output .= '<H2>'. $vars['day'] = format_date($node->created, 'custom', "j") .'</H2>';
  $output .= '<H3>'. $vars['year'] = format_date($node->created, 'custom', "Y") .'</H3>';
  return $output;
}
Let's examine what these functions do. The foo_preprocess_node function gets the value of the "foo_fancydates" by calling the theme_get_setting and assigns it to a variable. The variable is checked in a control statement and if set to the default value of '1', the  foo_fancydate function is executed to return formatted date values (which is assigned to the $fancydates_output variable).
 
Moving along! We need format our output a little so it fits into our nice date.gif background pictured below:
date.png
So let's whip up a little CSS and make it happen. Since we will be showing the fancydates in both node teasers and full nodes we need to create 2 classes (.fancydate-teaser & fancydate-content respectively). You can modify colors and positions to match your theme but I would suggest not changing the size or padding of elements as the date fits snuggly into the background) Here's what I am using (click to expand):
/*************** Fanceydates stuff *********************************/
/* This is for teasers*/
.fancydate-teaser {
        background: #FFFFFF url(../img/date.png);
        float: right;
        width: 45px;
        height: 50px;
        margin-top: 7px;
        margin-left: 7px;
        margin-right: 7px;
}

.fancydate-teaser h1 {
        color: #FFFFFF;
        font-size: 10px;
        font-weight: normal;
        padding: 1px 0px 0px 10px;
        margin: 0px;
        text-transform: uppercase;
}

.fancydate-teaser h2 {
        font-family: Times New Roman, Helvetica, Sans-Serif;
        color: #999999;
        font-size: 12px;
        font-weight: bold;
        padding: 4px 4px 0px 0px;
        margin: 0px;
        text-align: center;
}

.fancydate-teaser h3 {
        font-family: Times New Roman, Helvetica, Sans-Serif;
        color: #000000;
        font-size: 9px;
        font-weight: bold;
        padding: 0px 4px 0px 0px;
        margin-top: -3px;
        text-align: center;
}

/* This is for content */
.fancydate-content {
        background: #FFFFFF url(../img/date.png);
        float: right;
        width: 45px;
        height: 50px;
        margin-top: -35px;
        margin-right: 10px;
}

.fancydate-content h1 {
        color: #FFFFFF;
        font-size: 10px;
        font-weight: normal;
        padding: 1px 0px 0px 10px;
        margin: 0px;
        text-transform: uppercase;
}

.fancydate-content h2 {
        font-family: Times New Roman, Helvetica, Sans-Serif;
        color: #999999;
        font-size: 12px;
        font-weight: bold;
        padding: 4px 4px 0px 0px;
        margin: 0px;
        text-align: center;
}

.fancydate-content h3 {
        font-family: Times New Roman, Helvetica, Sans-Serif;
        color: #000000;
        font-size: 9px;
        font-weight: bold;
        padding: 0px 4px 0px 0px;
        margin-top: -3px;
        text-align: center;
}
Ok, we're almost there. The last step is to modify the node.tpl.php file you copied to the templates directory. Let's have a look. First, we'll put in the date for the node teaser:
<?php if ($teaser && $fancydates == "1"): ?>
  <div class="fancydate-teaser">
   <?php print $fancydates_output ?>
  </div>
 <?php endif; ?>

<article id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
What's happening here? First we check if the node is a $teaser and if $fancydates is set, then we put the fancydate right above the <article> tag in the Boron template. Next, for complete nodes, we place the same (but with fancydate-content class) right below the same <article> tag:
 
<article id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
    <?php if ($variables['node']->type != "page"  && !$teaser && $fancydates == "1"): ?>
          <div class="fancydate-content">
                <?php print $fancydates_output ?>
          </div>
         <?php endif; ?>
A couple of additional checks are done in the above code snippet. First, we verify that the node is not a regular drupal page (probably don't want a fancydate on them), and second, we verify that the node is not a teaser.
 
Lastly, and this is just a little housekeeping, if we are using fancydates we probably don't want to print out the default date format that Drupal does with $display_submitted. A simple control statement will accomplish this:
      <?php if ($display_submitted): ?>
        <p class="submitted">
          <?php if($fancydates == "0") {
              print t('Submitted by !username on !datetime',
              array('!username' => $name, '!datetime' => $date));
                  } else {
              print t('Submitted by !username',
              array('!username' => $name));
                  }
          ?>
        </p>
      <?php endif; ?>
If $fancydates is off (0) we print out the default, else we print out just the author's name. If all went smoothly you should be enjoying your new fancydates!!
 
fancydate_content.png
 

Comments

Very useful
I was looking for something like this. Thank you for sharing.

Cool
I love your blog.. very nice colors & theme. Did you make this website yourself or did you hire someone to do it for you? Plz reply as I’m looking to create my own blog and would like to know where u got this from. cheers

You can have it!
Glad you like it. I did make the site myself. If you click on the 'Theme' button under Links there is a download at the bottom of the page. This isn't original work, I took the Drupal MM theme and customized it a bunch. I have a follow up article coming as I'm incorporating some more changes :) Please check back!

Pages

Add new comment