Editor's note: This page involves hacking a contributed module which is greatly frowned upon. You should proceed with caution and only attempt this if you know what you are doing. Even better would be to create an issue and patch for the Image project so that you are not responsible for your own forked version of the code.

Author's note : This has now been done for Drupal 5.10. Please see note at the foot of this page.

I have adapted the type#1 pager from Add a << first < previous next > last >> Pager to Image Nodes Within a Gallery to work with multiple taxonomy terms and with the Nodeorder module. Nodeorder module allows drag-and-drop sequencing of image nodes, but if that's not used it defaults to normal Drupal 'sticky+upload' sequencing.

WHY BOTHER?

The standard image.module and image_gallery code provides no pager for individual image pages, only for gallery pages of thumbnails. This makes navigation insanely awkward, as to get to the next image you have to return to the thumbnails. Nor does it cope with images assigned to multiple taxonomy terms, the breadcrumbs get confused as they read only the first tid for the node. Nor does it permit explicit narrative sequencing of images.

SO....

1. provide next|prev links on single image display pages
2. allow an explicit display order set via Nodeorder module, rather than the default 'sticky+upload date' behaviour.
3. all this must cope with images that have multiple taxonomy terms and not derange the breadcrumbs
4. allow random image and latest image blocks to work as normal

You need to do the following

1. The pager that provides '< last>>'' links is created as a custom module using Osherl's type #1 code adapted as necessary. I've taken the liberty of giving it a name 'image_page_pager'. Just create a folder called 'Image_page_pager' within your modules directory, then copy the code below into a new file and save it as image_page_pager.module. Sorry about the name but it is to avoid confusion with the existing image_pager module, which creates a block containing a thumbnail and pager (image_block_pager would have been a better name for that). If you want a different sort of pager, other examples here should be fairly easy to substitute.

// $Id: image_page_pager.module

