Drupal gallery using CCK and Views

This lesson explains how to set up a full photo and video gallery solution in Drupal using CCK and Views. Step by step instructions as well as Views/CCK imports, template files, and CSS are provided.

This is an "in progress" lesson which I will be adding to as I go. Here's an Example of the finished gallery (however I expect to add additional features as well such as better access to tags/comments, and probably per-user galleries).

The guide will be in a rough draft form initially and then additional details/cleanup will be added once the initial version is complete.

I'm working on this as time permits, though if you're interested in seeing it complete as soon as possible, please consider a small donation so I can keep it higher on the to-do list:





Initial preparations

Begin by installing the required modules:

ImageCache Presets

To make it quicker and easier to import the exact ImageCache presets used, I've created a tiny module which will automatically set up the following presets upon install:

Install the module if you'd like to automatically create the presets, or you can create them yourself by hand if you prefer. The photoalbum-listing and photoalbum-small presets are connected to specific sizes set in the CSS, so if you adjust the ImageCache settings, be sure to also adjust them in the CSS. I'd suggest leaving them as default until the gallery is functional, then go back and adjust the sizes if desired.

After the install check that the presets have appeared at Administer > Site building > ImageCache (admin/build/imagecache). If so, you may uninstall the module as it is no longer required after the import has successfully completed.

AttachmentSize
import_presets.zip1.47 KB

Import the Content Types

You will now import the content types which will make up the gallery. To keep this page tidy, I've provided each as separate text files attached to this page (scroll the bottom to download them). You MUST import the Photo Album content type and the Video Category content type "before" you import the Photo and Video types (this is because these latter two types include node reference fields that connect to the first two types).

For each type, go to Administer > Content management > Content types > Import (admin/content/types/import) and paste in the contents of one of the text files.

This gallery setup makes use of 4 separate content types. As you can likely guess, the Photo and Video types are the actual nodes which hold the photo/video media itself. The Photo Album and Video Category types act as "container" nodes which display groups of related Photo/Video nodes together (by means of an embedded View with a node reference argument, in case you're curious).

While Drupal does already have an excellent Taxonomy system built in for categorization (which may be more appropriate in some situations), the reasons for choosing to use node references in this case instead are:

  1. There's no particularly great solution currently for allowing a "less privileged" user to add taxonomy terms besides resorting to free tags (actually Taxonomy Delegate is promising, though it still doesn't meet some of the other benefits outlined below). Otherwise the user must have "administer taxonomy" permission, which is both undesirable and confusing for the user. Nodes however are both accessible/familiar to the and also have a wide variety of modules for managing their creation, editing, deleting, etc.
  2. Container nodes are "owned" by the user that creates them. This opens the door to relatively simple "per user" albums/categories (one potential solution if using taxonomy is Community Tags).
  3. Container nodes have their Body field, making it simple for the user to include description/introduction text for the album/category. All other node functionality is also available (more custom fields, comments on the album/category itself, search, etc).
  4. Integration with Popups API along with Popups: Add and Reference module make for a great feature of adding the Container nodes directly from the Photo/Video node creation page.

On the other hand one trade-off with this method is losing the ability (which is simple with taxonomy) to have nested levels of albums/categories.

AttachmentSize
gallery-content-type-photo_album.txt2.36 KB
gallery-content-type-video_category.txt2.39 KB
gallery-content-type-photo.txt6.56 KB
gallery-content-type-video.txt7.74 KB

Pathauto settings and Custom Breadcrumbs

Pathauto

It's always best to set up Pathauto settings before making any new nodes.

Go to Administer > Site building > URL Aliases > Automated alias settings (admin/build/path/pathauto) and expand the "Node path settings" fieldset.

Add the following settings:

Click the "Save configuration" button.

Add some sample content

Now that the content types have correct path aliases set up, go ahead and add at least 1-2 Photo Albums and 1-2 Video Categories, and then add several sample nodes for each album/category. Having several nodes to work with initially is important for confirming that everything is working correctly throughout the process.

After creating the new content, run cron to have the content automatically indexed by the Search module (go to admin/reports/status/run-cron).

Custom Breadcrumbs

Go to Administer > Site building > Custom breadcrumbs (admin/build/custom_breadcrumbs) and click the "Add a new custom breadcrumb" link (repeat for each instance). Add the following settings:

Photo Album

Photo

Video Category

Video

Import the Views

Download and open the following two text files which contain the Views needed for the gallery. Go to Administer > Site building > Views > Import. Leave the View name option blank so that the correct name will be automatically used, paste the content of the first View into the Paste view code here field, and click the "Import" button to import the View to your site. After you initially import, the View is not yet saved to your site, so you must click the "Save" button near the bottom of the Views configuration page.

Repeat this process to import the other View into your site as well. Remember to save the second View before leaving the Views configuration page.

AttachmentSize
gallery-view-media_photos.txt16.37 KB
gallery-view-media_videos.txt12.67 KB

Add template files to your theme

I've prepared a number of template files to the gallery system, consisting of several Views template files, a CSS file, JavaScript file, and several images, and a set of node template files.

Currently, the node templates node-photo_album.tpl.php and node-video_category.tpl.php are critical to the functionality of the Photo Album and Video Category listing pages, as they include several embedded Views that provide the functionality for these pages. In the future these files will be simplified once I adapt the gallery system to make use of the Views Attach module.

