Skip to content
Browse files

refactored many things

  • Loading branch information...
1 parent ae0ff21 commit 103a140c77b40f22b2f413858210d735b9b2daf9 @pablodip pablodip committed Mar 31, 2013
Showing with 2,452 additions and 1,027 deletions.
  1. +3 −2 .gitignore
  2. +1 −2 .travis.yml
  3. +1 −1 composer.json
  4. +1 −1 phpunit.xml.dist
  5. +0 −6 src/Pagerfanta/Adapter/AdapterInterface.php
  6. +0 −6 src/Pagerfanta/Adapter/ArrayAdapter.php
  7. +13 −13 src/Pagerfanta/Adapter/CallbackAdapter.php
  8. +0 −6 src/Pagerfanta/Adapter/DoctrineCollectionAdapter.php
  9. +5 −7 src/Pagerfanta/Adapter/DoctrineODMMongoDBAdapter.php
  10. +0 −6 src/Pagerfanta/Adapter/DoctrineORM/Paginator.php
  11. +4 −9 src/Pagerfanta/Adapter/DoctrineORMAdapter.php
  12. +0 −6 src/Pagerfanta/Adapter/MandangoAdapter.php
  13. +4 −7 src/Pagerfanta/Adapter/MongoAdapter.php
  14. +23 −7 src/Pagerfanta/Adapter/NullAdapter.php
  15. +8 −2 src/Pagerfanta/Adapter/PropelAdapter.php
  16. +63 −16 src/Pagerfanta/Adapter/SolariumAdapter.php
  17. +19 −0 src/Pagerfanta/Exception/NotBooleanException.php
  18. +251 −74 src/Pagerfanta/Pagerfanta.php
  19. +3 −129 src/Pagerfanta/PagerfantaInterface.php
  20. +173 −66 src/Pagerfanta/View/DefaultView.php
  21. +2 −6 src/Pagerfanta/View/OptionableView.php
  22. +89 −0 src/Pagerfanta/View/Template/DefaultTemplate.php
  23. +43 −0 src/Pagerfanta/View/Template/Template.php
  24. +40 −0 src/Pagerfanta/View/Template/TemplateInterface.php
  25. +139 −0 src/Pagerfanta/View/Template/TwitterBootstrapTemplate.php
  26. +9 −96 src/Pagerfanta/View/TwitterBootstrapView.php
  27. +0 −4 src/Pagerfanta/View/ViewFactory.php
  28. +0 −12 src/Pagerfanta/View/ViewFactoryInterface.php
  29. +3 −8 src/Pagerfanta/View/ViewInterface.php
  30. +7 −8 tests/Pagerfanta/Tests/Adapter/ArrayAdapterTest.php
  31. +50 −18 tests/Pagerfanta/Tests/Adapter/CallbackAdapterTest.php
  32. +75 −0 tests/Pagerfanta/Tests/Adapter/DoctrineCollectionAdapterTest.php
  33. +0 −64 tests/Pagerfanta/Tests/Adapter/DoctrineCollectionTest.php
  34. +35 −30 tests/Pagerfanta/Tests/Adapter/DoctrineODMMongoDBAdapterTest.php
  35. +43 −29 tests/Pagerfanta/Tests/Adapter/MandangoAdapterTest.php
  36. +33 −25 tests/Pagerfanta/Tests/Adapter/MongoAdapterTest.php
  37. +21 −11 tests/Pagerfanta/Tests/Adapter/NullAdapterTest.php
  38. +29 −37 tests/Pagerfanta/Tests/Adapter/PropelAdapterTest.php
  39. +26 −0 tests/Pagerfanta/Tests/Adapter/Solarium2AdapterTest.php
  40. +26 −0 tests/Pagerfanta/Tests/Adapter/Solarium3AdapterTest.php
  41. +60 −83 tests/Pagerfanta/Tests/Adapter/SolariumAdapterTest.php
  42. +471 −166 tests/Pagerfanta/Tests/PagerfantaTest.php
  43. +260 −25 tests/Pagerfanta/Tests/View/DefaultViewTest.php
  44. +50 −12 tests/Pagerfanta/Tests/View/OptionableViewTest.php
  45. +297 −27 tests/Pagerfanta/Tests/View/TwitterBootstrapViewTest.php
  46. +72 −0 tests/Pagerfanta/Tests/View/ViewTestCase.php
