A simple pager script for Drupal
Today I found myself needing to render pager links in Drupal 6 for a list of items. By pager I mean the links you usually see at the bottom of the page which indicate what page you’re currently on, what pages comes before and after and where you are in the grand context of the total number of pages available (example: http://drupal.org/search/apachesolr_search/e).
Drupal has built-in pager generation methods (theme_pager) but these either require you to have loaded the data to be paged from the local Drupal database or require you to shoe-horn the data you wish to page into Drupal’s pager global variables. I needed something simpler which would work with any data but which would still generate output similar to what Drupal’s pager functions generate.
After a bit of work I had something which did the job:
- /**
- * Return themed pager using same markup and CSS classes as the standard Drupal pager.
- *
- * @param $total_pages total no. of pages.
- * @param $current_page the current page being viewed (1 <= $current_page <= $total_pages).
- * @param $num_pages_to_show no. of pages links for, excluding first, next, previous and last links .
- * @param $base_url the base URL for paging links. Each paging link will be at $base_url?page=<page_num>
- * @return themed paging links; empty string if there is only one page in total.
- */
- function garland_simple_pager_links($total_pages, $current_page, $num_pages_to_show, $base_url) {
- static $buttons;
- );
- }
- // show nothing if only one page
- if (1 >= $total_pages)
- return ”;
- // remove all query params from the base URL
- // the first page in current set of pages
- // the last page in current set of pages
- // normalize
- if (1 > $pager_first) {
- $pager_last += (1 - $pager_first);
- $pager_first = 1;
- }
- if ($total_pages < $pager_last) {
- $pager_first -= ($pager_last - $total_pages);
- if (1 > $pager_first)
- $pager_first = 1;
- $pager_last = $total_pages;
- }
- // show ‘prev’ button
- if (1 < $current_page) {
- // show ‘first’ button
- if (1 < $pager_first) {
- ‘class’ => ‘pager-first’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, 1, $buttons[‘first’]),
- );
- }
- ‘class’ => ‘pager-previous’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, $current_page-1, $buttons[‘prev’]),
- );
- // show ellipsis
- if (1 < $pager_first) {
- ‘class’ => ‘pager-ellipsis’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, ‘…’, $buttons[‘ellipsis’]),
- );
- }
- }
- // page links
- for ($i=$pager_first; $i<=$pager_last; ++$i) {
- if ($i == $current_page) {
- ‘class’ => ‘pager-current’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, $i, $buttons[‘current’]),
- );
- } else {
- ‘class’ => ‘pager-item’,
- );
- }
- }
- // show ‘next’ button
- if ($total_pages > $current_page) {
- // show ellipsis
- if ($total_pages > $pager_last) {
- ‘class’ => ‘pager-ellipsis’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, ‘…’, $buttons[‘ellipsis’]),
- );
- }
- ‘class’ => ‘pager-next’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, $current_page+1, $buttons[‘next’]),
- );
- // show ‘last’ button
- if ($total_pages > $pager_last) {
- ‘class’ => ‘pager-last’,
- ‘data’ => theme(‘simple-pager-link’, $base_url, $total_pages, $buttons[‘last’]),
- );
- }
- }
- }
- /**
- * Return a themed pager link.
- *
- * @param $base_url the base URL to add the paging query param to.
- * @param $page the number of the page to link to.
- * @param $button_attributes array(‘link_tooltip’ =>, ‘text’ => ‘class’ =>).
- * If ‘link_tooltip’ is ommitted then the text is returned witout a wrapping anchor. If ‘text’ is ommitted then
- * $page is used as the link text.
- *
- * @return themed pager link.
- * @see garland_pager_link()
- */
- function garland_simple_pager_link($base_url, $page, $button_attributes) {
- );
- $attributes[‘class’] = $button_attributes[‘class’];
- } else {
- return $text;
- }
- }
- // Amend you theme’s theme() method accordingly, as I’ve done below for Garland:
- function garland_theme($existing, $type, $theme, $path) {
- ‘function’ => ‘garland_simple_pager_links’,
- ),
- ‘function’ => ‘garland_simple_pager_link’,
- )
- );
- }
The only hook you need to know is simple-pager-links. You pass it to the total number of pages in your result set, the current page number (should be between 1 and the total number of pages), and the number of page links to show either side of the current page’s item when rendering the pager links. Note that the pager does not need to know about how many data items you wish to show on each page or even what data you plan to show. The generated page links are of the form http://<domain.com>/<path>?page=<page_number>.
Example usage:
// total no. of pages = 20
// current page = 5
// no. of page links to show = 5
// base_url = http://domain.com/directory
$pager_html = theme('simple-pager-links', 20, 5, 5, 'http://domain.com/directory');
This would produce a pager like the following:
-
Lee
-
http://twitter.com/hiddentao HiddenTao
-
Profachie
-
http://twitter.com/hiddentao HiddenTao
