<?php
/*
* This file is part of the Pagerfanta package.
*
* (c) Pablo Díez <pablodip@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Pagerfanta;
use Pagerfanta\Adapter\AdapterInterface;
use Pagerfanta\Exception\LogicException;
use Pagerfanta\Exception\NotIntegerMaxPerPageException;
use Pagerfanta\Exception\LessThan1MaxPerPageException;
use Pagerfanta\Exception\NotIntegerCurrentPageException;
use Pagerfanta\Exception\LessThan1CurrentPageException;
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
/**
* Pagerfanta.
*
* @author Pablo Díez <pablodip@gmail.com>
*
* @api
*/
class Pagerfanta implements PagerfantaInterface, \IteratorAggregate
{
private $adapter;
private $maxPerPage;
private $currentPage;
private $currentPageResults;
private $nbResults;
private $nbPages;
/**
* Constructor.
*
* @param AdapterInterface $adapter An adapter.
* @param integer $maxPerPage The maximum of results per page.
*
* @api
*/
public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
$this->maxPerPage = 10;
$this->currentPage = 1;
}
/**
* Returns the adapter.
*
* @return AdapterInterface The adapter.
*
* @api
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* This method implements a fluent interface.
*
* {@inheritdoc}
*/
public function setMaxPerPage($maxPerPage)
{
// tries to normalize from string to integer
if (is_string($maxPerPage) && (int) $maxPerPage == $maxPerPage) {
$maxPerPage = (int) $maxPerPage;
}
if (!is_int($maxPerPage)) {
throw new NotIntegerMaxPerPageException();
}
if ($maxPerPage < 1) {
throw new LessThan1MaxPerPageException();
}
$this->currentPageResults = null;
$this->nbPages = null;
$this->maxPerPage = $maxPerPage;
return $this;
}
/**
* {@inheritdoc}
*/
public function getMaxPerPage()
{
return $this->maxPerPage;
}
/**
* This method implements a fluent interface.
*
* {@inheritdoc}
*/
public function setCurrentPage($currentPage, $allowOutOfRangePages = false, $normalizeOutOfRangePages = false)
{
// tries to normalize from string to integer
if ((is_string($currentPage) || is_float($currentPage)) && (int) $currentPage == $currentPage) {
$currentPage = (int) $currentPage;
}
// integer?
if (!is_int($currentPage)) {
throw new NotIntegerCurrentPageException();
}
// less than 1?
if ($currentPage < 1) {
$currentPage = 1;
}
// out of range pages
if (!$allowOutOfRangePages && $currentPage > 1) {
if ($currentPage > $this->getNbPages()) {
if (!$normalizeOutOfRangePages) {
throw new OutOfRangeCurrentPageException();
}
$currentPage = $this->getNbPages();
}
}
$this->currentPageResults = null;
$this->currentPage = $currentPage;
return $this;
}
/**
* {@inheritdoc}
*/
public function getCurrentPage()
{
return $this->currentPage;
}
/**
* {@inheritdoc}
*/
public function getCurrentPageResults()
{
if (null === $this->currentPageResults) {
$offset = ($this->getCurrentPage() - 1) * $this->getMaxPerPage();
$length = $this->getMaxPerPage();
$this->currentPageResults = $this->adapter->getSlice($offset, $length);
}
return $this->currentPageResults;
}
/**
* {@inheritdoc}
*/
public function getNbResults()
{
if (null === $this->nbResults) {
$this->nbResults = $this->getAdapter()->getNbResults();
}
return $this->nbResults;
}
/**
* {@inheritdoc}
*/
public function getNbPages()
{
if (null === $this->nbPages) {
$this->nbPages = (int) ceil($this->getNbResults() / $this->getMaxPerPage());
}
return $this->nbPages;
}
/**
* {@inheritdoc}
*/
public function haveToPaginate()
{
return $this->getNbResults() > $this->maxPerPage;
}
/**
* {@inheritdoc}
*/
public function hasPreviousPage()
{
return $this->currentPage > 1;
}
/**
* {@inheritdoc}
*/
public function getPreviousPage()
{
if (!$this->hasPreviousPage()) {
throw new LogicException('There is not previous page.');
}
return $this->currentPage - 1;
}
/**
* {@inheritdoc}
*/
public function hasNextPage()
{
return $this->currentPage < $this->getNbPages();
}
/**
* {@inheritdoc}
*/
public function getNextPage()
{
if (!$this->hasNextPage()) {
throw new LogicException('There is not next page.');
}
return $this->currentPage + 1;
}
/**
* Implements the \IteratorAggregate interface.
*
* Returns an \ArrayIterator instance with the current results.
*
* @api
*/
public function getIterator()
{
return new \ArrayIterator($this->getCurrentPageResults());
}
}