This has on my todo list for years... I'm glad to finally get around to it.
		
			
				
	
	
		
			217 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /*****************************************************************************
 | |
|  * PageIndex.php
 | |
|  * Contains key class PageIndex.
 | |
|  *
 | |
|  * Kabuki CMS (C) 2013-2015, Aaron van Geffen
 | |
|  *****************************************************************************/
 | |
| 
 | |
| class PageIndex
 | |
| {
 | |
| 	protected $base_url;
 | |
| 	protected $current_page = 1;
 | |
| 	protected $index_class = 'pagination';
 | |
| 	protected $items_per_page = 0;
 | |
| 	protected $needsPageIndex = false;
 | |
| 	protected $num_pages = 1;
 | |
| 	protected $page_index = [];
 | |
| 	protected $page_slug = '%AMP%page=%PAGE%';
 | |
| 	protected $recordCount = 0;
 | |
| 	protected $sort_direction = null;
 | |
| 	protected $sort_order = null;
 | |
| 	protected $start = 0;
 | |
| 
 | |
| 	public function __construct($options)
 | |
| 	{
 | |
| 		static $neededKeys = ['base_url', 'items_per_page', 'recordCount'];
 | |
| 		foreach ($neededKeys as $key)
 | |
| 		{
 | |
| 			if (!isset($options[$key]))
 | |
| 				throw new Exception('PageIndex: argument ' . $key . ' missing in options');
 | |
| 
 | |
| 			$this->$key = $options[$key];
 | |
| 		}
 | |
| 
 | |
| 		static $optionalKeys = ['index_class', 'page_slug', 'sort_direction', 'sort_order', 'start'];
 | |
| 		foreach ($optionalKeys as $key)
 | |
| 			if (isset($options[$key]))
 | |
| 				$this->$key = $options[$key];
 | |
| 
 | |
| 		$this->generatePageIndex();
 | |
| 	}
 | |
| 
 | |
| 	protected function generatePageIndex()
 | |
| 	{
 | |
| 		/*
 | |
| 			Example 1:
 | |
| 			[1] [2] [3] [...] [c-2] [c-1] [c] [c+1] [c+2] [...] [n-2] [n-1] [n]
 | |
| 			\---------/       \-------------------------/       \-------------/
 | |
| 			   lower           current/contiguous pages              upper
 | |
| 
 | |
| 			Example 2:
 | |
| 			[1] [2] [3] [4] [5] [c] [6] [7] [...] [n/2] [...] [n-2] [n-1] [n]
 | |
| 			\---------/ \-----------------/       \---/       \-------------/
 | |
| 			   lower     current/cont. pgs.       center            upper
 | |
| 		*/
 | |
| 
 | |
| 		$this->num_pages = ceil($this->recordCount / $this->items_per_page);
 | |
| 		$this->current_page = min(ceil($this->start / $this->items_per_page) + 1, $this->num_pages);
 | |
| 		if ($this->num_pages == 0)
 | |
| 		{
 | |
| 			$this->needsPageIndex = false;
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		$lowerLower = 1;
 | |
| 		$lowerUpper = min($this->num_pages, 3);
 | |
| 
 | |
| 		$contigLower = max($lowerUpper + 1, max($this->current_page - 2, 1));
 | |
| 		$contigUpper = min($this->current_page + 2, $this->num_pages);
 | |
| 
 | |
| 		$center = floor($this->num_pages / 2);
 | |
| 
 | |
| 		$upperLower = max($contigUpper + 1, max(0, $this->num_pages - 2));
 | |
| 		$upperUpper = $this->num_pages;
 | |
| 
 | |
| 		$this->page_index = [];
 | |
| 
 | |
| 		// Lower pages
 | |
| 		for ($p = $lowerLower; $p <= $lowerUpper; $p++)
 | |
| 			$this->page_index[$p] = [
 | |
| 				'index' => $p,
 | |
| 				'is_selected' => $this->current_page == $p,
 | |
| 				'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction),
 | |
| 			];
 | |
| 
 | |
| 		// The center of the page index.
 | |
| 		if ($center > $lowerUpper && $center < $contigLower)
 | |
| 		{
 | |
| 			// Gap?
 | |
| 			if ($lowerUpper != $center)
 | |
| 				$this->page_index[] = '...';
 | |
| 
 | |
| 			$this->page_index[$center] = [
 | |
| 				'index' => $center,
 | |
| 				'is_selected' => $this->current_page == $center,
 | |
| 				'href'=> $this->getLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction),
 | |
| 			];
 | |
| 		}
 | |
| 
 | |
| 		// Gap?
 | |
| 		if ($contigLower != $p)
 | |
| 			$this->page_index[] = '...';
 | |
| 
 | |
| 		// contig pages
 | |
| 		for ($p = $contigLower; $p <= $contigUpper; $p++)
 | |
| 			$this->page_index[$p] = [
 | |
| 				'index' => $p,
 | |
| 				'is_selected' => $this->current_page == $p,
 | |
| 				'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction),
 | |
| 			];
 | |
| 
 | |
| 		// The center of the page index.
 | |
| 		if ($center > $contigUpper && $center < $upperLower)
 | |
| 		{
 | |
| 			// Gap?
 | |
| 			if ($contigUpper != $center)
 | |
| 				$this->page_index[] = '...';
 | |
| 
 | |
| 			$this->page_index[$center] = [
 | |
| 				'index' => $center,
 | |
| 				'is_selected' => $this->current_page == $center,
 | |
| 				'href'=> $this->getLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction),
 | |
| 			];
 | |
| 		}
 | |
| 
 | |
| 		// Gap?
 | |
| 		if ($upperLower != $p)
 | |
| 			$this->page_index[] = '...';
 | |
| 
 | |
| 		// Upper pages
 | |
| 		for ($p = $upperLower; $p <= $upperUpper; $p++)
 | |
| 			$this->page_index[$p] = [
 | |
| 				'index' => $p,
 | |
| 				'is_selected' => $this->current_page == $p,
 | |
| 				'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction),
 | |
| 			];
 | |
| 
 | |
| 		// Previous page?
 | |
| 		if ($this->current_page > 1)
 | |
| 			$this->page_index['previous'] = $this->page_index[$this->current_page - 1];
 | |
| 
 | |
| 		// Next page?
 | |
| 		if ($this->current_page < $this->num_pages)
 | |
| 			$this->page_index['next'] = $this->page_index[$this->current_page + 1];
 | |
| 	}
 | |
