Skip to content

Commit

Permalink
Merge pull request #115 from KnpLabs/refactor
Browse files Browse the repository at this point in the history
Use doctrine Paginator if available
  • Loading branch information
docteurklein committed Oct 6, 2014
2 parents 3f2fe97 + 861c2a0 commit 756c445
Show file tree
Hide file tree
Showing 24 changed files with 301 additions and 174 deletions.
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
tests/phpunit.xml
tests/temp/*.php
vendor/*
/tests/phpunit.xml
/tests/temp/*.php
/vendor
tags
/composer.lock
7 changes: 4 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ php:
- 5.5
- 5.6
- hhvm

matrix:
allow_failures:
- php: hhvm

before_script:
- php bin/vendors.php
- echo 'extension=mongo.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- composer install --prefer-dist

script: phpunit -c tests
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ PHPUnit 3.5 or newer is required.
To setup and run tests follow these steps:

- go to the root directory of components
- run: **php bin/vendors.php**
- run: **phpunit -c tests**
- run:

composer install
vendor/bin/phpunit -c tests

50 changes: 0 additions & 50 deletions bin/vendors.php

This file was deleted.

13 changes: 12 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"symfony/event-dispatcher": "~2.5",
"doctrine/orm": "~2.4",
"doctrine/mongodb-odm": "~1.0@beta",
"phpunit/phpunit": "~4.2"
},

"suggest": {
"doctrine/orm" : "to allow usage pagination with Doctrine ORM",
Expand All @@ -38,7 +44,12 @@

"autoload": {
"psr-0": {
"Knp\\Component": "src/"
"Knp\\Component": "src"
}
},
"autoload-dev": {
"psr-0": {
"Test": "tests"
}
}
}
37 changes: 37 additions & 0 deletions doc/pager/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Configuration


Some subscribers will take into account some options.
These options can be passed as the 4th argument of `Paginator::paginate()`.

For example, Doctrine ORM subscriber will generate different sql queries if the `distinct` options changes.


The list of existing options are:

| name | type | default value | subscribers |
| -------------------------- | ------ | ------------- | ----------------------------------------------- |
| wrap-queries | bool | false | orm QuerySubscriber, orm QueryBuilderSubscriber |
| distinct | bool | true | QuerySubscriber, QueryBuilderSubscriber |
| pageParameterName | string | page | SortableSubscriber |
| defaultSortFieldName | string | | SortableSubscriber |
| defaultSortDirection | string | asc | SortableSubscriber |
| sortFieldWhitelist | array | [] | SortableSubscriber |
| sortFieldParameterName | string | sort | SortableSubscriber |
| sortDirectionParameterName | string | sort | SortableSubscriber |
| filterFieldParameterName | string | filterParam | FiltrationSubscriber |
| filterValueParameterName | string | filterValue | FiltrationSubscriber |


## Noticeable behaviors of some options

### `distinct`

If set to true, will add a distinct sql keyword on orm queries to ensuire unicity of counted results


### `wrap-queries`

If set to true, will take advantage of doctrine 2.3 output walkers by using subqueries to handle composite keys and HAVING queries.
This can considerably impact performances depending on the query and the platform, you will have to consider it at some point.

1 change: 1 addition & 0 deletions doc/pager/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Why reinvent the wheel? Can someone me tell what the definition of **wheel** is
- Separation of conserns, paginator is responsible for generating the pagination view only,
pagination view - for representation purposes.
- Does not require initializing specific adapters
- [configurable](config.md)

## Usage examples:

Expand Down
45 changes: 1 addition & 44 deletions doc/pager/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,7 @@ This tutorial will cover installation and usage examples.

## Installation

Initially, all what is needed is:

- >= php5.3.2
- Symfony **EventDispatcher** component and if you do not have autoloader, I recommend
**ClassLoader** from the same symfony components
- this repository

Now somewhere in you third party vendor directory download mentioned dependencies:
**Note:** if you are in your project root and you have [git](http://help.github.com/set-up-git-redirect)
installed, **vendor** directory is the location where these components will be installed.

- run **git clone git://github.com/knplabs/knp-components.git vendor/knp-components**
- run **git clone git://github.com/symfony/EventDispatcher.git vendor/Symfony/Component/EventDispatcher**
- run **git clone git://github.com/symfony/ClassLoader.git vendor/Symfony/Component/ClassLoader**

To initially autoload these components, you will need to include
**vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php**

``` php
<?php
// file: autoloader.php
// taking into account that this autoloader is in the same directory as vendor folder
require_once __DIR__.'/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';

$loader = new Symfony\Component\ClassLoader\UniversalClassLoader;
$loader->registerNamespaces(array(
'Symfony\\Component' => __DIR__.'/vendor',
'Knp\\Component' => __DIR__.'/vendor/knp-components/src'
));
$loader->register();
```

Next, usually **index.php** file is the starting point. Lets create it in the same
project root directory as **autoloader.php**

``` php
<?php
// file: index.php
include 'autoloader.php';

// usage examples will continue here
```

In general now you can start using the paginator..
composer require "knplabs/knp-components:~1.2"

## Basic usage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* @author David Abdemoulaie <[email protected]>
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
* @license http://hobodave.com/license.txt New BSD License
* @deprecated
*/
class CountWalker extends TreeWalkerAdapter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* @author David Abdemoulaie <[email protected]>
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
* @license http://hobodave.com/license.txt New BSD License
* @deprecated
*/

namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\Query;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* @author David Abdemoulaie <[email protected]>
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
* @license http://hobodave.com/license.txt New BSD License
* @deprecated
*/
class WhereInWalker extends TreeWalkerAdapter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
use Doctrine\ORM\Tools\Pagination\WhereInWalker as DoctrineWhereInWalker;
use Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker as DoctrineLimitSubqueryWalker;

/**
* @deprecated see UsesPaginator
**/
class QuerySubscriber implements EventSubscriberInterface
{
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\QuerySubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Knp\Component\Pager\Event\ItemsEvent;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\ORM\Tools\Pagination\CountWalker;

class UsesPaginator implements EventSubscriberInterface
{
const HINT_FETCH_JOIN_COLLECTION = 'knp_paginator.fetch_join_collection';

public function items(ItemsEvent $event)
{
if (!class_exists('Doctrine\ORM\Tools\Pagination\Paginator')) {
return;
}
if (!$event->target instanceof Query) {
return;
}
$event->stopPropagation();

$useOutputWalkers = false;
if (isset($event->options['wrap-queries'])) {
$useOutputWalkers = $event->options['wrap-queries'];
}

$event->target
->setFirstResult($event->getOffset())
->setMaxResults($event->getLimit())
->setHint(CountWalker::HINT_DISTINCT, $event->options['distinct'])
;

$fetchJoinCollection = true;
if ($event->target->hasHint(self::HINT_FETCH_JOIN_COLLECTION)) {
$fetchJoinCollection = $event->target->getHint(self::HINT_FETCH_JOIN_COLLECTION);
}

$paginator = new Paginator($event->target, $fetchJoinCollection);
$paginator->setUseOutputWalkers($useOutputWalkers);
$event->count = count($paginator);
$event->items = iterator_to_array($paginator);
}

public static function getSubscribedEvents()
{
return array(
'knp_pager.items' => array('items', 0)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function before(BeforeEvent $event)
// hook all standard subscribers
$disp->addSubscriber(new ArraySubscriber);
$disp->addSubscriber(new Doctrine\ORM\QueryBuilderSubscriber);
$disp->addSubscriber(new Doctrine\ORM\QuerySubscriber\UsesPaginator);
$disp->addSubscriber(new Doctrine\ORM\QuerySubscriber);
$disp->addSubscriber(new Doctrine\ODM\MongoDB\QueryBuilderSubscriber);
$disp->addSubscriber(new Doctrine\ODM\MongoDB\QuerySubscriber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function shouldPaginate()

private function populate()
{
$mockFile = realpath(TESTS_PATH.'/temp/summer.gif');
$mockFile = __DIR__.'/summer.gif';
$dm = $this->getMockDocumentManager();
$summer = new Image;
$summer->setTitle('summer');
Expand Down
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function shouldBeAbleToPaginateWithHavingClause()
$q = $this->em->createQuery($dql);
$q->setHydrationMode(Query::HYDRATE_ARRAY);
$p = new Paginator;
$view = $p->paginate($q, 1, 10);
$view = $p->paginate($q, 1, 10, array('wrap-queries' => true));
$this->assertEquals(3, count($view));
}

Expand Down Expand Up @@ -126,6 +126,27 @@ function shouldBeAbleToPaginateCaseBasedQuery()
$this->assertEquals(1, $items[0]['relevance']);
}

/**
* @test
*/
function shouldUseOutputWalkersIfHinted()
{
$this->populate();

$dql = <<<___SQL
SELECT p, t
FROM Test\Fixture\Entity\Shop\Product p
INNER JOIN p.tags t
GROUP BY p.id
HAVING p.numTags = COUNT(t)
___SQL;
$q = $this->em->createQuery($dql);
$q->setHydrationMode(Query::HYDRATE_ARRAY);
$p = new Paginator;
$view = $p->paginate($q, 1, 10, array('wrap-queries' => true));
$this->assertEquals(3, count($view));
}

protected function getUsedEntityFixtures()
{
return array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,11 @@
use Test\Tool\BaseTestCaseORM;
use Knp\Component\Pager\Paginator;
use Test\Fixture\Entity\Composite;
use Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\QuerySubscriber\UsesPaginator;
use Doctrine\ORM\Query;

class CompositeKeyTest extends BaseTestCaseORM
{
/**
* @test
* @expectedException Doctrine\ORM\Mapping\MappingException
*/
function shouldNotBeAbleToCountCompositeKeyOnByCountQueryWalker()
{
$p = new Paginator;
$em = $this->getMockSqliteEntityManager();

$query = $em->createQuery('SELECT c FROM Test\Fixture\Entity\Composite c');
$view = $p->paginate($query);
}

/**
* @test
*/
Expand All @@ -38,7 +27,8 @@ function shouldBeHandledByQueryHintByPassingCount()
->createQuery('SELECT c FROM Test\Fixture\Entity\Composite c')
->setHint('knp_paginator.count', $count)
;
$view = $p->paginate($query);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, false);
$view = $p->paginate($query, 1, 10, array('wrap-queries' => true));

$items = $view->getItems();
$this->assertEquals(0, count($items));
Expand Down
Loading

1 comment on commit 756c445

@gondo
Copy link
Contributor

@gondo gondo commented on 756c445 Dec 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this merge broke count hinting functionality as mentioned here KnpLabs/KnpPaginatorBundle#276 (comment)

Please sign in to comment.