├── .github └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── composer.json ├── docs └── symfony_integration.md ├── phpunit.xml ├── src └── Porpaginas │ ├── Arrays │ ├── ArrayPage.php │ └── ArrayResult.php │ ├── Doctrine │ └── ORM │ │ ├── ORMQueryPage.php │ │ └── ORMQueryResult.php │ ├── Iterator │ └── IteratorPage.php │ ├── KnpPager │ └── PorpaginasSubscriber.php │ ├── Page.php │ ├── Pager.php │ ├── Pagerfanta │ └── PorpaginasAdapter.php │ ├── Result.php │ └── Twig │ ├── KnpPagerRenderingAdapter.php │ ├── PagerfantaRenderingAdapter.php │ ├── PorpaginasExtension.php │ └── RenderingAdapter.php └── tests └── Porpaginas ├── AbstractResultTestCase.php ├── ArrayTest.php ├── DoctrineORMQueryTest.php ├── KnpPager └── PorpaginasSubscriberTest.php ├── PagerTest.php ├── Pagerfanta └── PorpaginasAdapterTest.php └── Twig ├── KnpPagerRenderingAdapterTest.php └── PorpaginasExtensionTest.php /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: CI 3 | jobs: 4 | tests: 5 | name: Tests 6 | runs-on: ubuntu-latest 7 | strategy: 8 | matrix: 9 | php-versions: ['8.0', '8.1', '8.2'] 10 | 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v1 14 | 15 | - name: Setup PHP 16 | uses: shivammathur/setup-php@v2 17 | with: 18 | php-version: ${{ matrix.php-versions }} 19 | tools: "cs2pr" 20 | 21 | - name: "Cache dependencies installed with composer" 22 | uses: "actions/cache@v1" 23 | with: 24 | path: "~/.composer/cache" 25 | key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" 26 | restore-keys: "php-${{ matrix.php-version }}-composer-locked-" 27 | 28 | - name: "Composer" 29 | run: "composer update --prefer-stable" 30 | 31 | - name: "PHPUnit" 32 | run: "php vendor/bin/phpunit" 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor 3 | .idea 4 | .phpunit.result.cache 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Porpaginas 2 | 3 | [![Build Status](https://travis-ci.org/beberlei/porpaginas.svg)](https://travis-ci.org/beberlei/porpaginas) 4 | 5 | This library solves a bunch of issues that comes up with APIs of Repository 6 | classes alot: 7 | 8 | - You need different methods for paginatable and non-paginatable finder 9 | methods. 10 | - You need to expose the underlying data-source and return query objects from 11 | your repository. 12 | - Serialization of paginators should be easily possible for REST APIs 13 | 14 | Both Pagerfanta and KnpLabs Pager don't solve this issue and their APIs are 15 | really problematic in this regard. You need to return the query objects or 16 | adapters for paginators from your repositories to get it working and then use 17 | an API on the controller side to turn them into a paginated result set. 18 | 19 | Porpaginas solves this by introducing a sane abstraction for paginated results. 20 | For rendering purposes you can integrate with either Pagerfanta or KnpLabs 21 | Pager, this library is not about reimplementating the view part of pagination. 22 | 23 | Central part of this library is the interface `Result`: 24 | 25 | ```php 26 | createQueryBuilder('u')->orderBy('u.username'); 114 | 115 | return new ORMQueryResult($qb); 116 | } 117 | } 118 | 119 | class UserController 120 | { 121 | /** 122 | * @var UserRepository 123 | */ 124 | private $userRepository; 125 | 126 | public function listAction(Request $request) 127 | { 128 | $result = $this->userRepository->findAllUsers(); 129 | // no filtering by page, iterate full result 130 | 131 | return array('users' => $result); 132 | } 133 | 134 | public function porpaginasListAction(Request $request) 135 | { 136 | $result = $this->userRepository->findAllUsers(); 137 | 138 | $paginator = $result->take(($request->get('page')-1) * 20, 20); 139 | 140 | return array('users' => $paginator); 141 | } 142 | } 143 | ``` 144 | 145 | Now in the template for `porpaginasListAction` using the `porpaginas` Twig 146 | extension for example: 147 | 148 | ```jinja 149 | We found a total of {{ porpaginas_total(users) }} users: 150 | 151 | 156 | 157 | {{ porpaginas_render(users) }} 158 | ``` 159 | 160 | ## Pager Library Support 161 | 162 | * For Pagerfanta use the ``Porpaginas\Pagerfanta\PorpaginasAdapter`` and pass it a result as first argument. 163 | 164 | ## Embedded Pager 165 | 166 | You can use the `Porpaginas\Pager` class to help you get a slice of previous and next pages to display: 167 | 168 | ``` php 169 | $pager = Porpaginas\Pager::fromPage($page); 170 | ``` 171 | 172 | Passed to a twig template: 173 | 174 | ``` jinja 175 | 184 | ``` 185 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beberlei/porpaginas", 3 | "description": "Library that generically solves several pagination issues with DAO/repository abstractions.", 4 | "keywords": ["page","paging", "paginator", "pagination"], 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"} 9 | ], 10 | "autoload": { 11 | "psr-0": {"Porpaginas\\": "src/"} 12 | }, 13 | "autoload-dev": { 14 | "psr-0": {"Porpaginas\\": "tests/"} 15 | }, 16 | "require": { 17 | "php": "^8" 18 | }, 19 | "require-dev": { 20 | "doctrine/orm": ">=2.2", 21 | "pagerfanta/pagerfanta": "@stable", 22 | "knplabs/knp-components": "@stable", 23 | "symfony/event-dispatcher": "@stable", 24 | "twig/twig": "@stable", 25 | "phake/phake": "@stable", 26 | "phpunit/phpunit": "^7|^8|^9", 27 | "symfony/cache": "@stable" 28 | }, 29 | "suggest": { 30 | "pagerfanta/pagerfanta": "For rendering pagination with Pagerfanta" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/symfony_integration.md: -------------------------------------------------------------------------------- 1 | # Symfony Integration 2 | 3 | Integrating Porpaginas into a Symfony application is fairly easy. There is [PorpaginasBundle](https://github.com/fightmaster/PorpaginasBundle), but you can to register some of the services manually also. 4 | 5 | ```xml 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | viewname 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests/ 6 | 7 | 8 | 9 | 10 | 11 | src 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Porpaginas/Arrays/ArrayPage.php: -------------------------------------------------------------------------------- 1 | slice = $slice; 29 | $this->offset = $offset; 30 | $this->limit = $limit; 31 | $this->totalCount = $totalCount; 32 | } 33 | 34 | /** 35 | * @return int 36 | */ 37 | public function getCurrentOffset() 38 | { 39 | return $this->offset; 40 | } 41 | 42 | /** 43 | * @return int 44 | */ 45 | public function getCurrentPage() 46 | { 47 | return (int) floor($this->offset / $this->limit) + 1; 48 | } 49 | 50 | /** 51 | * @return int 52 | */ 53 | public function getCurrentLimit() 54 | { 55 | return $this->limit; 56 | } 57 | 58 | /** 59 | * Return the number of results on the currrent page of the {@link Result}. 60 | * 61 | * @return int 62 | */ 63 | public function count() 64 | { 65 | return count($this->slice); 66 | } 67 | 68 | /** 69 | * Return the number of ALL results in the paginatable of {@link Result}. 70 | * 71 | * @return int 72 | */ 73 | public function totalCount() 74 | { 75 | return $this->totalCount; 76 | } 77 | 78 | /** 79 | * Return an iterator over selected windows of results of the paginatable. 80 | * 81 | * @return Iterator 82 | */ 83 | public function getIterator() 84 | { 85 | return new ArrayIterator($this->slice); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Porpaginas/Arrays/ArrayResult.php: -------------------------------------------------------------------------------- 1 | data = $data; 26 | } 27 | 28 | /** 29 | * @param int $offset 30 | * @return \Porpaginas\Page 31 | */ 32 | public function take($offset, $limit) 33 | { 34 | return new ArrayPage( 35 | array_slice($this->data, $offset, $limit), 36 | $offset, 37 | $limit, 38 | count($this->data) 39 | ); 40 | } 41 | 42 | /** 43 | * Return the number of all results in the paginatable. 44 | 45 | * @return int 46 | */ 47 | public function count() 48 | { 49 | return count($this->data); 50 | } 51 | 52 | /** 53 | * Return an iterator over all results of the paginatable. 54 | * 55 | * @return Iterator 56 | */ 57 | public function getIterator() 58 | { 59 | return new ArrayIterator($this->data); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Porpaginas/Doctrine/ORM/ORMQueryPage.php: -------------------------------------------------------------------------------- 1 | paginator = $paginator; 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getCurrentOffset() 41 | { 42 | return $this->paginator->getQuery()->getFirstResult(); 43 | } 44 | 45 | /** 46 | * @return int 47 | */ 48 | public function getCurrentPage() 49 | { 50 | return (int) floor($this->getCurrentOffset() / $this->getCurrentLimit()) + 1; 51 | } 52 | 53 | /** 54 | * @return int 55 | */ 56 | public function getCurrentLimit() 57 | { 58 | return $this->paginator->getQuery()->getMaxResults(); 59 | } 60 | 61 | /** 62 | * Return the number of results on the currrent page of the {@link Result}. 63 | * 64 | * @return int 65 | */ 66 | public function count() 67 | { 68 | if ($this->result === null) { 69 | $this->result = iterator_to_array($this->paginator); 70 | } 71 | 72 | return count($this->result); 73 | } 74 | 75 | /** 76 | * Return the number of ALL results in the paginatable of {@link Result}. 77 | * 78 | * @return int 79 | */ 80 | public function totalCount() 81 | { 82 | return $this->paginator->count(); 83 | } 84 | 85 | /** 86 | * Return an iterator over selected windows of results of the paginatable. 87 | * 88 | * @return Iterator 89 | */ 90 | public function getIterator() 91 | { 92 | if ($this->result) { 93 | return new ArrayIterator($this->result); 94 | } 95 | 96 | return $this->paginator; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Porpaginas/Doctrine/ORM/ORMQueryResult.php: -------------------------------------------------------------------------------- 1 | getQuery(); 51 | } 52 | 53 | $this->query = $query; 54 | $this->fetchCollection = $fetchCollection; 55 | } 56 | 57 | /** 58 | * @param int $offset 59 | * @return \Porpaginas\Page 60 | */ 61 | public function take($offset, $limit) 62 | { 63 | if ($this->result !== null) { 64 | return new ArrayPage( 65 | array_slice($this->result, $offset, $limit), 66 | $offset, 67 | $limit, 68 | count($this->result) 69 | ); 70 | } 71 | 72 | $query = clone $this->query; 73 | $query->setParameters($this->query->getParameters()); 74 | foreach ($this->query->getHints() as $name => $value) { 75 | $query->setHint($name, $value); 76 | } 77 | 78 | $query->setFirstResult($offset)->setMaxResults($limit); 79 | 80 | return new ORMQueryPage(new Paginator($query, $this->fetchCollection)); 81 | } 82 | 83 | /** 84 | * Return the number of all results in the paginatable. 85 | 86 | * @return int 87 | */ 88 | public function count() 89 | { 90 | if ($this->count === null) { 91 | $this->count = count(new Paginator($this->query, $this->fetchCollection)); 92 | } 93 | 94 | return $this->count; 95 | } 96 | 97 | /** 98 | * Return an iterator over all results of the paginatable. 99 | * 100 | * @return Iterator 101 | */ 102 | public function getIterator() 103 | { 104 | if ($this->result === null) { 105 | $this->result = $this->query->getResult(); 106 | $this->count = count($this->result); 107 | } 108 | 109 | return new ArrayIterator($this->result); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Porpaginas/Iterator/IteratorPage.php: -------------------------------------------------------------------------------- 1 | iterator = $iterator; 49 | $this->offset = $offset; 50 | $this->limit = $limit; 51 | $this->totalCount = $totalCount; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getCurrentOffset() 58 | { 59 | return $this->offset; 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | public function getCurrentPage() 66 | { 67 | if (0 === $this->limit) { 68 | return 1; 69 | } 70 | 71 | return floor($this->offset / $this->limit) + 1; 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function getCurrentLimit() 78 | { 79 | return $this->limit; 80 | } 81 | 82 | /** 83 | * {@inheritdoc} 84 | */ 85 | public function count() 86 | { 87 | return count($this->iterator); 88 | } 89 | 90 | /** 91 | * {@inheritdoc} 92 | */ 93 | public function totalCount() 94 | { 95 | return $this->totalCount; 96 | } 97 | 98 | /** 99 | * {@inheritdoc} 100 | */ 101 | public function getIterator() 102 | { 103 | return $this->iterator; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Porpaginas/KnpPager/PorpaginasSubscriber.php: -------------------------------------------------------------------------------- 1 | target instanceof Page)) { 15 | return; 16 | } 17 | 18 | $page = $event->target; 19 | 20 | $event->count = $page->totalCount(); 21 | $event->items = $page->getIterator(); 22 | $event->stopPropagation(); 23 | } 24 | 25 | public static function getSubscribedEvents() 26 | { 27 | return array( 28 | 'knp_pager.items' => array('items', 0) 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Porpaginas/Page.php: -------------------------------------------------------------------------------- 1 | totalCount = $totalCount; 14 | $this->limit = $limit; 15 | $this->currentPage = max(1, $currentPage); 16 | } 17 | 18 | public static function fromPage(Page $page) 19 | { 20 | return new self($page->totalCount(), $page->getCurrentLimit(), $page->getCurrentPage()); 21 | } 22 | 23 | public function isCurrent($page) 24 | { 25 | return $this->currentPage === $page; 26 | } 27 | 28 | public function getPages($siblings = 3) 29 | { 30 | return range($this->getSliceStart($siblings), $this->getSliceEnd($siblings)); 31 | } 32 | 33 | public function getNumberOfPages() 34 | { 35 | return (int) ceil($this->totalCount / $this->limit) ?: 1; 36 | } 37 | 38 | private function getSliceStart($siblings) 39 | { 40 | return min( 41 | max(1, $this->getNumberOfPages() - $siblings), 42 | max(1, $this->currentPage - $siblings) 43 | ); 44 | } 45 | 46 | private function getSliceEnd($siblings) 47 | { 48 | return max(1, min($this->getNumberOfPages(), $this->currentPage + $siblings)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Porpaginas/Pagerfanta/PorpaginasAdapter.php: -------------------------------------------------------------------------------- 1 | result = $result; 15 | } 16 | 17 | /** 18 | * Returns the number of results. 19 | * 20 | * @return integer The number of results. 21 | */ 22 | function getNbResults(): int 23 | { 24 | return $this->result->take(0, 1)->totalCount(); 25 | } 26 | 27 | /** 28 | * Returns an slice of the results. 29 | * 30 | * @param integer $offset The offset. 31 | * @param integer $length The length. 32 | * 33 | * @return array|\Traversable The slice. 34 | */ 35 | function getSlice(int $offset, int $length): iterable 36 | { 37 | return iterator_to_array($this->result->take($offset, $length)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Porpaginas/Result.php: -------------------------------------------------------------------------------- 1 | paginator = $paginator; 17 | $this->template = $template; 18 | } 19 | 20 | /** 21 | * @return string 22 | */ 23 | public function renderPagination(Page $page, Environment $environment) 24 | { 25 | return $environment->getExtension('knp_pagination')->render( 26 | $this->paginator->paginate( 27 | $page, 28 | $page->getCurrentPage(), 29 | $page->getCurrentLimit() 30 | ), 31 | $this->template 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Porpaginas/Twig/PagerfantaRenderingAdapter.php: -------------------------------------------------------------------------------- 1 | viewName = $viewName; 36 | $this->options = $options; 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function renderPagination(Page $page, Environment $environment) 43 | { 44 | $pagerfanta = new Pagerfanta(new PorpaginasAdapter($page)); 45 | $pagerfanta->setCurrentPage($page->getCurrentPage()); 46 | $pagerfanta->setMaxPerPage($page->getCurrentLimit()); 47 | 48 | return $environment->getExtension('pagerfanta')->renderPagerfanta( 49 | $pagerfanta, $this->viewName, $this->options 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Porpaginas/Twig/PorpaginasExtension.php: -------------------------------------------------------------------------------- 1 | adapter = $adapter; 32 | } 33 | 34 | public function getFunctions() 35 | { 36 | return array( 37 | new TwigFunction('porpaginas_render', array($this, 'renderPagination'), array('is_safe' => array('html'), 'needs_environment' => true)), 38 | new TwigFunction('porpaginas_total', array($this, 'renderTotal')), 39 | ); 40 | } 41 | 42 | public function renderPagination(Environment $environment, Page $page) 43 | { 44 | return $this->adapter->renderPagination($page, $environment); 45 | } 46 | 47 | public function renderTotal(Page $page) 48 | { 49 | return $page->totalCount(); 50 | } 51 | 52 | public function getName() 53 | { 54 | return 'Porpaginas'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Porpaginas/Twig/RenderingAdapter.php: -------------------------------------------------------------------------------- 1 | createResultWithItems(2); 15 | 16 | $this->assertCount(2, $result); 17 | } 18 | 19 | /** 20 | * @test 21 | */ 22 | public function it_iterates_over_all_items() 23 | { 24 | $result = $this->createResultWithItems(11); 25 | 26 | $this->assertCount(11, iterator_to_array($result)); 27 | } 28 | 29 | /** 30 | * @test 31 | */ 32 | public function it_takes_slice_as_page() 33 | { 34 | $result = $this->createResultWithItems(11); 35 | 36 | $page = $result->take(0, 10); 37 | 38 | $this->assertEquals(1, $page->getCurrentPage()); 39 | $this->assertEquals(0, $page->getCurrentOffset()); 40 | $this->assertEquals(10, $page->getCurrentLimit()); 41 | $this->assertCount(10, $page); 42 | $this->assertEquals(11, $page->totalCount()); 43 | } 44 | 45 | /** 46 | * @test 47 | */ 48 | public function it_counts_last_page_of_slice_correctly() 49 | { 50 | $result = $this->createResultWithItems(11); 51 | 52 | $page = $result->take(10, 10); 53 | 54 | $this->assertEquals(2, $page->getCurrentPage()); 55 | $this->assertEquals(10, $page->getCurrentOffset()); 56 | $this->assertEquals(10, $page->getCurrentLimit()); 57 | $this->assertCount(1, $page); 58 | } 59 | 60 | /** 61 | * @test 62 | */ 63 | public function it_counts_page_first_then_iterates() 64 | { 65 | $result = $this->createResultWithItems(16); 66 | 67 | $page = $result->take(10, 5); 68 | 69 | $this->assertCount(5, $page); 70 | $this->assertCount(5, iterator_to_array($page)); 71 | } 72 | 73 | /** 74 | * @test 75 | */ 76 | public function it_itereates_first_then_counts_page() 77 | { 78 | $result = $this->createResultWithItems(16); 79 | 80 | $page = $result->take(10, 5); 81 | 82 | $this->assertCount(5, iterator_to_array($page)); 83 | $this->assertCount(5, $page); 84 | } 85 | 86 | abstract protected function createResultWithItems($count); 87 | } 88 | -------------------------------------------------------------------------------- /tests/Porpaginas/ArrayTest.php: -------------------------------------------------------------------------------- 1 | setupEntityManager(); 20 | 21 | for ($i = 0; $i < $count; $i++) { 22 | $entityManager->persist(new DoctrineOrmEntity()); 23 | } 24 | $entityManager->flush(); 25 | $entityManager->clear(); 26 | 27 | $query = $entityManager->createQuery('SELECT e FROM Porpaginas\DoctrineOrmEntity e'); 28 | 29 | return new ORMQueryResult($query); 30 | } 31 | 32 | private function setupEntityManager() 33 | { 34 | $paths = array(); 35 | $isDevMode = false; 36 | 37 | // the connection configuration 38 | $dbParams = array( 39 | 'driver' => 'pdo_sqlite', 40 | 'memory' => true, 41 | ); 42 | 43 | $config = Setup::createAttributeMetadataConfiguration($paths, $isDevMode); 44 | $entityManager = EntityManager::create($dbParams, $config); 45 | 46 | $schemaTool = new SchemaTool($entityManager); 47 | $schemaTool->createSchema(array( 48 | $entityManager->getClassMetadata(__NAMESPACE__ . '\\DoctrineOrmEntity') 49 | )); 50 | 51 | return $entityManager; 52 | } 53 | } 54 | 55 | #[Entity] 56 | class DoctrineOrmEntity 57 | { 58 | #[Id, Column(type: "integer"), GeneratedValue] 59 | private $id; 60 | } 61 | -------------------------------------------------------------------------------- /tests/Porpaginas/KnpPager/PorpaginasSubscriberTest.php: -------------------------------------------------------------------------------- 1 | target = new ArrayPage(array(1, 2), 10, 10, 2); 18 | 19 | $subscriber = new PorpaginasSubscriber(); 20 | $subscriber->items($event); 21 | 22 | $this->assertEquals(2, $event->count); 23 | $this->assertEquals(array(1, 2), iterator_to_array($event->items)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Porpaginas/PagerTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($pager->getPages(), array(1, 2, 3, 4,)); 17 | } 18 | 19 | /** 20 | * @test 21 | */ 22 | public function it_handles_negative_page_numbers() 23 | { 24 | $pager = new Pager(95, 10, -42); 25 | $this->assertEquals($pager->getPages(), array(1, 2, 3, 4,)); 26 | } 27 | 28 | /** 29 | * @test 30 | */ 31 | public function it_handles_too_big_page_numbers() 32 | { 33 | $pager = new Pager(95, 10, 42); 34 | $this->assertEquals($pager->getPages(), array(7, 8, 9, 10)); 35 | } 36 | 37 | /** 38 | * @test 39 | */ 40 | public function it_handles_empty_lists() 41 | { 42 | $pager = new Pager(0, 10, 42); 43 | $this->assertEquals($pager->getPages(), array(1)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Porpaginas/Pagerfanta/PorpaginasAdapterTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(4, $pagerfanta->getNbResults()); 23 | } 24 | 25 | /** 26 | * @test 27 | */ 28 | public function it_iterates_slice() 29 | { 30 | $pagerfanta = new Pagerfanta( 31 | new PorpaginasAdapter( 32 | new ArrayResult(array(1, 2, 3, 4)) 33 | ) 34 | ); 35 | 36 | $pagerfanta->setMaxPerPage(2); 37 | $pagerfanta->setCurrentPage(1); 38 | 39 | $this->assertEquals(array(1, 2), $pagerfanta->getCurrentPageResults()); 40 | 41 | $pagerfanta->setCurrentPage(2); 42 | 43 | $this->assertEquals(array(3, 4), $pagerfanta->getCurrentPageResults()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Porpaginas/Twig/KnpPagerRenderingAdapterTest.php: -------------------------------------------------------------------------------- 1 | getExtension('knp_pagination')->thenReturn($extension); 25 | 26 | $paginator = new \Knp\Component\Pager\Paginator( 27 | $eventDispatcher = new EventDispatcher(), 28 | \Phake::mock(ArgumentAccessInterface::class), 29 | ); 30 | 31 | $eventDispatcher->addListener('knp_pager.items', function (ItemsEvent $event) { 32 | $event->stopPropagation(); 33 | $event->count = 0; 34 | $event->items = []; 35 | }); 36 | $eventDispatcher->addListener('knp_pager.pagination', function (PaginationEvent $event) { 37 | $event->stopPropagation(); 38 | $event->setPagination(new SlidingPagination()); 39 | }); 40 | 41 | $adapter = new KnpPagerRenderingAdapter($paginator); 42 | $page = new ArrayPage(array(1, 2), 10, 10, 2); 43 | 44 | $adapter->renderPagination($page, $env); 45 | 46 | \Phake::verify($extension)->render(\Phake::anyParameters()); 47 | } 48 | } 49 | 50 | class KnpPaginationExtension extends \Twig\Extension\AbstractExtension 51 | { 52 | public function render($items, $template) 53 | { 54 | } 55 | 56 | public function getName() 57 | { 58 | return 'knp_pagination'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/Porpaginas/Twig/PorpaginasExtensionTest.php: -------------------------------------------------------------------------------- 1 | renderPagination($env, $page); 20 | 21 | \Phake::verify($adapter)->renderPagination($page, $env); 22 | } 23 | } 24 | --------------------------------------------------------------------------------