| 
 | |
| 	public function getLink($start = null, $order = null, $dir = null)
 | |
| 	{
 | |
| 		$url = $this->base_url;
 | |
| 		$amp = strpos($this->base_url, '?') ? '&' : '?';
 | |
| 
 | |
| 		if (!empty($start))
 | |
| 		{
 | |
| 			$page = $start !== '%d' ? ($start / $this->items_per_page) + 1 : $start;
 | |
| 			$url .= strtr($this->page_slug, ['%PAGE%' => $page, '%AMP%' => $amp]);
 | |
| 			$amp = '&';
 | |
| 		}
 | |
| 		if (!empty($order))
 | |
| 		{
 | |
| 			$url .= $amp . 'order=' . $order;
 | |
| 			$amp = '&';
 | |
| 		}
 | |
| 		if (!empty($dir))
 | |
| 		{
 | |
| 			$url .= $amp . 'dir=' . $dir;
 | |
| 			$amp = '&';
 | |
| 		}
 | |
| 
 | |
| 		return $url;
 | |
| 	}
 | |
| 
 | |
| 	public function getArray()
 | |
| 	{
 | |
| 		return $this->page_index;
 | |
| 	}
 | |
| 
 | |
| 	public function getPageIndex()
 | |
| 	{
 | |
| 		return $this->page_index;
 | |
| 	}
 | |
| 
 | |
| 	public function getItemsPerPage()
 | |
| 	{
 | |
| 		return $this->items_per_page;
 | |
| 	}
 | |
| 
 | |
| 	public function getSortOrder()
 | |
| 	{
 | |
| 		return $this->sort_order;
 | |
| 	}
 | |
| 
 | |
| 	public function getSortDirection()
 | |
| 	{
 | |
| 		return $this->sort_direction;
 | |
| 	}
 | |
| 
 | |
| 	public function getPageIndexClass()
 | |
| 	{
 | |
| 		return $this->index_class;
 | |
| 	}
 | |
| 
 | |
| 	public function getCurrentPage()
 | |
| 	{
 | |
| 		return $this->current_page;
 | |
| 	}
 | |
| 
 | |
| 	public function getNumberOfPages()
 | |
| 	{
 | |
| 		return $this->num_pages;
 | |
| 	}
 | |
| 
 | |
| 	public function getRecordCount()
 | |
| 	{
 | |
| 		return $this->recordCount;
 | |
| 	}
 | |
| }
 |