function image_page_pager_help($section = '') {
  switch ($section) {
    case 'admin/modules#description':
      return t('Adds a  pager with first,next, prev, last links to individual image pages.');
  }
}
/**
/ Adds a pager to single image displays provided by image_gallery module
/ and respects Nodeorder module ordering of nodes if used
*/
function image_page_pager($current_nid, $tid, $class = NULL) {
// Pick up the tid stored as a session variable by the image gallery page hack needed for multiple taxonomies
// if blank (no hack), get the first tid from current node
$tid = $_SESSION ['current_tid'];
  if  ($tid == 0) {
  $tid = reset(array_keys(taxonomy_node_get_terms($current_nid)));
  }
  else {
    if (arg(0) == 'node' && is_numeric(arg(1)) && is_numeric(arg(2))) {
      $terms = taxonomy_node_get_terms(arg(2));
      foreach ($terms as $term) {
        $key->tid = $tid;
      }
    }
  }
// If  Nodeorder is installed, get the array of nodes in weight_of_tid order
  if (module_exist ('nodeorder')) {
  $result = db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid = %s AND n.status = 1 ORDER BY tn.weight_in_tid ASC'), $tid);
  }
// If Nodeorder not present, use the usual sticky+upload order
  else {
  $result = db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid = %s AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC, n.nid DESC'), $tid);
  }
    while ($node = db_fetch_object($result)) {
    $nodes[++$i] = $node;
    if ($node->nid == $current_nid) $x = $i;
  }
  if($x > 1) {
    $output .= l('&laquo; first', 'node/'. $nodes[1]->nid, array('title' => check_plain($nodes[1]->title), 'class' => $class), NULL, NULL, FALSE, TRUE);
    $output .= l('&nbsp;&lsaquo;previous&nbsp;', 'node/'. $nodes[$x-1]->nid, array('title' => check_plain($nodes[$x-1]->title), 'class' => $class), NULL, NULL, FALSE, TRUE);
  }
  $output .= '|'. $x .' of '. $i . '|';
  if($x < $i) {
    $output .= l('&nbsp;next&rsaquo;&nbsp;', 'node/'. $nodes[$x+1]->nid, array('title' => check_plain($nodes[$x+1]->title), 'class' => $class), NULL, NULL, FALSE, TRUE);
    $output .= l('last &raquo;', 'node/'. $nodes[$i]->nid, array('title' => check_plain($nodes[$i]->title), 'class' => $class), NULL, NULL, FALSE, TRUE);
  }
  return $output;
}
2. Replace the function image_gallery_nodeapi in image_gallery.module with the following:
/**
* Image load single node page -- with customised breadcrumb to deal with multi-taxonomy terms
*/
function image_gallery_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'view':
      if ($page && $node->type == 'image') {
        //Eris's Changes ... plz2work!
        //Check if this node belongs in the current taxonomy
        $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, _image_gallery_get_vid());
        $ctidok=0; // Flag to indicate if there was a match, 0 (no matches) by default
        foreach ($terms as $term) {
          if($_SESSION['current_tid'] == $term->tid) {
            $ctidok=1; // Yes i do belong! set a flag and stop searching
            break;
          }
        }
        //If the current session = 0 or node doesnt belong to the current tid then do this stuff
        if ($_SESSION['current_tid'] == 0 || $ctidok==0) {
          // If Session var for current_tid empty
          $term = array_pop($terms);
          if ($term) {
            $vocabulary = taxonomy_get_vocabulary(_image_gallery_get_vid());
          // Breadcrumb navigation
            $breadcrumb = array();
            $breadcrumb[] = array('path' => 'image', 'title' => $vocabulary->name);
            if ($parents = taxonomy_get_parents_all($term->tid)) {
              $parents = array_reverse($parents);
              foreach ($parents as $p) {
                $breadcrumb[] = array('path' => 'image/tid/'. $p->tid, 'title' => $p->name);
              }
            }
          $breadcrumb[] = array('path' => 'node/'. $node->nid);
          $_SESSION['current_tid'] = $p->tid;
        }
// end
        }
        else {
          $tid = $_SESSION['current_tid'];
          $gallery = taxonomy_get_term($tid);
          $breadcrumb[] = array('path' => 'image/tid/'. $tid, 'title' => $gallery->name);
          $parents = taxonomy_get_parents_all($tid);
          foreach ($parents as $parent) {
            $breadcrumb[] = array('path' => 'image/tid/'. $parent->tid, 'title' => $parent->name);
          }
          $breadcrumb = array_reverse($breadcrumb);
          $terms = taxonomy_node_get_terms($current_nid);
          drupal_set_title($title->name);
        }
      }
    menu_set_location($breadcrumb);
    $content = theme('image_gallery', $galleries, $images);
  }
  return $content;
}
3. Replace the function image_gallery_page in image_gallery.module with the following:
/**
* Image gallery callback, displays an image gallery ordered by Nodeorder (if used), passes current image tid to
* next page via pager 'next|prev' links and maintains breadcrumbs in multi-taxonomies
*/
function image_gallery_page($type = NULL, $tid=0) {
  $galleries = taxonomy_get_tree(_image_gallery_get_vid(), $tid, -1, 1);
  for ($i=0; $i < count($galleries); $i++) {
    $galleries[$i]->count = taxonomy_term_count_nodes($galleries[$i]->tid, 'image');
    $tree = taxonomy_get_tree(_image_gallery_get_vid(), $galleries[$i]->tid, -1);
    $descendant_tids = array_merge(array($galleries[$i]->tid), array_map('_taxonomy_get_tid_from_term', $tree));
// HACK TO ALLOW NODEORDER TO WORK
    if (module_exist ('nodeorder')) {
      $last = db_fetch_object(db_query_range(db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN (%s) AND n.status = 1 ORDER BY tn.weight_in_tid ASC'), implode(',', $descendant_tids), 0, 1));
    }
    else {
      $last = db_fetch_object(db_query_range(db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN (%s) AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'),  implode(',', $descendant_tids), 0, 1));
    }
    $galleries[$i]->latest = node_load(array('nid' => $last->nid));
  }
  $images = array();
  if ($tid) {
// Hack to pass current_tid
     $_SESSION['current_tid'] = $tid;
// HACK TO ALLOW NODEORDER TO WORK
     if (module_exist ('nodeorder')) {
       $result = pager_query(db_rewrite_sql("SELECT n.nid FROM {term_node} tn INNER JOIN {node} n ON tn.nid=n.nid WHERE n.status=1 AND n.type='image' AND tn.tid=%d ORDER BY tn.weight_in_tid ASC"), variable_get('image_images_per_page', 6), 0, NULL, $tid);
     }
     else {
       $result = pager_query(db_rewrite_sql("SELECT n.nid FROM {term_node} t INNER JOIN {node} n ON t.nid=n.nid WHERE n.status=1 AND n.type='image' AND t.tid=%d ORDER BY n.sticky DESC, n.created DESC"), variable_get('image_images_per_page', 6), 0, NULL, $tid);
     }
// END HACK
     while ($node = db_fetch_object($result)) {
        $images[] = node_load(array('nid' => $node->nid));
     }
     $gallery = taxonomy_get_term($tid);
     $parents = taxonomy_get_parents_all($tid);
     foreach ($parents as $parent) {
       $breadcrumb[] = array('path' => 'image/tid/'. $parent->tid, 'title' => $parent->name);
     }
     $breadcrumb = array_reverse($breadcrumb);
     drupal_set_title($gallery->name);
  }
  menu_set_location($breadcrumb);
  $content = theme('image_gallery', $galleries, $images);
  return $content;
}
4. Create a node_image.tpl.php in your theme that includes:
    <div class="pager">
<?php  if ($page != 0 && $terms) { print image_page_pager($node->nid, $tid->tid, $gallery->name);} 
?>
    </div>
This can all be seen working at my site http://tonysleep.co.uk/exhibits makes use of Nodeorder http://tonysleep.co.uk/folios makes use of multi-taxonomies as well, eg you can choose to view photos either by genre or by the type of client who commissioned them. I'm sure it could be done better, I'm a novice at this stuff. I'm sorry if anyone wasted time exploring the interestingly broken bizarre behaviours of the earlier version. And I'm sure template.php would be a better route than hacking the modules. And proper patches would be preferable but I'm no developer. Hopefully someone who's more accomplished will come along and refine and civilise it.

Drupal 5.10 version

There is now a version of these mods for Image 5.x-1.x.dev as a proper patch for Image_gallery + an Image_page_pager module which allows a choice of 4 different pagers on image nodes. http://drupal.org/node/317902

Comments

desiree_cox’s picture

Is there a way to override image_gallery_page() in template.php, without hacking the module?

I think the answer is no, since it's not a theme function. (I'm new to this override business.)

Long time reader, first time commenter--sorry if this is in the wrong place.

Thank you.