From bd7c7f963663cc570f378f395863d99e9a1c3d7d Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 19 May 2015 13:57:11 +0200 Subject: [PATCH] Introduce widget Paginator This does not support custom scrolling styles as of now. Custom view scripts are supported though. In case Paginator::getPages() does not suffice, feel free to improve this. --- library/Icinga/Web/Controller.php | 10 +- library/Icinga/Web/Widget/Paginator.php | 168 ++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 library/Icinga/Web/Widget/Paginator.php diff --git a/library/Icinga/Web/Controller.php b/library/Icinga/Web/Controller.php index 61e80173b..9acf17469 100644 --- a/library/Icinga/Web/Controller.php +++ b/library/Icinga/Web/Controller.php @@ -3,12 +3,11 @@ namespace Icinga\Web; -use Zend_Paginator; use Icinga\Data\Sortable; use Icinga\Data\QueryInterface; -use Icinga\Web\Paginator\Adapter\QueryAdapter; use Icinga\Web\Controller\ModuleActionController; use Icinga\Web\Widget\Limiter; +use Icinga\Web\Widget\Paginator; use Icinga\Web\Widget\SortBox; /** @@ -115,12 +114,11 @@ class Controller extends ModuleActionController $request = $this->getRequest(); $limit = $request->getParam('limit', $itemsPerPage); $page = $request->getParam('page', $pageNumber); - $query->limit($limit, $page * $limit); + $query->limit($limit, $page > 0 ? ($page - 1) * $limit : 0); if (! $this->view->compact) { - $paginator = new Zend_Paginator(new QueryAdapter($query)); - $paginator->setItemCountPerPage($limit); - $paginator->setCurrentPageNumber($page); + $paginator = new Paginator(); + $paginator->setQuery($query); $this->view->paginator = $paginator; } diff --git a/library/Icinga/Web/Widget/Paginator.php b/library/Icinga/Web/Widget/Paginator.php new file mode 100644 index 000000000..dc014e371 --- /dev/null +++ b/library/Icinga/Web/Widget/Paginator.php @@ -0,0 +1,168 @@ +query = $query; + return $this; + } + + /** + * Set the view script to use + * + * @param string|array $script + * + * @return $this + */ + public function setViewScript($script) + { + $this->viewScript = $script; + return $this; + } + + /** + * Render this paginator + */ + public function render() + { + if ($this->query === null) { + throw new ProgrammingError('Need a query to create the paginator widget for'); + } + + $itemCountPerPage = $this->query->getLimit(); + if (! $itemCountPerPage) { + return ''; // No pagination required + } + + $totalItemCount = count($this->query); + $pageCount = (int) ceil($totalItemCount / $itemCountPerPage); + $currentPage = $this->query->hasOffset() ? ($this->query->getOffset() / $itemCountPerPage) + 1 : 1; + $pagesInRange = $this->getPages($pageCount, $currentPage); + $variables = array( + 'totalItemCount' => $totalItemCount, + 'pageCount' => $pageCount, + 'itemCountPerPage' => $itemCountPerPage, + 'first' => 1, + 'current' => $currentPage, + 'last' => $pageCount, + 'pagesInRange' => $pagesInRange, + 'firstPageInRange' => min($pagesInRange), + 'lastPageInRange' => max($pagesInRange) + ); + + if ($currentPage > 1) { + $variables['previous'] = $currentPage - 1; + } + + if ($currentPage < $pageCount) { + $variables['next'] = $currentPage + 1; + } + + if (is_array($this->viewScript)) { + if ($this->viewScript[1] !== null) { + return $this->view()->partial($this->viewScript[0], $this->viewScript[1], $variables); + } + + return $this->view()->partial($this->viewScript[0], $variables); + } + + return $this->view()->partial($this->viewScript, $variables); + } + + /** + * Returns an array of "local" pages given the page count and current page number + * + * @return array + */ + protected function getPages($pageCount, $currentPage) + { + $range = array(); + + if ($pageCount < 10) { + // Show all pages if we have less than 10 + for ($i = 1; $i < 10; $i++) { + if ($i > $pageCount) { + break; + } + + $range[$i] = $i; + } + } else { + // More than 10 pages: + foreach (array(1, 2) as $i) { + $range[$i] = $i; + } + + if ($currentPage < 6 ) { + // We are on page 1-5 from + for ($i = 1; $i <= 7; $i++) { + $range[$i] = $i; + } + } else { + // Current page > 5 + $range[] = '...'; + + if (($pageCount - $currentPage) < 5) { + // Less than 5 pages left + $start = 5 - ($pageCount - $currentPage); + } else { + $start = 1; + } + + for ($i = $currentPage - $start; $i < ($currentPage + (4 - $start)); $i++) { + if ($i > $pageCount) { + break; + } + + $range[$i] = $i; + } + } + + if ($currentPage < ($pageCount - 2)) { + $range[] = '...'; + } + + foreach (array($pageCount - 1, $pageCount) as $i) { + $range[$i] = $i; + } + + } + + if (empty($range)) { + $range[] = 1; + } + + return $range; + } +}