pics/models/PageIndex.php

221 lines
5.6 KiB
PHP

<?php
/*****************************************************************************
* PageIndex.php
* Contains key class PageIndex.
*
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
*****************************************************************************/
class PageIndex
{
private $base_url;
private $current_page = 1;
private $index_class = 'pagination';
private $items_per_page = 0;
private $linkBuilder;
private $needsPageIndex = false;
private $num_pages = 1;
private $page_index = [];
private $page_slug = '%AMP%page=%PAGE%';
private $recordCount = 0;
private $sort_direction = null;
private $sort_order = null;
private $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', 'linkBuilder', 'page_slug', 'sort_direction', 'sort_order', 'start'];
foreach ($optionalKeys as $key)
if (isset($options[$key]))
$this->$key = $options[$key];
$this->generatePageIndex();
}
private function buildLink($start = null, $order = null, $dir = null)
{
if (isset($this->linkBuilder))
return call_user_func($this->linkBuilder, $start, $order, $dir);
else
return $this->getLink($start, $order, $dir);
}
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->buildLink(($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->buildLink(($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->buildLink(($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->buildLink(($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->buildLink(($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 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;
}
}