A node-photo.tpl.php and node-video.tpl.php file is also included, and the only custom code in them is the inclusion of the variable needed to print out the Previous and Next images, and the variable for including a context-sensitive "Add Photo" (or Video) link to pages. If you prefer, you may simply add <?php print $add_media; ?> and <?php print $prev_next; ?> into your own node-photo.tpl.php and node-video.tpl.php templates if you prefer.

Unzip the attached file into your own theme's directory (e.g. sites/all/themes/yourtheme/).

You need to include the following in your theme's .info file:

stylesheets[all][] = gallery-templates/cck_gallery.css
scripts[] = gallery-templates/cck_gallery.js

You must also include the following code in your theme's template.php file (change instances of YOURTHEME to the correct name of your own theme). Note that if you already have preprocess_page and/or preprocess_node functions in your theme, you should integrate the code from those two functions into your own - do not duplicate them or your site will produce errors:

/**
* Override or insert PHPTemplate variables into the templates.
*/
function YOURTHEME_preprocess_page(&$vars) {
  // Wrap content of gallery pages with a custom ID.
  if (arg(0) == 'media' && (arg(1) == 'photos' || arg(1) == 'videos')) {
    $vars['content'] = '<div id="gallery-wrapper">'. $vars['content'] .'</div>';
  }
}



/**
* Override or insert PHPTemplate variables into the templates.
*/
function YOURTHEME_preprocess_node(&$vars) {
  $node = $vars['node'];

  $prev_next  = '<ul id="node-navigation" class="clear-block">';
  $prev_next .= '<li class="prev">'. pn_node($node, 'p') .'</li>';
  $prev_next .= '<li class="next">'. pn_node($node, 'n') .'</li>';
  $prev_next .= '</ul>';
  $vars['prev_next'] = $prev_next;


  // Create Photo/Video node add links for users with access.
  if (user_access('create photo content') && ($node->type == 'photo' || $node->type == 'photo_album')) {
    $vars['add_media'] = l(t('Add new photo'), 'node/add/photo', $options = array('attributes' => array('class' => 'add-media')));
  }
  if (user_access('create video content') && ($node->type == 'video' || $node->type == 'video_category')) {
    $vars['add_media'] = l(t('Add new video'), 'node/add/video', $options = array('attributes' => array('class' => 'add-media')));
  }
}



/**
* Implementation of hook_theme().
*/
function YOURTHEME_theme(){
  return array(
    'views_exposed_form' => array(
      'arguments' => array('form' => NULL),
    ),
  );
}

// For the gallery, rename Views "Apply" button and add a Reset option.
function YOURTHEME_views_exposed_form($form) {

  if (arg(0) == 'media' && arg(1) == 'photos') {
    $form['reset']['#value'] = l(t('Reset'), 'media/photos');
    $form['submit']['#value'] = t('Search');
  }
  if (arg(0) == 'media' && arg(1) == 'videos') {
    $form['reset']['#value'] = l(t('Reset'), 'media/videos');
    $form['submit']['#value'] = t('Search');
  }
 
  return drupal_render($form);
}



/**
* Prev/Next API.
*/
function pn_node($node, $mode = 'n') {
  if (!function_exists('prev_next_nid')) {
    return NULL;
  }

  switch($mode) {
    case 'p':
      $n_nid = prev_next_nid($node->nid, 'prev');
      $link_text = t('previous');
      break;

    case 'n':
      $n_nid = prev_next_nid($node->nid, 'next');
      $link_text = t('next');
      break;

    default:
      return NULL;
  }

  if ($n_nid) {
    $n_node = node_load($n_nid);

    $options = array(
      'attributes' => array('class' => 'thumbnail'),
      'html'  => TRUE,
    );
    switch($n_node->type) {
      case 'photo': // This is a Photo node, get the thumbnail
        $fid = db_fetch_object(db_query("SELECT f.field_photo_fid FROM {content_type_photo} f WHERE nid = %d", $n_nid));
        $img_path = db_fetch_object(db_query("SELECT f.filepath FROM {files} f WHERE fid = %d", $fid->field_photo_fid));
        $img_path = file_create_path($img_path->filepath);

        $image = theme('imagecache', 'photo-mini', $img_path);
       
        $html  = l($image, "node/$n_nid", $options);
        $html .= l($link_text, "node/$n_nid", array('html' => TRUE));
        return $html;

      case 'video':
        foreach ($n_node->files as $fid => $file) {
          $html  = '<img src="' . base_path() . $file->filepath;
          $html .= '" alt="' . $n_node->title;
          $html .= '" title="' . $n_node->title;
          $html .= '" class="image image-thumbnail" />';
          $img_html = l($html, "node/$n_nid", $options);
          $text_html = l($link_text, "node/$n_nid", array('html' => TRUE));
          return $img_html . $text_html;
        }
    }
  }
}

After you have added all of the template files and added all of the above code to your template.php file, you need to rebuild the Theme Registry to ensure that Drupal is made aware of all of the new files. To do this simply go to Administer > Site configuration > Performance and click the "Clear cached data" button.

Adjust the Block settings

The next task is to set several of the blocks created by Views to appear on the appropriate pages of the gallery.

Add all of the following blocks to the Content region. For each block, change the "Page specific visibility settings" option to Show on only the listed pages, and add the appropriate paths for each.

If you'd like to add the sidebar block to show off a random group of photos from the gallery, add the media_photos: Photos block to one of your sidebar regions.