Welcome to the Geeks & God Static Archive. Read more »

Quick and Dirty Logo Linking with Node Reference and template.php

User Rating:
4
Average: 4 (3 votes)

Hey, gang. It's been a while since I posted one of my quick-and-dirty tutorials. I tweeted the other day about having some fun with Node Reference, Image Cache and template.php. This wasn't a church-related project, but it's the kind of thing that could be adapted to other uses. In fact, I've altered it a bit for this tutorial. Here's the details.

The site in question has node types for vendors and products, and I wanted to display the vendor's logo as the page title from page.tpl.php for all vendor and product nodes. In order to do this trick, I used template.php to create a variable called $title_styled. In the page template, I simply replaced the output of $title like this:

  <?php if ($title || $title_styled): ?>
    <h2 class="title">
      <?php echo ($title_styled ? $title_styled : $title); ?>
    </h2>
  <?php endif; ?>

Ok, so that displays $title_styled, but how is it created? I created the variable using the phptemplate_preprocess_page() function in template.php. This function lets you do all sorts of fun stuff to page variables, including creating arbitrary new ones.

function phptemplate_preprocess_page(&$vars, $hook) {
  // This does lots of other stuff I'm not showing here.
 
  // Throwing this one in as a bonus: It really annoys me that by default,
  // Drupal 6 page.tpl.php files have to call theme() function to display
  // $primary_links and $secondary_links. Let's do that here instead!
  if ($vars['primary_links']) {
    //$vars['themed_primary_links'] = theme('links', $vars['primary_links'], array('class' => 'links primary-links'));
    // Bonus #2: I'm using Nice Menus on this site. Here's how I got them on the page.
    $vars['themed_primary_links'] = theme_nice_menus_primary_links();
  }
  if ($vars['secondary_links']) {
    $vars['themed_secondary_links'] = theme('links', $vars['secondary_links'], array('class' => 'links secondary-links'));
  }
 
  // For vendor nodes, display logo as page title, using the node title for
  // both alt and title attributes for the image tag.
  if ($vars['node']->type == 'vendor' && is_array($vars['node']->field_vendor_logo)) {
    // Use node title for alt and title attributes in img tag.
    $title = check_plain($vars['node']->title);
    $vars['title_styled'] = theme('imagecache', 'toplogo', $vars['node']->field_vendor_logo[0]['filepath'], $title, $title);
  }
 
  // For product nodes, display logo of linked vendor as page title.
  if ($vars['node']->type == 'product') {
    $vars['title_styled'] = phptemplate_get_vendor_logo($vars['node']->field_product_vendor[0]['nid']);
  }
}

Ok, sorry, I went a little crazy there and added in some bonus tips on theming $primary_links and $secondary_links. That's not really part of this tutorial, but basically you can just print $themed_primary_links rather than killing kittens (calling the theme() function directly) in your page template.

Getting back on track, what do we have so far? My vendor content type has an image field called field_vendor_logo. I want this field displayed using an imagecache preset called "toplogo". So I simply check to see if my node type is vendor and the field is set. If so, I populate $vars['title_styled'] with this info, pushing it through the theme() function to display the image the way I want it to look.

Product nodes have a node reference to the vendor node called field_product_vendor. When products are nodes, I call a local function phptemplate_get_vendor_logo() with the nid of the vendor node. (I should probably be verifying that field is populated, but since the field is required, I skipped that.) Products can also be nested, so field_product_vendor might also point at another product. Therefore, this function can call itself recursively in order to make its way back to an actual vendor node. If the vendor logo is missing, it simply returns the title of the vendor node.

Lastly, because node_load() is expensive, we cache the results.

/**
 * Retrieve vendor logo for product nodes.
 *
 * Since product nodes can be nested, it may be necessary to recurse upward
 * through node reference links to find the actual vendor node. The results
 * are cached for quicker retrieval on subsequent calls.
 *
 * @param $nid
 *   The nid of the referenced node to be checked.
 *
 * @return
 *   Themed imagecache representation of the vendor logo image.
 *
 */
function phptemplate_get_vendor_logo($nid) {
  $cid = 'get_vendor_logo-' . $nid;
  $output = '';
  if ($cachedata = cache_get($cid, 'cache')) {
    $output = $cachedata->data;
  }
  else {
    $node = node_load($nid);
    if ($node->type == 'vendor' && is_array($node->field_vendor_logo)) {
      $title = check_plain($node->title);
      $output = theme('imagecache', 'toplogo', $node->field_vendor_logo[0]['filepath'], $title, $title);
      cache_set($cid, $output, 'cache', CACHE_TEMPORARY);
    }
    elseif ($node->type == 'vendor') {
      $output = check_plain($node->title);
      // Don't cache this output. Maybe user will remember to add a logo soon.
    }
    elseif ($node->type == 'product') {
      $output = phptemplate_get_vendor_logo($node->field_product_vendor[0]['nid']);
      if ($output) {
        cache_set($cid, $output, 'cache', CACHE_TEMPORARY);
      }
    }
  }
  return $output;
}

And that's it. This tutorial showed a few things, including how to generate an image from node references using imagecache, how to cache results in Drupal cache, and how to create arbitrary variables that can be inserted in your page template. Hopefully that's helpful to someone.

Micah