diff --git a/src/Pagerfanta/Adapter/ElasticaAdapter.php b/src/Pagerfanta/Adapter/ElasticaAdapter.php index 93d2c06e..236fe1f0 100644 --- a/src/Pagerfanta/Adapter/ElasticaAdapter.php +++ b/src/Pagerfanta/Adapter/ElasticaAdapter.php @@ -14,7 +14,7 @@ use Elastica\Query; use Elastica\SearchableInterface; -class ElasticaAdapter implements AdapterInterface +class ElasticaAdapter implements LazyAdapterInterface { /** * @var Query diff --git a/src/Pagerfanta/Adapter/LazyAdapterInterface.php b/src/Pagerfanta/Adapter/LazyAdapterInterface.php new file mode 100644 index 00000000..4a8ea9aa --- /dev/null +++ b/src/Pagerfanta/Adapter/LazyAdapterInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Pagerfanta\Adapter; + +/** + * LazyAdapterInterface that marks adapter lazy. + * + * @author Konstantin Myakshin + */ +interface LazyAdapterInterface extends AdapterInterface +{ + +} diff --git a/src/Pagerfanta/Pagerfanta.php b/src/Pagerfanta/Pagerfanta.php index 36858fd9..2ac17178 100644 --- a/src/Pagerfanta/Pagerfanta.php +++ b/src/Pagerfanta/Pagerfanta.php @@ -13,6 +13,7 @@ use OutOfBoundsException; use Pagerfanta\Adapter\AdapterInterface; +use Pagerfanta\Adapter\LazyAdapterInterface; use Pagerfanta\Exception\LogicException; use Pagerfanta\Exception\NotBooleanException; use Pagerfanta\Exception\NotIntegerException; @@ -227,7 +228,9 @@ private function filterCurrentPage($currentPage) { $currentPage = $this->toInteger($currentPage); $this->checkCurrentPage($currentPage); - $currentPage = $this->filterOutOfRangeCurrentPage($currentPage); + if (!$this->adapter instanceof LazyAdapterInterface) { + $currentPage = $this->filterOutOfRangeCurrentPage($currentPage); + } return $currentPage; } @@ -318,7 +321,18 @@ private function getCurrentPageResultsFromAdapter() $offset = $this->calculateOffsetForCurrentPageResults(); $length = $this->getMaxPerPage(); - return $this->adapter->getSlice($offset, $length); + $slice = $this->adapter->getSlice($offset, $length); + + if ($this->adapter instanceof LazyAdapterInterface) { + $page = $this->filterOutOfRangeCurrentPage($this->getCurrentPage()); + if ($page != $this->getCurrentPage()) { + $this->setCurrentPage($page); + + return $this->getCurrentPageResultsFromAdapter(); + } + } + + return $slice; } private function calculateOffsetForCurrentPageResults() diff --git a/tests/Pagerfanta/Tests/PagerfantaTest.php b/tests/Pagerfanta/Tests/PagerfantaTest.php index ff3fb503..4020b815 100644 --- a/tests/Pagerfanta/Tests/PagerfantaTest.php +++ b/tests/Pagerfanta/Tests/PagerfantaTest.php @@ -672,6 +672,42 @@ public function testPagerfantaShouldImplementIteratorAggregateInterface() $this->assertInstanceOf('IteratorAggregate', $this->pagerfanta); } + public function testLazyAdapterDoNotCallsGetNbResultsOnSetCurrentPage() + { + $adapter = $this->getMock('Pagerfanta\Adapter\LazyAdapterInterface'); + + $adapter + ->expects($this->never()) + ->method('getNbResults'); + + $pagerfanta = new Pagerfanta($adapter); + $pagerfanta->setMaxPerPage(10); + $pagerfanta->setCurrentPage(3); + } + + /** + * @expectedException Pagerfanta\Exception\OutOfRangeCurrentPageException + */ + public function testLazyAdapterCallsGetNbResultsOnGetCurrentPageResults() + { + $adapter = $this->getMock('Pagerfanta\Adapter\LazyAdapterInterface'); + + $adapter + ->expects($this->any()) + ->method('getSlice') + ->will($this->returnValue(range(0, 9))); + + $adapter + ->expects($this->any()) + ->method('getNbResults') + ->will($this->returnValue(20)); + + $pagerfanta = new Pagerfanta($adapter); + $pagerfanta->setMaxPerPage(10); + $pagerfanta->setCurrentPage(3); + $pagerfanta->getCurrentPageResults(); + } + private function assertResetCurrentPageResults($callback) { $this->setAdapterNbResultsAny(100);