Skip to content

Instantly share code, notes, and snippets.

@ZhukV
Created June 18, 2013 11:55
Show Gist options
  • Save ZhukV/5804761 to your computer and use it in GitHub Desktop.
Save ZhukV/5804761 to your computer and use it in GitHub Desktop.
<?php
namespace Acme\DemoBundle\Util;
use Doctrine\ORM\QueryBuilder;
/**
* Pagination
*/
class Pagination implements \Countable, \Iterator
{
/**
* @var QueryBuilder
*/
protected $qb;
/**
* @var int
*/
protected $page;
/**
* @var int
*/
protected $limit;
/**
* @var bool
*/
protected $_init = false;
/**
* @var array
*/
protected $_storage = array();
/**
* @var int
*/
protected $allCount;
/**
* Construct
*
* @param QueryBuilder $qb
* @param int $page
* @param int $limit
*/
public function __construct(QueryBuilder $qb, $page, $limit)
{
$this->qb = $qb;
$this->page = abs($page);
$this->limit = $limit;
// Fix page
if ($this->page < 1) {
$this->page = 1;
}
}
/**
* Get new instance
*
* @param QueryBuilder $qb
* @param int $page
* @param int $limit
* @return self
*/
public static function newInstance(QueryBuilder $qb, $page, $limit)
{
return new static($qb, $page, $limit);
}
/**
* Execute
*/
public function execute()
{
if ($this->_init) {
return $this;
}
// Load results
$resultsQueryBuilder = clone ($this->qb);
$countsQueryBuilder = clone ($this->qb);
$this->_storage = $resultsQueryBuilder
->getQuery()
->setFirstResult($this->page * $this->limit - $this->limit)
->setMaxResults($this->limit)
->getResult();
// Generate pager
$countsQueryBuilder
->select('COUNT(' . $countsQueryBuilder->getRootAlias() . ') as count_items')
->resetDQLPart('orderBy');
$count = $countsQueryBuilder->getQuery()->getSingleResult();
$this->allCount = $count['count_items'];
$this->_init = true;
return $this;
}
/**
* Get all items count
*
* @return int
*/
public function getAllCount()
{
$this->execute();
return $this->allCount;
}
/**
* Get all pages
*
* @return int
*/
public function getCountPages()
{
$this->execute();
return ceil($this->allCount / $this->limit);
}
/**
* Is active
*
* @param int $page
* @return int
*/
public function isActive($page)
{
return $this->page == $page;
}
/**
* Get pager
*
* @param int $count
* @param bool $arrow
* @return array
*/
public function getPager($count = 5, $arrow = true)
{
$division = floor($count / 2);
$pages = array();
if ($arrow) {
$prevPage = $this->page - 1;
$pages[] = array(
'index' => $prevPage > 0 ? $prevPage : 1,
'title' => '&laquo;',
'active' => $this->isActive(1)
);
}
// Start/End loop
$start = $this->page - $division;
if ($start < 1) {
$start = 1;
}
$end = $start + ($count - 1);
// End large than count pages
if ($end >= $this->getCountPages()) {
// Set end to last page
$end = $this->getCountPages();
$start = $this->getCountPages() - $count + 1;
}
if ($start < 1) {
$start = 1;
}
for ($i = $start; $i <= $end; $i++) {
$pages[] = array(
'index' => $i,
'title' => $i,
'active' => $this->isActive($i)
);
}
if ($arrow) {
$pages[] = array(
'index' => $this->getCountPages(),
'title' => '&raquo;',
'active' => $this->isActive($this->getCountPages())
);
}
return $pages;
}
/**
* Is pager
*/
public function isPager()
{
return (bool) count($this->getPager(5, false)) > 1;
}
/**
* {@inheritDoc}
*/
public function count()
{
$this->execute();
return count($this->_storage);
}
/**
* {@inheritDoc}
*/
public function current()
{
$this->execute();
return current($this->_storage);
}
/**
* {@inheritDoc}
*/
public function next()
{
$this->execute();
return next($this->_storage);
}
/**
* {@inheritDoc}
*/
public function key()
{
$this->execute();
return key($this->_storage);
}
/**
* {@inheritDoc}
*/
public function valid()
{
$this->execute();
return $this->current();
}
/**
* {@inheritDoc}
*/
public function rewind()
{
$this->execute();
return reset($this->_storage);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment