pagination.class.php
12 june 2012
<?php
class Pagination {

	// Current page number
	private $_current_page;

	// Current page key in $_GET
	private $_current_page_key;

	// Total item count
	private $_total_items;

	// How many items to show per page
	private $_items_per_page;

	// Total page count
	private $_total_pages;

	// Item offset for the first item displayed on the current page
	private $_current_first_item;

	// Item offset for the last item displayed on the current page
	private $_current_last_item;

	// Previous page number; FALSE if the current page is the first one
	private $_previous_page;

	// Next page number; FALSE if the current page is the last one
	private $_next_page;

	// First page number; FALSE if the current page is the first one
	private $_first_page;

	// Last page number; FALSE if the current page is the last one
	private $_last_page;

	// Query offset
	private $_offset;

	// Number of page links in the begin and end of whole range
	private $_count_out;

	// Number of page links on each side of current page
	private $_count_in;

	// Show [Previous]
	private $_show_previous_page;

	// Show [Next]
	private $_show_next_page;

	// Show [First]
	private $_show_first_page;

	// Show [Last]
	private $_show_last_page;

	public function setCurrentPage($current_page)
	{
		$this->_current_page = $current_page;
	}

	public function getCurrentPage()
	{
		return $this->_current_page;
	}

	public function setCurrentPageKey($current_page_key)
	{
		$this->_current_page_key = $current_page_key;
	}

	public function getCurrentPageKey()
	{
		return $this->_current_page_key;
	}

	public function setTotalItems($total_items)
	{
		$this->_total_items = $total_items;
	}

	public function getTotalItems()
	{
		return $this->_total_items;
	}

	public function setItemsPerPage($items_per_page)
	{
		$this->_items_per_page = $items_per_page;
	}

	public function getItemsPerPage()
	{
		return $this->_items_per_page;
	}

	public function setTotalPages($total_pages)
	{
		$this->_total_pages = $total_pages;
	}

	public function getTotalPages()
	{
		return $this->_total_pages;
	}

	public function setCurrentFirstItem($current_first_item)
	{
		$this->_current_first_item = $current_first_item;
	}

	public function getCurrentFirstItem()
	{
		return $this->_current_first_item;
	}

	public function setCurrentLastItem($current_last_item)
	{
		$this->_current_last_item = $current_last_item;
	}

	public function getCurrentLastItem()
	{
		return $this->_current_last_item;
	}

	public function setPreviousPage($previous_page)
	{
		$this->_previous_page = $previous_page;
	}

	public function getPreviousPage()
	{
		return $this->_previous_page;
	}

	public function setNextPage($next_page)
	{
		$this->_next_page = $next_page;
	}

	public function getNextPage()
	{
		return $this->_next_page;
	}

	public function setFirstPage($first_page)
	{
		$this->_first_page = $first_page;
	}

	public function getFirstPage()
	{
		return $this->_first_page;
	}

	public function setLastPage($last_page)
	{
		$this->_last_page = $last_page;
	}

	public function getLastPage()
	{
		return $this->_last_page;
	}

	public function setOffset($offset)
	{
		$this->_offset = $offset;
	}

	public function getOffset()
	{
		return $this->_offset;
	}

	public function setCountOut($count_out)
	{
		$this->_count_out = $count_out;
	}

	public function getCountOut()
	{
		return $this->_count_out;
	}

	public function setCountIn($count_in)
	{
		$this->_count_in = $count_in;
	}

	public function getCountIn()
	{
		return $this->_count_in;
	}

	public function setShowPreviousPage($show_previous_page)
	{
		$this->_show_previous_page = $show_previous_page;
	}

	public function getShowPreviousPage()
	{
		return $this->_show_previous_page;
	}

	public function setShowNextPage($show_next_page)
	{
		$this->_show_next_page = $show_next_page;
	}

	public function getShowNextPage()
	{
		return $this->_show_next_page;
	}

	public function setShowFirstPage($show_first_page)
	{
		$this->_show_first_page = $show_first_page;
	}

	public function getShowFirstPage()
	{
		return $this->_show_first_page;
	}

	public function setShowLastPage($show_last_page)
	{
		$this->_show_last_page = $show_last_page;
	}

	public function getShowLastPage()
	{
		return $this->_show_last_page;
	}

