Drupal reverse pagination

I was waiting for this feature in Drupal 7, but there is not. Reversed pagination is logical and very SEO friendly way of content storing. For example: page number 12 will always have constant collection of nodes showed, so after a year of everyday nodes adding, when there is more than 500 pages - nodes on page number 12 will still be the same, so search engine doesn't need to reindex it over and over again... so ther is no situation when search engine have old index and user can't find needed information when going to your site.

As I was searching - there is no esy way to create reversed pagination on Drupal without changing core files. I'm using Drupal for multisiting, so there is host check in script.

The main magic is here:
/includes/pager.inc

/*FIND:*/
return db_query_range($query, $args, $pager_page_array[$element] * $limit, $limit);

/*REPLACE WITH:*/
//toopro fix (reverse pagination)
  if(strpos($_SERVER['HTTP_HOST'],'ite.com')) {//NOT site.com - remove first char for strpos to have >0
	  if($pager_page_array[$element]==0)  $pager_page_array[$element]= $pager_total[$element];
	  else if($pager_total[$element]-$pager_page_array[$element]) $offset = ceil( (($pager_total_items[$element]/$limit) -$pager_page_array[$element])*$limit );// (кол-во_страниц - текущая страница) * лимит
  } else {
	  $offset = $pager_page_array[$element] * $limit;
  }
  //toopro fix (reverse pagination)
  return db_query_range($query, $args, $offset, $limit);

For real situation i'm using long list of if(strpos($_SERVER['HTTP_HOST'],'ite.com') || strpos($_SERVER['HTTP_HOST'],'ite2.com') || strpos($_SERVER['HTTP_HOST'],'ite3.com') || ...etc... ) - so for easy code readability, without those long "!==FALSE".


The second file you may change - is theming of pages. For me it's more logical to see page "5" on address /node?page=5, and theme needs some fixes for reversed pagination, so you need to add these functions to theme.php (if there is no theme.php in your theme folder - create it and to update theme cache go to admin/build/themes)

/themes/youtheme/theme.php

function phptemplate_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
  global $pager_page_array, $pager_total;

  // Calculate various markers within this pager piece:
  // Middle is used to "center" pages around the current page.
  $pager_middle = ceil($quantity / 2);
  
  // current is the page we are currently paged to
  $pager_current = $pager_page_array[$element];
  // first is the first page listed by this pager piece (re quantity)
  $pager_first = $pager_current - $pager_middle; //TOOPRO FIX
  // last is the last page listed by this pager piece (re quantity)
  $pager_last = $pager_current + $quantity - $pager_middle; //TOOPRO FIX
  // max is the maximum page number
  $pager_max = $pager_total[$element];
  // End of marker calculations.

  // Prepare for generation loop.
  $i = $pager_first;
  if ($pager_last > $pager_max) {
    // Adjust "center" if at end of query.
    $i = $i + ($pager_max - $pager_last);
    $pager_last = $pager_max;
  }
  if ($i <= 0) {
    // Adjust "center" if at start of query.
    $pager_last = $pager_last + ( - $i);
    $i = 1;
  }
  // End of generation loop preparation.
	
  $li_first = theme('pager_first', (isset($tags[0]) ? $tags[0] : t('« first')), $limit, $element, $parameters);
  $li_previous = theme('pager_previous', (isset($tags[1]) ? $tags[1] : t('‹ previous')), $limit, $element, 1, $parameters);
  $li_next = theme('pager_next', (isset($tags[3]) ? $tags[3] : t('next ›')), $limit, $element, 1, $parameters);
  $li_last = theme('pager_last', (isset($tags[4]) ? $tags[4] : t('last »')), $limit, $element, $parameters);

  if ($pager_total[$element] > 1) {
    if ($li_first) {
      $items[] = array(
        'class' => 'pager-first',
        'data' => $li_first,
      );
    }
    if ($li_previous) {
      $items[] = array(
        'class' => 'pager-previous',
        'data' => $li_previous,
      );
    }

    // When there is more than one page, create the pager list.
    if ($i != $pager_max) {
      if ($i > 1) {
        $items[] = array(
          'class' => 'pager-ellipsis',
          'data' => '…',
        );
      }
	  
      // Now generate the actual pager piece.
      for (; $i <= $pager_last && $i <= $pager_max; $i++) {
        if ($i < $pager_current) {
          $items[] = array(
            'class' => 'pager-item',
            'data' => theme('pager_previous', $i, $limit, $element, ($pager_current - $i), $parameters),
            //'data' => theme('pager_previous', $pager_max - $i, $limit, $element, ($pager_current - $i), $parameters),
          );
        }
        if ($i == $pager_current) {
          $items[] = array(
            'class' => 'pager-current',
            'data' => $i,
            //'data' => $pager_max - $i,
          );
        }
        if ($i > $pager_current) {
          $items[] = array(
            'class' => 'pager-item',
            'data' => theme('pager_next', $i, $limit, $element, ($i - $pager_current), $parameters),
           // 'data' => theme('pager_next', $pager_max - $i, $limit, $element, ($i - $pager_current), $parameters),
          );
        }
      }//for loop
	  
      if ($i < $pager_max) {
        $items[] = array(
          'class' => 'pager-ellipsis',
          'data' => '…',
        );
      }
    }
    // End generation.
    if ($li_next) {
      $items[] = array(
        'class' => 'pager-next',
        'data' => $li_next,
      );
    }
    if ($li_last) {
      $items[] = array(
        'class' => 'pager-last',
        'data' => $li_last,
      );
    }
	
    return theme('item_list', $items, NULL, 'ul', array('class' => 'pager'));
  }
}


function phptemplate_pager_last($text, $limit, $element = 0, $parameters = array()) {
  global $pager_page_array, $pager_total;
  $output = '';

  //if we are anywhere but the last page
  if ($pager_page_array[$element] < ($pager_total[$element])) {
    //$output = theme('pager_link', $text, pager_load_array($pager_total[$element], $element, $pager_page_array), $element, $parameters);
    //print_r($pager_page_array);
	$output = theme('pager_link', $text, pager_load_array(0, $element, $pager_page_array), $element, $parameters);
  }

  return $output;
}


function phptemplate_pager_first($text, $limit, $element = 0, $parameters = array()) {
  global $pager_page_array;
  $output = '';

  // If we are anywhere but the first page
  if ($pager_page_array[$element] > 1) {
    $output = theme('pager_link', $text, pager_load_array(1, $element, $pager_page_array), $element, $parameters);
  }

  return $output;
}

function phptemplate_pager_next($text, $limit, $element = 0, $interval = 1, $parameters = array()) {
  global $pager_page_array, $pager_total;
  $output = '';

  // If we are anywhere but the last page
  if ($pager_page_array[$element] < ($pager_total[$element] - 1)) {
    $page_new = pager_load_array($pager_page_array[$element] + $interval, $element, $pager_page_array);
    
	// If the next page is the last page, mark the link as such.
    //if ($page_new[$element] == ($pager_total[$element] - 1)) {
	if ($page_new[$element] == ($pager_total[$element])) {
	  $output = theme('pager_last', $text, $limit, $element, $parameters);
    }
    // The next page is not the last page.
    else {
      $output = theme('pager_link', $text, $page_new, $element, $parameters);
    }
  }

  return $output;
}