View
5 .gitignore
@@ -1,3 +1,4 @@
-phpunit.xml
-/vendor/
composer.lock
+Guardfile
+phpunit.xml
+/vendor/
View
3 .travis.yml
@@ -14,8 +14,7 @@ env:
- DOCTRINE_ORM_VERSION=2.3.*
- DOCTRINE_ORM_VERSION=dev-master
- SOLARIUM_VERSION=2.*
- - SOLARIUM_VERSION=3.0.*
- - SOLARIUM_VERSION=3.1.*
+ - SOLARIUM_VERSION=dev-develop
services: mongodb
View
2 composer.json
@@ -18,7 +18,7 @@
"mandango/mandango": "*",
"doctrine/mongodb-odm": "*",
"propel/propel1": "~1.6",
- "solarium/solarium": "3.*"
+ "solarium/solarium": "dev-develop"
},
"minimum-stability": "dev",
"suggest": {
View
2 phpunit.xml.dist
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<phpunit bootstrap="tests/bootstrap.php">
+<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Pagerfanta Test Suite">
<directory>tests/Pagerfanta/</directory>
View
6 src/Pagerfanta/Adapter/AdapterInterface.php
@@ -15,17 +15,13 @@
* AdapterInterface.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
interface AdapterInterface
{
/**
* Returns the number of results.
*
* @return integer The number of results.
- *
- * @api
*/
function getNbResults();
@@ -36,8 +32,6 @@ function getNbResults();
* @param integer $length The length.
*
* @return array|\Traversable The slice.
- *
- * @api
*/
function getSlice($offset, $length);
}
View
6 src/Pagerfanta/Adapter/ArrayAdapter.php
@@ -15,8 +15,6 @@
* ArrayAdapter.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class ArrayAdapter implements AdapterInterface
{
@@ -26,8 +24,6 @@ class ArrayAdapter implements AdapterInterface
* Constructor.
*
* @param array $array The array.
- *
- * @api
*/
public function __construct(array $array)
{
@@ -38,8 +34,6 @@ public function __construct(array $array)
* Returns the array.
*
* @return array The array.
- *
- * @api
*/
public function getArray()
{
View
26 src/Pagerfanta/Adapter/CallbackAdapter.php
@@ -18,39 +18,39 @@
*/
class CallbackAdapter implements AdapterInterface
{
- private $nbResultsCallback;
- private $sliceCallback;
+ private $getNbResultsCallback;
+ private $getSliceCallback;
/**
- * @param callable $nbResultsCallback
- * @param callable $sliceCallback
+ * @param callable $getNbResultsCallback
+ * @param callable $getSliceCallback
*/
- public function __construct($nbResultsCallback, $sliceCallback)
+ public function __construct($getNbResultsCallback, $getSliceCallback)
{
- if (!is_callable($nbResultsCallback)) {
- throw new InvalidArgumentException('$nbResultsCallback should be a callable');
+ if (!is_callable($getNbResultsCallback)) {
+ throw new InvalidArgumentException('$getNbResultsCallback should be a callable');
}
- if (!is_callable($sliceCallback)) {
- throw new InvalidArgumentException('$sliceCallback should be a callable');
+ if (!is_callable($getSliceCallback)) {
+ throw new InvalidArgumentException('$getSliceCallback should be a callable');
}
- $this->nbResultsCallback = $nbResultsCallback;
- $this->sliceCallback = $sliceCallback;
+ $this->getNbResultsCallback = $getNbResultsCallback;
+ $this->getSliceCallback = $getSliceCallback;
}
/**
* {@inheritdoc}
*/
public function getNbResults()
{
- return call_user_func($this->nbResultsCallback);
+ return call_user_func($this->getNbResultsCallback);
}
/**
* {@inheritdoc}
*/
public function getSlice($offset, $length)
{
- return call_user_func_array($this->sliceCallback, array($offset, $length));
+ return call_user_func($this->getSliceCallback, $offset, $length);
}
}
View
6 src/Pagerfanta/Adapter/DoctrineCollectionAdapter.php
@@ -17,8 +17,6 @@
* DoctrineCollectionAdapter.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class DoctrineCollectionAdapter implements AdapterInterface
{
@@ -28,8 +26,6 @@ class DoctrineCollectionAdapter implements AdapterInterface
* Constructor.
*
* @param Collection $collection A Doctrine collection.
- *
- * @api
*/
public function __construct(Collection $collection)
{
@@ -40,8 +36,6 @@ public function __construct(Collection $collection)
* Returns the collection.
*
* @return Collection The collection.
- *
- * @api
*/
public function getCollection()
{
View
12 src/Pagerfanta/Adapter/DoctrineODMMongoDBAdapter.php
@@ -17,8 +17,6 @@
* DoctrineODMMongoDBAdapter.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class DoctrineODMMongoDBAdapter implements AdapterInterface
{
@@ -28,8 +26,6 @@ class DoctrineODMMongoDBAdapter implements AdapterInterface
* Constructor.
*
* @param Builder $queryBuilder A DoctrineMongo query builder.
- *
- * @api
*/
public function __construct(Builder $queryBuilder)
{
@@ -40,8 +36,6 @@ public function __construct(Builder $queryBuilder)
* Returns the query builder.
*
* @return Builder The query builder.
- *
- * @api
*/
public function getQueryBuilder()
{
@@ -61,6 +55,10 @@ public function getNbResults()
*/
public function getSlice($offset, $length)
{
- return iterator_to_array($this->queryBuilder->limit($length)->skip($offset)->getQuery()->execute());
+ return $this->queryBuilder
+ ->limit($length)
+ ->skip($offset)
+ ->getQuery()
+ ->execute();
}
}
View
6 src/Pagerfanta/Adapter/DoctrineORM/Paginator.php
@@ -23,8 +23,6 @@
*
* @author Pablo Díez <pablodip@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
- *
- * @api
*/
class Paginator implements \Countable, \IteratorAggregate
{
@@ -40,8 +38,6 @@ class Paginator implements \Countable, \IteratorAggregate
*
* @param Query|QueryBuilder $query A Doctrine ORM query or query builder.
* @param Boolean $fetchJoinCollection Whether the query joins a collection (true by default).
- *
- * @api
*/
public function __construct($query, $fetchJoinCollection = true)
{
@@ -57,8 +53,6 @@ public function __construct($query, $fetchJoinCollection = true)
* Returns the query
*
* @return Query
- *
- * @api
*/
public function getQuery()
{
View
13 src/Pagerfanta/Adapter/DoctrineORMAdapter.php
@@ -18,8 +18,6 @@
* DoctrineORMAdapter.
*
* @author Christophe Coevoet <stof@notk.org>
- *
- * @api
*/
class DoctrineORMAdapter implements AdapterInterface
{
@@ -31,10 +29,8 @@ class DoctrineORMAdapter implements AdapterInterface
/**
* Constructor.
*
- * @param \Doctrine\ORM\Query|\Doctrine\ORM\QueryBuilder $query A Doctrine ORM query or query builder.
- * @param Boolean $fetchJoinCollection Whether the query joins a collection (true by default).
- *
- * @api
+ * @param \Doctrine\ORM\Query|\Doctrine\ORM\QueryBuilder $query A Doctrine ORM query or query builder.
+ * @param Boolean $fetchJoinCollection Whether the query joins a collection (true by default).
*/
public function __construct($query, $fetchJoinCollection = true)
{
@@ -49,8 +45,6 @@ public function __construct($query, $fetchJoinCollection = true)
* Returns the query
*
* @return Query
- *
- * @api
*/
public function getQuery()
{
@@ -80,7 +74,8 @@ public function getNbResults()
*/
public function getSlice($offset, $length)
{
- $this->paginator->getQuery()
+ $this->paginator
+ ->getQuery()
->setFirstResult($offset)
->setMaxResults($length);
View
6 src/Pagerfanta/Adapter/MandangoAdapter.php
@@ -17,8 +17,6 @@
* MandangoAdapter.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class MandangoAdapter implements AdapterInterface
{
@@ -28,8 +26,6 @@ class MandangoAdapter implements AdapterInterface
* Constructor.
*
* @param Query $query The query.
- *
- * @api
*/
public function __construct(Query $query)
{
@@ -40,8 +36,6 @@ public function __construct(Query $query)
* Returns the query.
*
* @return Query The query.
- *
- * @api
*/
public function getQuery()
{
View
11 src/Pagerfanta/Adapter/MongoAdapter.php
@@ -15,8 +15,6 @@
* MongoAdapter.
*
* @author Sergey Ponomaryov <serg.ponomaryov@gmail.com>
- *
- * @api
*/
class MongoAdapter implements AdapterInterface
{
@@ -26,8 +24,6 @@ class MongoAdapter implements AdapterInterface
* Constructor.
*
* @param \MongoCursor $cursor The cursor.
- *
- * @api
*/
public function __construct(\MongoCursor $cursor)
{
@@ -38,8 +34,6 @@ public function __construct(\MongoCursor $cursor)
* Returns the cursor.
*
* @return \MongoCursor The cursor.
- *
- * @api
*/
public function getCursor()
{
@@ -59,6 +53,9 @@ public function getNbResults()
*/
public function getSlice($offset, $length)
{
- return $this->cursor->limit($length)->skip($offset);
+ $this->cursor->limit($length);
+ $this->cursor->skip($offset);
+
+ return $this->cursor;
}
}
View
30 src/Pagerfanta/Adapter/NullAdapter.php
@@ -24,8 +24,6 @@ class NullAdapter implements AdapterInterface
* Constructor.
*
* @param integer $nbResults Total item count.
- *
- * @api
*/
public function __construct($nbResults = 0)
{
@@ -47,17 +45,35 @@ public function getNbResults()
* Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
*
* {@inheritdoc}
- *
*/
public function getSlice($offset, $length)
{
- if ($offset >= $this->getNbResults()) {
+ if ($offset >= $this->nbResults) {
return array();
}
- $remainItemCount = $this->getNbResults() - $offset;
- $currentItemCount = $remainItemCount > $length ? $length : $remainItemCount;
+ $nullArrayLength = $this->calculateNullArrayLength($offset, $length);
+
+ return $this->createNullArray($nullArrayLength);
+ }
+
+ private function calculateNullArrayLength($offset, $length)
+ {
+ $remainCount = $this->remainCount($offset);
+ if ($length > $remainCount) {
+ return $remainCount;
+ }
- return array_fill(0, $currentItemCount, null);
+ return $length;
+ }
+
+ private function remainCount($offset)
+ {
+ return $this->nbResults - $offset;
+ }
+
+ private function createNullArray($length)
+ {
+ return array_fill(0, $length, null);
}
}
View
10 src/Pagerfanta/Adapter/PropelAdapter.php
@@ -43,7 +43,10 @@ public function getNbResults()
{
$q = clone $this->getQuery();
- return $q->limit(0)->offset(0)->count();
+ $q->limit(0);
+ $q->offset(0);
+
+ return $q->count();
}
/**
@@ -53,6 +56,9 @@ public function getSlice($offset, $length)
{
$q = clone $this->getQuery();
- return $q->limit($length)->offset($offset)->find();
+ $q->limit($length);
+ $q->offset($offset);
+
+ return $q->find();
}
}
View
79 src/Pagerfanta/Adapter/SolariumAdapter.php
@@ -21,41 +21,74 @@
* SolariumAdapter.
*
* @author Igor Wiedler <igor@wiedler.ch>
- *
- * @api
*/
class SolariumAdapter implements AdapterInterface
{
private $client;
private $query;
- private $cachedResultSet;
+ private $resultSet;
/**
* Constructor.
*
* @param Solarium_Client|Client $client A Solarium client.
* @param Solarium_Query_Select|Query $query A Solarium select query.
- *
- * @api
*/
public function __construct($client, $query)
{
- if ((!$query instanceof Query) && (!$query instanceof Solarium_Query_Select)) {
- throw new InvalidArgumentException('The query object should be a Solarium_Query_Select or Solarium\QueryType\Select\Query\Query instance, '.get_class($query).' given');
- }
- if ((!$client instanceof Client) && (!$client instanceof Solarium_Client)) {
- throw new InvalidArgumentException('The client object should be a Solarium_Client or Solarium\Core\Client\Client instance, '.get_class($client).' given');
- }
+ $this->checkClient($client);
+ $this->checkQuery($query);
+
$this->client = $client;
$this->query = $query;
}
+ private function checkClient($client)
+ {
+ if ($this->isClientInvalid($client)) {
+ throw new InvalidArgumentException($this->getClientInvalidMessage($client));
+ }
+ }
+
+ private function isClientInvalid($client)
+ {
+ return !($client instanceof Client) &&
+ !($client instanceof Solarium_Client);
+ }
+
+ private function getClientInvalidMessage($client)
+ {
+ return sprintf('The client object should be a Solarium_Client or Solarium\Core\Client\Client instance, %s given',
+ get_class($client)
+ );
+ }
+
+ private function checkQuery($query)
+ {
+ if ($this->isQueryInvalid($query)) {
+ throw new InvalidArgumentException($this->getQueryInvalidMessage($query));
+ }
+ }
+
+ private function isQueryInvalid($query)
+ {
+ return !($query instanceof Query) &&
+ !($query instanceof Solarium_Query_Select);
+ }
+
+ private function getQueryInvalidMessage($query)
+ {
+ return sprintf('The query object should be a Solarium_Query_Select or Solarium\QueryType\Select\Query\Query instance, %s given',
+ get_class($query)
+ );
+ }
+
/**
* {@inheritdoc}
*/
public function getNbResults()
{
- return $this->getCachedResultSet()->getNumFound();
+ return $this->getResultSet()->getNumFound();
}
/**
@@ -67,18 +100,32 @@ public function getSlice($offset, $length)
->setStart($offset)
->setRows($length);
- $this->cachedResultSet = $this->getResultSet();
+ $this->clearResultSet();
- return $this->cachedResultSet;
+ return $this->getResultSet();
}
private function getResultSet()
{
+ if ($this->isResultSetNotCached()) {
+ $this->resultSet = $this->createResultSet();
+ }
+
+ return $this->resultSet;
+ }
+
+ private function isResultSetNotCached()
+ {
+ return $this->resultSet === null;
+ }
+
+ private function createResultSet()
+ {
return $this->client->select($this->query);
}
- private function getCachedResultSet()
+ private function clearResultSet()
{
- return $this->cachedResultSet ?: $this->getResultSet();
+ $this->resultSet = null;
}
}
View
19 src/Pagerfanta/Exception/NotBooleanException.php
@@ -0,0 +1,19 @@
+<?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\Exception;
+
+/**
+ * @author Pablo Díez <pablodip@gmail.com>
+ */
+class NotBooleanException extends InvalidArgumentException
+{
+}
View
325 src/Pagerfanta/Pagerfanta.php
@@ -13,38 +13,36 @@
use Pagerfanta\Adapter\AdapterInterface;
use Pagerfanta\Exception\LogicException;
+use Pagerfanta\Exception\NotBooleanException;
use Pagerfanta\Exception\NotIntegerMaxPerPageException;
use Pagerfanta\Exception\LessThan1MaxPerPageException;
use Pagerfanta\Exception\NotIntegerCurrentPageException;
use Pagerfanta\Exception\LessThan1CurrentPageException;
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
/**
- * Pagerfanta.
+ * Represents a paginator.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
-class Pagerfanta implements PagerfantaInterface
+class Pagerfanta implements \Countable, \IteratorAggregate, PagerfantaInterface
{
private $adapter;
+ private $allowOutOfRangePages;
+ private $normalizeOutOfRangePages;
private $maxPerPage;
private $currentPage;
private $nbResults;
private $currentPageResults;
- private $nbPages;
/**
- * Constructor.
- *
* @param AdapterInterface $adapter An adapter.
- *
- * @api
*/
public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
+ $this->allowOutOfRangePages = false;
+ $this->normalizeOutOfRangePages = false;
$this->maxPerPage = 10;
$this->currentPage = 1;
}
@@ -53,157 +51,320 @@ public function __construct(AdapterInterface $adapter)
* Returns the adapter.
*
* @return AdapterInterface The adapter.
- *
- * @api
*/
public function getAdapter()
{
return $this->adapter;
}
/**
- * This method implements a fluent interface.
+ * Sets whether or not allow out of range pages.
*
- * {@inheritdoc}
+ * @param Boolean $value
*/
- public function setMaxPerPage($maxPerPage)
+ public function setAllowOutOfRangePages($value)
{
- // tries to normalize from string to integer
- if (is_string($maxPerPage) && (int) $maxPerPage == $maxPerPage) {
- $maxPerPage = (int) $maxPerPage;
+ $this->allowOutOfRangePages = $this->filterBoolean($value);
+
+ return $this;
+ }
+
+ /**
+ * Returns whether or not allow out of range pages.
+ *
+ * @return Boolean
+ */
+ public function allowOutOfRangePages()
+ {
+ return $this->allowOutOfRangePages;
+ }
+
+ /**
+ * Sets whether or not normalize out of range pages.
+ *
+ * @param Boolean $value
+ */
+ public function setNormalizeOutOfRangePages($value)
+ {
+ $this->normalizeOutOfRangePages = $this->filterBoolean($value);
+
+ return $this;
+ }
+
+ /**
+ * Returns whether or not normalize out of range pages.
+ *
+ * @return Boolean
+ */
+ public function normalizeOutOfRangePages()
+ {
+ return $this->normalizeOutOfRangePages;
+ }
+
+ private function filterBoolean($value)
+ {
+ if (!is_bool($value)) {
+ throw new NotBooleanException();
}
+ return $value;
+ }
+
+ /**
+ * Sets the max per page.
+ *
+ * Tries to convert from string and float.
+ *
+ * @param integer $maxPerPage
+ *
+ * @throws NotIntegerMaxPerPageException If the max per page is not an integer even converting.
+ * @throws LessThan1MaxPerPageException If the max per page is less than 1.
+ */
+ public function setMaxPerPage($maxPerPage)
+ {
+ $this->maxPerPage = $this->filterMaxPerPage($maxPerPage);
+ $this->resetForMaxPerPageChange();
+
+ return $this;
+ }
+
+ private function filterMaxPerPage($maxPerPage)
+ {
+ $maxPerPage = $this->toInteger($maxPerPage);
+ $this->checkMaxPerPage($maxPerPage);
+
+ return $maxPerPage;
+ }
+
+ private function checkMaxPerPage($maxPerPage)
+ {
if (!is_int($maxPerPage)) {
throw new NotIntegerMaxPerPageException();
}
if ($maxPerPage < 1) {
throw new LessThan1MaxPerPageException();
}
+ }
+ private function resetForMaxPerPageChange()
+ {
$this->currentPageResults = null;
+ $this->nbResults = null;
$this->nbPages = null;
- $this->maxPerPage = $maxPerPage;
-
- return $this;
}
/**
- * {@inheritdoc}
+ * Returns the max per page.
+ *
+ * @return integer
*/
public function getMaxPerPage()
{
return $this->maxPerPage;
}
/**
- * This method implements a fluent interface.
+ * Sets the current page.
+ *
+ * Tries to convert from string and float.
*
- * {@inheritdoc}
+ * @param integer $currentPage
+ *
+ * @throws NotIntegerCurrentPageException If the current page is not an integer even converting.
+ * @throws LessThan1CurrentPageException If the current page is less than 1.
+ * @throws OutOfRangeCurrentPageException If It is not allowed out of range pages and they are not normalized.
*/
- public function setCurrentPage($currentPage, $allowOutOfRangePages = false, $normalizeOutOfRangePages = false)
+ public function setCurrentPage($currentPage)
+ {
+ $this->useDeprecatedCurrentPageBooleanArguments(func_get_args());
+
+ $this->currentPage = $this->filterCurrentPage($currentPage);
+ $this->resetForCurrentPageChange();
+
+ return $this;
+ }
+
+ private function useDeprecatedCurrentPageBooleanArguments($arguments)
+ {
+ $this->useDeprecatedCurrentPageAllowOutOfRangePagesBooleanArgument($arguments);
+ $this->useDeprecatedCurrentPageNormalizeOutOfRangePagesBooleanArgument($arguments);
+ }
+
+ private function useDeprecatedCurrentPageAllowOutOfRangePagesBooleanArgument($arguments)
{
- // tries to normalize from string to integer
- if ((is_string($currentPage) || is_float($currentPage)) && (int) $currentPage == $currentPage) {
- $currentPage = (int) $currentPage;
+ $index = 1;
+ $method = 'setAllowOutOfRangePages';
+
+ $this->useDeprecatedBooleanArgument($arguments, $index, $method);
+ }
+
+ private function useDeprecatedCurrentPageNormalizeOutOfRangePagesBooleanArgument($arguments)
+ {
+ $index = 2;
+ $method = 'setNormalizeOutOfRangePages';
+
+ $this->useDeprecatedBooleanArgument($arguments, $index, $method);
+ }
+
+ private function useDeprecatedBooleanArgument($arguments, $index, $method)
+ {
+ if (isset($arguments[$index])) {
+ $this->$method($arguments[$index]);
}
+ }
+
+ private function filterCurrentPage($currentPage)
+ {
+ $currentPage = $this->toInteger($currentPage);
+ $this->checkCurrentPage($currentPage);
+ $currentPage = $this->filterOutOfRangeCurrentPage($currentPage);
- // integer?
+ return $currentPage;
+ }
+
+ private function checkCurrentPage($currentPage)
+ {
if (!is_int($currentPage)) {
throw new NotIntegerCurrentPageException();
}
- // out of range pages
- if (!$allowOutOfRangePages && $currentPage > 1) {
- if ($currentPage > $this->getNbPages()) {
- if (!$normalizeOutOfRangePages) {
- throw new OutOfRangeCurrentPageException(sprintf('Page "%d" does not exists. The currentPage must be inferior to "%d"', $currentPage, $this->getNbPages()));
- }
+ if ($currentPage < 1) {
+ throw new LessThan1CurrentPageException();
+ }
+ }
- $currentPage = $this->getNbPages();
- }
+ private function filterOutOfRangeCurrentPage($currentPage)
+ {
+ if ($this->notAllowedCurrentPageOutOfRange($currentPage)) {
+ return $this->normalizeOutOfRangeCurrentPage($currentPage);
}
- // less than 1?
- if ($currentPage < 1) {
- $currentPage = 1;
+ return $currentPage;
+ }
+
+ private function notAllowedCurrentPageOutOfRange($currentPage)
+ {
+ return !$this->allowOutOfRangePages() &&
+ $this->currentPageOutOfRange($currentPage);
+ }
+
+ private function currentPageOutOfRange($currentPage)
+ {
+ return $currentPage > 1 && $currentPage > $this->getNbPages();
+ }
+
+ private function normalizeOutOfRangeCurrentPage($currentPage)
+ {
+ if ($this->normalizeOutOfRangePages()) {
+ return $this->getNbPages();
}
- $this->currentPageResults = null;
- $this->currentPage = $currentPage;
+ throw new OutOfRangeCurrentPageException(sprintf('Page "%d" does not exists. The currentPage must be inferior to "%d"', $currentPage, $this->getNbPages()));
+ }
- return $this;
+ private function resetForCurrentPageChange()
+ {
+ $this->currentPageResults = null;
}
/**
- * {@inheritdoc}
+ * Returns the current page.
+ *
+ * @return integer
*/
public function getCurrentPage()
{
return $this->currentPage;
}
/**
- * {@inheritdoc}
+ * Returns the results for the current page.
+ *
+ * @return array|\Traversable
*/
public function getCurrentPageResults()
{
- if (null === $this->currentPageResults) {
- $offset = ($this->getCurrentPage() - 1) * $this->getMaxPerPage();
- $length = $this->getMaxPerPage();
- $this->currentPageResults = $this->adapter->getSlice($offset, $length);
+ if ($this->notCachedCurrentPageResults()) {
+ $this->currentPageResults = $this->getCurrentPageResultsFromAdapter();
}
return $this->currentPageResults;
}
+ private function notCachedCurrentPageResults()
+ {
+ return $this->currentPageResults === null;
+ }
+
+ private function getCurrentPageResultsFromAdapter()
+ {
+ $offset = $this->calculateOffsetForCurrentPageResults();
+ $length = $this->getMaxPerPage();
+
+ return $this->adapter->getSlice($offset, $length);
+ }
+
+ private function calculateOffsetForCurrentPageResults()
+ {
+ return ($this->getCurrentPage() - 1) * $this->getMaxPerPage();
+ }
+
/**
- * {@inheritdoc}
+ * Returns the number of results.
+ *
+ * @return integer
*/
public function getNbResults()
{
- if (null === $this->nbResults) {
+ if ($this->notCachedNbResults()) {
$this->nbResults = $this->getAdapter()->getNbResults();
}
return $this->nbResults;
}
-
- public function setNbResults($count)
+
+ private function notCachedNbResults()
{
- $this->nbResults = (integer) $count;
+ return $this->nbResults === null;
}
/**
- * {@inheritdoc}
+ * Returns the number of pages.
+ *
+ * @return integer
*/
public function getNbPages()
{
- if (null === $this->nbPages) {
- $this->nbPages = (int) ceil($this->getNbResults() / $this->getMaxPerPage());
- }
-
- return $this->nbPages;
+ return (int) ceil($this->getNbResults() / $this->getMaxPerPage());
}
/**
- * {@inheritdoc}
+ * Returns if the number of results is higher than the max per page.
+ *
+ * @return Boolean
*/
public function haveToPaginate()
{
return $this->getNbResults() > $this->maxPerPage;
}
/**
- * {@inheritdoc}
+ * Returns whether there is previous page or not.
+ *
+ * @return Boolean
*/
public function hasPreviousPage()
{
return $this->currentPage > 1;
}
/**
- * {@inheritdoc}
+ * Returns the previous page.
+ *
+ * @return integer
+ *
+ * @throws LogicException If there is no previous page.
*/
public function getPreviousPage()
{
@@ -215,15 +376,21 @@ public function getPreviousPage()
}
/**
- * {@inheritdoc}
+ * Returns whether there is next page or not.
+ *
+ * @return Boolean
*/
public function hasNextPage()
{
return $this->currentPage < $this->getNbPages();
}
/**
- * {@inheritdoc}
+ * Returns the next page.
+ *
+ * @return integer
+ *
+ * @throws LogicException If there is no next page.
*/
public function getNextPage()
{
@@ -238,8 +405,6 @@ public function getNextPage()
* Implements the \Countable interface.
*
* Return integer The number of results.
- *
- * @api
*/
public function count()
{
@@ -250,21 +415,33 @@ public function count()
* Implements the \IteratorAggregate interface.
*
* Returns an \ArrayIterator instance with the current results.
- *
- * @api
*/
public function getIterator()
{
- $currentPageResults = $this->getCurrentPageResults();
+ $results = $this->getCurrentPageResults();
- if ($currentPageResults instanceof \Iterator) {
- return $currentPageResults;
+ if ($results instanceof \Iterator) {
+ return $results;
}
- if ($currentPageResults instanceof \IteratorAggregate) {
- return $currentPageResults->getIterator();
+ if ($results instanceof \IteratorAggregate) {
+ return $results->getIterator();
}
- return new \ArrayIterator($currentPageResults);
+ return new \ArrayIterator($results);
+ }
+
+ private function toInteger($value)
+ {
+ if ($this->needsToIntegerConvertion($value)) {
+ return (int) $value;
+ }
+
+ return $value;
+ }
+
+ private function needsToIntegerConvertion($value)
+ {
+ return (is_string($value) || is_float($value)) && (int) $value == $value;
}
}
View
132 src/Pagerfanta/PagerfantaInterface.php
@@ -12,134 +12,8 @@
namespace Pagerfanta;
/**
- * PagerfantaInterface.
- *
- * @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
+ * Deprecated.
@stof
stof added a note Apr 4, 2013

this should be marked as @deprecated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
*/
-interface PagerfantaInterface extends \Countable, \IteratorAggregate
+interface PagerfantaInterface
{
- /**
- * Sets the max per page.
- *
- * @param integer $maxPerPage The max per page.
- *
- * @api
- */
- function setMaxPerPage($maxPerPage);
-
- /**
- * Returns the max per page.
- *
- * Tries to normalize from string to integer.
- *
- * @return integer The max per page.
- *
- * @throws NotIntegerMaxPerPageException If the max per page is not an integer even normalizing.
- * @throws LessThan1MaxPerPageException If the max per page is less than 1.
- *
- * @api
- */
- function getMaxPerPage();
-
- /**
- * Sets the current page.
- *
- * @param integer $currentPage The current page.
- * @param Boolean $allowOutOfRangePages Whether to allow out of range pages or not (false by default).
- * @param Boolean $normalizeOutOfRangePages Whether to show the last page instead (false by default).
- *
- * @throws NotIntegerCurrentPageException If the current page is not an integer even normalizing.
- * @throws LessThan1CurrentPageException If the current page is less than 1.
- * @throws OutOfRangeCurrentPageException If It is not allowed out of range pages and they are not normalized.
- *
- * @api
- */
- function setCurrentPage($currentPage);
-
- /**
- * Returns the current page.
- *
- * @return integer The current page.
- *
- * @api
- */
- function getCurrentPage();
-
- /**
- * Returns the results for the current page.
- *
- * @return array|\Traversable The results.
- *
- * @api
- */
- function getCurrentPageResults();
-
- /**
- * Returns the number of results.
- *
- * @return integer The number of results.
- *
- * @api
- */
- function getNbResults();
-
- /**
- * Returns the number of pages.
- *
- * @return integer The number of pages.
- *
- * @api
- */
- function getNbPages();
-
- /**
- * Returns whether have to paginate or not.
- *
- * This is true if the number of results is higher than the max per page.
- *
- * @return Boolean Whether have to paginate or not.
- */
- function haveToPaginate();
-
- /**
- * Returns whether there is previous page or not.
- *
- * @return Boolean Whether there is previous page or not.
- *
- * @api
- */
- function hasPreviousPage();
-
- /**
- * Returns the previous page.
- *
- * @return integer The previous page.
- *
- * @throws PagerfantaException If there is not previous page.
- *
- * @api
- */
- function getPreviousPage();
-
- /**
- * Returns whether there is next page or not.
- *
- * @return Boolean Whether there is previous page or not.
- *
- * @api
- */
- function hasNextPage();
-
- /**
- * Returns the next page.
- *
- * @return integer The next page.
- *
- * @throws PagerfantaException If there is not next page.
- *
- * @api
- */
- function getNextPage();
-}
+}
View
239 src/Pagerfanta/View/DefaultView.php
@@ -12,103 +12,210 @@
namespace Pagerfanta\View;
use Pagerfanta\PagerfantaInterface;
+use Pagerfanta\View\Template\DefaultTemplate;
/**
- * DefaultInterface.
- *
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class DefaultView implements ViewInterface
{
+ private $pagerfanta;
+ private $template;
+
+ private $proximity;
+
+ private $currentPage;
+ private $nbPages;
+
+ private $startPage;
+ private $endPage;
+
/**
* {@inheritdoc}
*/
public function render(PagerfantaInterface $pagerfanta, $routeGenerator, array $options = array())
{
- $options = array_merge(array(
- 'proximity' => 2,
- 'previous_message' => 'Previous',
- 'next_message' => 'Next',
- 'css_disabled_class' => 'disabled',
- 'css_dots_class' => 'dots',
- 'css_current_class' => 'current',
- ), $options);
+ $this->initializePagerfanta($pagerfanta);
+ $this->initializeOptions($options);
+
+ $this->template = $this->createTemplate($routeGenerator, $options);
+
+ return $this->generate();
+ }
+
+ private function initializePagerfanta($pagerfanta)
+ {
+ $this->pagerfanta = $pagerfanta;
+
+ $this->currentPage = $pagerfanta->getCurrentPage();
+ $this->nbPages = $pagerfanta->getNbPages();
+ }
+
+ private function initializeOptions($options)
+ {
+ $this->proximity = isset($options['proximity']) ?
+ $options['proximity'] :
+ $this->defaultProximity();
+ }
+
+ protected function defaultProximity()
+ {
+ return 2;
+ }
+
+ protected function createTemplate($routeGenerator, $options)
+ {
+ return new DefaultTemplate($routeGenerator, $options);
+ }
+
+ private function generate()
+ {
+ $pages = $this->generatePages();
+
+ return $this->generateContainer($pages);
+ }
+
+ private function generateContainer($pages)
+ {
+ return str_replace('%pages%', $pages, $this->template->container());
+ }
- $currentPage = $pagerfanta->getCurrentPage();
+ private function generatePages()
+ {
+ $this->calculateStartAndEndPage();
+
+ return $this->previous().
+ $this->first().
+ $this->secondIfStartIs3().
+ $this->dotsIfStartIsOver3().
+ $this->pages().
+ $this->dotsIfEndIsUnder3ToLast().
+ $this->secondToLastIfEndIs3ToLast().
+ $this->last().
+ $this->next();
+ }
- $startPage = $currentPage - $options['proximity'];
- $endPage = $currentPage + $options['proximity'];
+ private function calculateStartAndEndPage()
+ {
+ $startPage = $this->currentPage - $this->proximity;
+ $endPage = $this->currentPage + $this->proximity;
- if ($startPage < 1) {
- $endPage = min($endPage + (1 - $startPage), $pagerfanta->getNbPages());
+ if ($this->startPageUnderflow($startPage)) {
+ $endPage = $this->calculateEndPageForStartPageUnderflow($startPage, $endPage);
$startPage = 1;
}
- if ($endPage > $pagerfanta->getNbPages()) {
- $startPage = max($startPage - ($endPage - $pagerfanta->getNbPages()), 1);
- $endPage = $pagerfanta->getNbPages();
+ if ($this->endPageOverflow($endPage)) {
+ $startPage = $this->calculateStartPageForEndPageOverflow($startPage, $endPage);
+ $endPage = $this->nbPages;
}
- $pages = array();
+ $this->startPage = $startPage;
+ $this->endPage = $endPage;
+ }
+
+ private function startPageUnderflow($startPage)
+ {
+ return $startPage < 1;
+ }
+
+ private function endPageOverflow($endPage)
+ {
+ return $endPage > $this->nbPages;
+ }
- // previous
- if ($pagerfanta->hasPreviousPage()) {
- $pages[] = array($pagerfanta->getPreviousPage(), $options['previous_message']);
- } else {
- $pages[] = sprintf('<span class="%s">%s</span>', $options['css_disabled_class'], $options['previous_message']);
+ private function calculateEndPageForStartPageUnderflow($startPage, $endPage)
+ {
+ return min($endPage + (1 - $startPage), $this->nbPages);
+ }
+
+ private function calculateStartPageForEndPageOverflow($startPage, $endPage)
+ {
+ return max($startPage - ($endPage - $this->nbPages), 1);
+ }
+
+ private function previous()
+ {
+ if ($this->pagerfanta->hasPreviousPage()) {
+ return $this->template->previousEnabled($this->pagerfanta->getPreviousPage());
}
- // first
- if ($startPage > 1) {
- $pages[] = array(1, 1);
- if (3 == $startPage) {
- $pages[] = array(2, 2);
- } elseif (2 != $startPage) {
- $pages[] = sprintf('<span class="%s">...</span>', $options['css_dots_class']);
- }
+ return $this->template->previousDisabled();
+ }
+
+ private function first()
+ {
+ if ($this->startPage > 1) {
+ return $this->template->first();
}
+ }
- // pages
- for ($page = $startPage; $page <= $endPage; $page++) {
- if ($page == $currentPage) {
- $pages[] = sprintf('<span class="%s">%s</span>', $options['css_current_class'], $page);
- } else {
- $pages[] = array($page, $page);
- }
+ private function secondIfStartIs3()
+ {
+ if ($this->startPage == 3) {
+ return $this->template->page(2);
}
+ }
- // last
- if ($pagerfanta->getNbPages() > $endPage) {
- if ($pagerfanta->getNbPages() > ($endPage + 1)) {
- if ($pagerfanta->getNbPages() > ($endPage + 2)) {
- $pages[] = sprintf('<span class="%s">...</span>', $options['css_dots_class']);
- } else {
- $pages[] = array($endPage + 1, $endPage + 1);
- }
- }
-
- $pages[] = array($pagerfanta->getNbPages(), $pagerfanta->getNbPages());
+ private function dotsIfStartIsOver3()
+ {
+ if ($this->startPage > 3) {
+ return $this->template->separator();
}
+ }
+
+ private function pages()
+ {
+ $pages = '';
- // next
- if ($pagerfanta->hasNextPage()) {
- $pages[] = array($pagerfanta->getNextPage(), $options['next_message']);
- } else {
- $pages[] = sprintf('<span class="%s">%s</span>', $options['css_disabled_class'], $options['next_message']);
+ foreach (range($this->startPage, $this->endPage) as $page) {
+ $pages .= $this->page($page);
}
- // process
- $pagesHtml = '';
- foreach ($pages as $page) {
- if (is_string($page)) {
- $pagesHtml .= $page;
- } else {
- $pagesHtml .= '<a href="'.$routeGenerator($page[0]).'">'.$page[1].'</a>';
- }
+ return $pages;
+ }
+
+ private function page($page)
+ {
+ if ($page == $this->currentPage) {
+ return $this->template->current($page);
+ }
+
+ return $this->template->page($page);
+ }
+
+ private function dotsIfEndIsUnder3ToLast()
+ {
+ if ($this->endPage < $this->toLast(3)) {
+ return $this->template->separator();
+ }
+ }
+
+ private function secondToLastIfEndIs3ToLast()
+ {
+ if ($this->endPage == $this->toLast(3)) {
+ return $this->template->page($this->toLast(2));
+ }
+ }
+
+ private function toLast($n)
+ {
+ return $this->pagerfanta->getNbPages() - ($n - 1);
+ }
+
+ private function last()
+ {
+ if ($this->pagerfanta->getNbPages() > $this->endPage) {
+ return $this->template->page($this->pagerfanta->getNbPages());
+ }
+ }
+
+ private function next()
+ {
+ if ($this->pagerfanta->hasNextPage()) {
+ return $this->template->nextEnabled($this->pagerfanta->getNextPage());
}
- return '<nav>'.$pagesHtml.'</nav>';
+ return $this->template->nextDisabled();
}
/**
View
8 src/Pagerfanta/View/OptionableView.php
@@ -19,8 +19,6 @@
* This view renders another view with a default options to reuse them in a project.
*
* @author Pablo Díez <pablodip@gmail.com>
- *
- * @api
*/
class OptionableView implements ViewInterface
{
@@ -31,11 +29,9 @@ class OptionableView implements ViewInterface
* Constructor.
*
* @param ViewInterface $view A view.
- * @param array $options An array of default options (optional).
- *
- * @api
+ * @param array $options An array of default options.
*/
- public function __construct(ViewInterface $view, array $defaultOptions = array())
+ public function __construct(ViewInterface $view, array $defaultOptions)
{
$this->view = $view;
$this->defaultOptions = $defaultOptions;
View
89 src/Pagerfanta/View/Template/DefaultTemplate.php
@@ -0,0 +1,89 @@
+<?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\View\Template;
+
+/**
+ * @author Pablo Díez <pablodip@gmail.com>
+ */
+class DefaultTemplate extends Template
+{
+ static protected $defaultOptions = array(
+ 'previous_message' => 'Previous',
+ 'next_message' => 'Next',
+ 'css_disabled_class' => 'disabled',
+ 'css_dots_class' => 'dots',
+ 'css_current_class' => 'current',
+ 'dots_text' => '...'
+ );
+
+ public function container()
+ {
+ return '<nav>%pages%</nav>';
+ }
+
+ public function page($page)
+ {
+ $text = $page;
+
+ return $this->pageWithText($page, $text);
+ }
+
+ public function pageWithText($page, $text)
+ {
+ return sprintf('<a href="%s">%s</a>', $this->generateRoute($page), $text);
+ }
+
+ public function previousDisabled()
+ {
+ return $this->generateSpan($this->option('css_disabled_class'), $this->option('previous_message'));
+ }
+
+ public function previousEnabled($page)
+ {
+ return $this->pageWithText($page, $this->option('previous_message'));
+ }
+
+ public function nextDisabled()
+ {
+ return $this->generateSpan($this->option('css_disabled_class'), $this->option('next_message'));
+ }
+
+ public function nextEnabled($page)
+ {
+ return $this->pageWithText($page, $this->option('next_message'));
+ }
+
+ public function first()
+ {
+ return $this->page(1);
+ }
+
+ public function last($page)
+ {
+ return $this->page($page);
+ }
+
+ public function current($page)
+ {
+ return $this->generateSpan($this->option('css_current_class'), $page);
+ }
+
+ public function separator()
+ {
+ return $this->generateSpan($this->option('css_dots_class'), $this->option('dots_text'));
+ }
+
+ private function generateSpan($class, $page)
+ {
+ return sprintf('<span class="%s">%s</span>', $class, $page);
+ }
+}
View
43 src/Pagerfanta/View/Template/Template.php
@@ -0,0 +1,43 @@
+<?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\View\Template;
+
+/**
+ * @author Pablo Díez <pablodip@gmail.com>
+ */
+abstract class Template implements TemplateInterface
+{
+ static protected $defaultOptions = array();
+
+ private $routeGenerator;
+ private $options;
+
+ public function __construct($routeGenerator, array $options = array())
+ {
+ $this->routeGenerator = $routeGenerator;
+ $this->options = array_merge(static::$defaultOptions, $options);
+ }
+
+ protected function generateRoute($page)
+ {
+ return call_user_func($this->routeGenerator, $page);
+ }
+
+ protected function option($name)
+ {
+ if (!isset($this->options[$name])) {
+ throw new \InvalidArgumentException(sprintf('The option "%s" does not exist.', $name));
+ }
+
+ return $this->options[$name];
+ }
+}
View
40 src/Pagerfanta/View/Template/TemplateInterface.php
@@ -0,0 +1,40 @@
+<?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\View\Template;
+
+/**
+ * @author Pablo Díez <pablodip@gmail.com>
+ */
+interface TemplateInterface
+{
+ function container();
+
+ function page($page);
+
+ function pageWithText($page, $text);
+
+ function previousDisabled();
+
+ function previousEnabled($page);
+
+ function nextDisabled();
+
+ function nextEnabled($page);
+
+ function first();
+
+ function last($page);
+
+ function current($page);
+
+ function separator();
+}
View
139 src/Pagerfanta/View/Template/TwitterBootstrapTemplate.php
@@ -0,0 +1,139 @@
+<?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\View\Template;
+
+/**
+ * @author Pablo Díez <pablodip@gmail.com>
+ */
+class TwitterBootstrapTemplate extends Template
+{
+ static protected $defaultOptions = array(
+ 'prev_message' => '&larr; Previous',
+ 'prev_disabled_href' => '',
+ 'next_message' => 'Next &rarr;',
+ 'next_disabled_href' => '',
+ 'dots_message' => '&hellip;',
+ 'dots_href' => '',
+ 'css_container_class' => 'pagination',
+ 'css_prev_class' => 'prev',
+ 'css_next_class' => 'next',
+ 'css_disabled_class' => 'disabled',
+ 'css_dots_class' => 'disabled',
+ 'css_active_class' => 'active'
+ );
+
+ public function container()
+ {
+ return sprintf('<div class="%s"><ul>%%pages%%</ul></div>',
+ $this->option('css_container_class')
+ );
+ }
+
+ public function page($page)
+ {
+ $text = $page;
+
+ return $this->pageWithText($page, $text);
+ }
+
+ public function pageWithText($page, $text)
+ {
+ $class = null;
+
+ return $this->pageWithTextAndClass($page, $text, $class);
+ }
+
+ private function pageWithTextAndClass($page, $text, $class)
+ {
+ $href = $this->generateRoute($page);
+
+ return $this->li($class, $href, $text);
+ }
+
+ public function previousDisabled()
+ {
+ $class = $this->previousDisabledClass();
+ $href = $this->option('prev_disabled_href');
+ $text = $this->option('prev_message');
+
+ return $this->li($class, $href, $text);
+ }
+
+ private function previousDisabledClass()
+ {
+ return $this->option('css_prev_class').' '.$this->option('css_disabled_class');
+ }
+
+ public function previousEnabled($page)
+ {
+ $text = $this->option('prev_message');
+ $class = $this->option('css_prev_class');
+
+ return $this->pageWithTextAndClass($page, $text, $class);
+ }
+
+ public function nextDisabled()
+ {
+ $class = $this->nextDisabledClass();
+ $href = $this->option('next_disabled_href');
+ $text = $this->option('next_message');
+
+ return $this->li($class, $href, $text);
+ }
+
+ private function nextDisabledClass()
+ {
+ return $this->option('css_next_class').' '.$this->option('css_disabled_class');
+ }
+
+ public function nextEnabled($page)
+ {
+ $text = $this->option('next_message');
+ $class = $this->option('css_next_class');
+
+ return $this->pageWithTextAndClass($page, $text, $class);
+ }
+
+ public function first()
+ {
+ return $this->page(1);
+ }
+
+ public function last($page)
+ {
+ return $this->page($page);
+ }
+
+ public function current($page)
+ {
+ $text = $page;
+ $class = $this->option('css_active_class');
+
+ return $this->pageWithTextAndClass($page, $text, $class);
+ }
+
+ public function separator()
+ {
+ $class = $this->option('css_dots_class');
+ $href = $this->option('dots_href');
+ $text = $this->option('dots_message');
+
+ return $this->li($class, $href, $text);
+ }
+
+ private function li($class, $href, $text)
+ {
+ $liClass = $class ? sprintf(' class="%s"', $class) : '';
+
+ return sprintf('<li%s><a href="%s">%s</a></li>', $liClass, $href, $text);
+ }
+}
View
105 src/Pagerfanta/View/TwitterBootstrapView.php
@@ -12,115 +12,28 @@
namespace Pagerfanta\View;
use Pagerfanta\PagerfantaInterface;
+use Pagerfanta\View\Template\TwitterBootstrapTemplate;
/**
* TwitterBootstrapView.
*
- * View that can be used with the pagination module
+ * View that can be used with the pagination module
* from the Twitter Bootstrap CSS Toolkit
* http://twitter.github.com/bootstrap/
*
* @author Pablo Díez <pablodip@gmail.com>
* @author Jan Sorgalla <jsorgalla@gmail.com>
- *
- * @api
*/
-class TwitterBootstrapView implements ViewInterface
+class TwitterBootstrapView extends DefaultView
{
- /**
- * {@inheritdoc}
- */
- public function render(PagerfantaInterface $pagerfanta, $routeGenerator, array $options = array())
+ protected function createTemplate($routeGenerator, $options)
{
- $options = array_merge(array(
- 'proximity' => 3,
- 'prev_message' => '&larr; Previous',
- 'prev_disabled_href' => '',
- 'next_message' => 'Next &rarr;',
- 'next_disabled_href' => '',
- 'dots_message' => '&hellip;',
- 'dots_href' => '',
- 'css_container_class' => 'pagination',
- 'css_prev_class' => 'prev',
- 'css_next_class' => 'next',
- 'css_disabled_class' => 'disabled',
- 'css_dots_class' => 'disabled',
- 'css_active_class' => 'active',
- ), $options);
-
- $currentPage = $pagerfanta->getCurrentPage();
-
- $startPage = $currentPage - $options['proximity'];
- $endPage = $currentPage + $options['proximity'];
-
- if ($startPage < 1) {
- $endPage = min($endPage + (1 - $startPage), $pagerfanta->getNbPages());
- $startPage = 1;
- }
- if ($endPage > $pagerfanta->getNbPages()) {
- $startPage = max($startPage - ($endPage - $pagerfanta->getNbPages()), 1);
- $endPage = $pagerfanta->getNbPages();
- }
-
- $pages = array();
-
- // previous
- $class = $options['css_prev_class'];
- $url = $options['prev_disabled_href'];
- if (!$pagerfanta->hasPreviousPage()) {
- $class .= ' '.$options['css_disabled_class'];
- } else {
- $url = $routeGenerator($pagerfanta->getPreviousPage());
- }
-
- $pages[] = sprintf('<li class="%s"><a href="%s">%s</a></li>', $class, $url, $options['prev_message']);
-
-
- // first
- if ($startPage > 1) {
- $pages[] = sprintf('<li><a href="%s">%s</a></li>', $routeGenerator(1), 1);
- if (3 == $startPage) {
- $pages[] = sprintf('<li><a href="%s">%s</a></li>', $routeGenerator(2), 2);
- } elseif (2 != $startPage) {
- $pages[] = sprintf('<li class="%s"><a href="%s">%s</a></li>', $options['css_dots_class'], $options['dots_href'], $options['dots_message']);
- }
- }
-
- // pages
- for ($page = $startPage; $page <= $endPage; $page++) {
- $class = '';
- if ($page == $currentPage) {
- $class = sprintf(' class="%s"', $options['css_active_class']);
- }
-
- $pages[] = sprintf('<li%s><a href="%s">%s</a></li>', $class, $routeGenerator($page), $page);
- }
-
- // last
- if ($pagerfanta->getNbPages() > $endPage) {
- if ($pagerfanta->getNbPages() > ($endPage + 1)) {
- if ($pagerfanta->getNbPages() > ($endPage + 2)) {
- $pages[] = sprintf('<li class="%s"><a href="%s">%s</a></li>', $options['css_dots_class'], $options['dots_href'], $options['dots_message']);
- } else {
- $pages[] = sprintf('<li><a href="%s">%s</a></li>', $routeGenerator($endPage + 1), $endPage + 1);
- }
- }
-
- $pages[] = sprintf('<li><a href="%s">%s</a></li>', $routeGenerator($pagerfanta->getNbPages()), $pagerfanta->getNbPages());
- }
-
- // next
- $class = $options['css_next_class'];
- $url = $options['next_disabled_href'];
- if (!$pagerfanta->hasNextPage()) {
- $class .= ' '.$options['css_disabled_class'];
- } else {
- $url = $routeGenerator($pagerfanta->getNextPage());