	public function initialize()
	{
		$this->setCurrentPage($this->getCurrentPageKey() !== NULL ? (int) $_GET[$this->getCurrentPageKey()] : 1);
		$this->setTotalItems((int) max(0, $this->getTotalItems()));
		$this->setItemsPerPage((int) max(1, $this->getItemsPerPage()));
		$this->setTotalPages((int) ceil($this->getTotalItems() / $this->getItemsPerPage()));
		$this->setCurrentPage((int) min(max(1, $this->getCurrentPage()), max(1, $this->getTotalItems())));
		$this->setCurrentFirstItem((int) min((($this->getCurrentPage() - 1) * $this->getItemsPerPage()) + 1, $this->getTotalItems()));
		$this->setCurrentLastItem((int) min($this->getCurrentFirstItem() + $this->getItemsPerPage() - 1, $this->getTotalItems()));
		$this->setPreviousPage(($this->getCurrentPage() > 1) ? $this->getCurrentPage() - 1 : FALSE);
		$this->setNextPage(($this->getCurrentPage() < $this->getTotalPages()) ? $this->getCurrentPage() + 1 : FALSE);
		$this->setFirstPage(($this->getCurrentPage() === 1) ? FALSE : 1);
		$this->setLastPage(($this->getCurrentPage() >= $this->getTotalPages()) ? FALSE : $this->getTotalPages());
		$this->setOffset((int) (($this->getCurrentPage() - 1) * $this->getItemsPerPage()));
		$this->setCountOut(( ! is_null($this->getCountOut())) ? (int) $this->getCountOut() : 3);
		$this->setCountIn(( ! is_null($this->getCountIn())) ? (int) $this->getCountIn() : 5);
		$this->setShowPreviousPage(( ! is_null($this->getShowPreviousPage()) ? (bool) $this->getShowPreviousPage() : TRUE));
		$this->setShowNextPage(( ! is_null($this->getShowNextPage()) ? (bool) $this->getShowNextPage() : TRUE));
		$this->setShowFirstPage(( ! is_null($this->getShowFirstPage()) ? (bool) $this->getShowFirstPage() : TRUE));
		$this->setShowLastPage(( ! is_null($this->getShowLastPage()) ? (bool) $this->getShowLastPage() : TRUE));
	}

	private function url($page = 1)
	{
		// Clean the page number
		$page = max(1, (int) $page);

		$params = array($this->getCurrentPageKey() => $page);

		// Merge the current and new parameters
		$params = array_merge($_GET, $params);

		// Note: http_build_query returns an empty string for a params array with only NULL values
		$query = http_build_query($params, '', '&');

		// Don't prepend '?' to an empty string
		return ($query === '') ? '' : ('?'.$query);
	}

	public function render()
	{
		return $this->__toString();
	}

	public function __toString()
	{
		// Beginning group of pages: $n1...$n2
		$n1 = 1;
		$n2 = min($this->getCountOut(), $this->getTotalPages());

		// Ending group of pages: $n7...$n8
		$n7 = max(1, $this->getTotalPages() - $this->getCountOut() + 1);
		$n8 = $this->getTotalPages();

		// Middle group of pages: $n4...$n5
		$n4 = max($n2 + 1, $this->getCurrentPage() - $this->getCountOut());
		$n5 = min($n7 - 1, $this->getCurrentPage() + $this->getCountOut());
		$use_middle = ($n5 >= $n4);

		// Point $n3 between $n2 and $n4
		$n3 = (int) (($n2 + $n4) / 2);
		$use_n3 = ($use_middle && (($n4 - $n2) > 1));

		// Point $n6 between $n5 and $n7
		$n6 = (int) (($n5 + $n7) / 2);
		$use_n6 = ($use_middle && (($n7 - $n5) > 1));

		// Links to display as array(page => content)
		$links = array();

		// Generate links data in accordance with calculated numbers
		for ($i = $n1; $i <= $n2; $i++)
		{
			$links[$i] = $i;
		}
		if ($use_n3)
		{
			$links[$n3] = '…';
		}
		for ($i = $n4; $i <= $n5; $i++)
		{
			$links[$i] = $i;
		}
		if ($use_n6)
		{
			$links[$n6] = '…';
		}
		for ($i = $n7; $i <= $n8; $i++)
		{
			$links[$i] = $i;
		}

		$output = '';

		if ($this->getShowFirstPage() === TRUE)
		{
			$output .= ($this->getFirstPage() !== FALSE ? '<a href="'.$this->url($this->getFirstPage()).'" rel="first">'._('First').'</a>' : _('First'));
			$output .= PHP_EOL;
		}

		if ($this->getShowPreviousPage() === TRUE)
		{
			$output .= ($this->getPreviousPage() !== FALSE ? '<a href="'.$this->url($this->getPreviousPage()).'" rel="prev">'._('Previous').'</a>' : _('Previous'));
			$output .= PHP_EOL;
		}

		foreach ($links as $number => $content)
		{
			$output .= ($number === $this->getCurrentPage() ? '<strong>'.$content.'</strong>' : '<a href="'.$this->url($number).'">'.$content.'</a>');
			$output .= PHP_EOL;
		}

		if ($this->getShowNextPage() === TRUE)
		{
			$output .= ($this->getNextPage() !== FALSE ? '<a href="'.$this->url($this->getNextPage()).'" rel="next">'._('Next').'</a>' : _('Next'));
			$output .= PHP_EOL;
		}

		if ($this->getShowLastPage() === TRUE)
		{
			$output .= ($this->getLastPage() !== FALSE ? '<a href="'.$this->url($this->getLastPage()).'" rel="last">'._('Last').'</a>' : _('Last'));
		}

		return $output;
	}

}
?>