Added knp paginator support
Bug fix: no Feature addition: yes Backwards compatibility break: no Encapsulated Pagerfanta dependency for pagination and added support for knp pagination component
This commit is contained in:
parent
2b858f0e42
commit
0d9e0f1172
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace FOQ\ElasticaBundle\Finder;
|
namespace FOQ\ElasticaBundle\Finder;
|
||||||
|
|
||||||
|
use FOQ\ElasticaBundle\Paginator\PaginatorAdapterInterface;
|
||||||
use Pagerfanta\Pagerfanta;
|
use Pagerfanta\Pagerfanta;
|
||||||
|
use Elastica_Query;
|
||||||
|
|
||||||
interface PaginatedFinderInterface
|
interface PaginatedFinderInterface
|
||||||
{
|
{
|
||||||
|
@ -13,4 +15,12 @@ interface PaginatedFinderInterface
|
||||||
* @return Pagerfanta paginated results
|
* @return Pagerfanta paginated results
|
||||||
*/
|
*/
|
||||||
function findPaginated($query);
|
function findPaginated($query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a paginator adapter for this query
|
||||||
|
*
|
||||||
|
* @param Elastica_Query $query
|
||||||
|
* @return PaginatorAdapterInterface
|
||||||
|
*/
|
||||||
|
function createPaginatorAdapter(Elastica_Query $query);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace FOQ\ElasticaBundle\Finder;
|
namespace FOQ\ElasticaBundle\Finder;
|
||||||
|
|
||||||
use FOQ\ElasticaBundle\Paginator\RawPaginatorAdapter;
|
use FOQ\ElasticaBundle\Paginator\RawPaginatorAdapter;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\FantaPaginatorAdapter;
|
||||||
use Pagerfanta\Pagerfanta;
|
use Pagerfanta\Pagerfanta;
|
||||||
use Elastica_Searchable;
|
use Elastica_Searchable;
|
||||||
use Elastica_Query;
|
use Elastica_Query;
|
||||||
|
@ -42,7 +43,7 @@ class RawFinder implements FinderInterface, PaginatedFinderInterface
|
||||||
$queryObject = Elastica_Query::create($query);
|
$queryObject = Elastica_Query::create($query);
|
||||||
$paginatorAdapter = $this->createPaginatorAdapter($queryObject);
|
$paginatorAdapter = $this->createPaginatorAdapter($queryObject);
|
||||||
|
|
||||||
return new Pagerfanta($paginatorAdapter);
|
return new Pagerfanta(new FantaPaginatorAdapter($paginatorAdapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +52,7 @@ class RawFinder implements FinderInterface, PaginatedFinderInterface
|
||||||
* @param Elastica_Query $query
|
* @param Elastica_Query $query
|
||||||
* @return RawPaginatorAdapter
|
* @return RawPaginatorAdapter
|
||||||
*/
|
*/
|
||||||
protected function createPaginatorAdapter(Elastica_Query $query)
|
public function createPaginatorAdapter(Elastica_Query $query)
|
||||||
{
|
{
|
||||||
return new RawPaginatorAdapter($this->searchable, $query);
|
return new RawPaginatorAdapter($this->searchable, $query);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use FOQ\ElasticaBundle\Finder\FinderInterface;
|
||||||
use FOQ\ElasticaBundle\Finder\PaginatedFinderInterface;
|
use FOQ\ElasticaBundle\Finder\PaginatedFinderInterface;
|
||||||
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
||||||
use FOQ\ElasticaBundle\Paginator\TransformedPaginatorAdapter;
|
use FOQ\ElasticaBundle\Paginator\TransformedPaginatorAdapter;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\FantaPaginatorAdapter;
|
||||||
use Pagerfanta\Pagerfanta;
|
use Pagerfanta\Pagerfanta;
|
||||||
use Elastica_Searchable;
|
use Elastica_Searchable;
|
||||||
use Elastica_Query;
|
use Elastica_Query;
|
||||||
|
@ -67,7 +68,7 @@ class TransformedFinder implements FinderInterface, PaginatedFinderInterface
|
||||||
$queryObject = Elastica_Query::create($query);
|
$queryObject = Elastica_Query::create($query);
|
||||||
$paginatorAdapter = $this->createPaginatorAdapter($queryObject);
|
$paginatorAdapter = $this->createPaginatorAdapter($queryObject);
|
||||||
|
|
||||||
return new Pagerfanta($paginatorAdapter);
|
return new Pagerfanta(new FantaPaginatorAdapter($paginatorAdapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,7 +77,7 @@ class TransformedFinder implements FinderInterface, PaginatedFinderInterface
|
||||||
* @param Elastica_Query $query
|
* @param Elastica_Query $query
|
||||||
* @return TransformedPaginatorAdapter
|
* @return TransformedPaginatorAdapter
|
||||||
*/
|
*/
|
||||||
protected function createPaginatorAdapter(Elastica_Query $query)
|
public function createPaginatorAdapter(Elastica_Query $query)
|
||||||
{
|
{
|
||||||
return new TransformedPaginatorAdapter($this->searchable, $query, $this->transformer);
|
return new TransformedPaginatorAdapter($this->searchable, $query, $this->transformer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace FOQ\ElasticaBundle\Paginator;
|
|
||||||
|
|
||||||
use Pagerfanta\Adapter\AdapterInterface;
|
|
||||||
use Elastica_Searchable;
|
|
||||||
use Elastica_Query;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the Pagerfanta\Adapter\AdapterInterface for use with Pagerfanta\Pagerfanta
|
|
||||||
*
|
|
||||||
* Allows pagination of Elastica_Query. Does not map results
|
|
||||||
*/
|
|
||||||
abstract class AbstractPaginatorAdapter implements AdapterInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var Elastica_SearchableInterface the object to search in
|
|
||||||
*/
|
|
||||||
protected $searchable = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Elastica_Query the query to search
|
|
||||||
*/
|
|
||||||
protected $query = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see PaginatorAdapterInterface::__construct
|
|
||||||
*
|
|
||||||
* @param Elastica_SearchableInterface the object to search in
|
|
||||||
* @param Elastica_Query the query to search
|
|
||||||
*/
|
|
||||||
public function __construct(Elastica_Searchable $searchable, Elastica_Query $query)
|
|
||||||
{
|
|
||||||
$this->searchable = $searchable;
|
|
||||||
$this->query = $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getElasticaResults($offset, $itemCountPerPage)
|
|
||||||
{
|
|
||||||
$query = clone $this->query;
|
|
||||||
$query->setFrom($offset);
|
|
||||||
$query->setLimit($itemCountPerPage);
|
|
||||||
|
|
||||||
return $this->searchable->search($query)->getResults();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Pagerfanta\Adapter\AdapterInterface::getNbResults
|
|
||||||
*/
|
|
||||||
public function getNbResults()
|
|
||||||
{
|
|
||||||
return $this->searchable->count($this->query);
|
|
||||||
}
|
|
||||||
}
|
|
46
Paginator/FantaPaginatorAdapter.php
Normal file
46
Paginator/FantaPaginatorAdapter.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
use Pagerfanta\Adapter\AdapterInterface;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\PaginatorAdapterInterface;
|
||||||
|
|
||||||
|
class FantaPaginatorAdapter implements AdapterInterface
|
||||||
|
{
|
||||||
|
private $adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PaginatorAdapterInterface $adapter
|
||||||
|
*/
|
||||||
|
public function __construct(PaginatorAdapterInterface $adapter)
|
||||||
|
{
|
||||||
|
$this->adapter = $adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of results.
|
||||||
|
*
|
||||||
|
* @return integer The number of results.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function getNbResults()
|
||||||
|
{
|
||||||
|
return $this->adapter->getTotalHits();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an slice of the results.
|
||||||
|
*
|
||||||
|
* @param integer $offset The offset.
|
||||||
|
* @param integer $length The length.
|
||||||
|
*
|
||||||
|
* @return array|\Traversable The slice.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function getSlice($offset, $length)
|
||||||
|
{
|
||||||
|
return $this->adapter->getResults($offset,$length)->toArray();
|
||||||
|
}
|
||||||
|
}
|
27
Paginator/PaginatorAdapterInterface.php
Normal file
27
Paginator/PaginatorAdapterInterface.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
interface PaginatorAdapterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the number of results.
|
||||||
|
*
|
||||||
|
* @return integer The number of results.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
function getTotalHits();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an slice of the results.
|
||||||
|
*
|
||||||
|
* @param integer $offset The offset.
|
||||||
|
* @param integer $length The length.
|
||||||
|
*
|
||||||
|
* @return FOQ\ElasticaBundle\Paginator\PartialResults
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
function getResults($offset, $length);
|
||||||
|
}
|
32
Paginator/PartialResultsInterface.php
Normal file
32
Paginator/PartialResultsInterface.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
interface PartialResultsInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the paginated results.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
function toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of results.
|
||||||
|
*
|
||||||
|
* @return integer The number of results.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
function getTotalHits();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the facets
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function getFacets();
|
||||||
|
}
|
|
@ -2,20 +2,69 @@
|
||||||
|
|
||||||
namespace FOQ\ElasticaBundle\Paginator;
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
use Elastica_Searchable;
|
||||||
|
use Elastica_Query;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\PaginatorAdapterInterface;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\RawPartialResults;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the Pagerfanta\Adapter\AdapterInterface for use with Zend\Paginator\Paginator
|
|
||||||
*
|
|
||||||
* Allows pagination of Elastica_Query. Does not map results
|
* Allows pagination of Elastica_Query. Does not map results
|
||||||
*/
|
*/
|
||||||
class RawPaginatorAdapter extends AbstractPaginatorAdapter
|
class RawPaginatorAdapter implements PaginatorAdapterInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @see Pagerfanta\Adapter\AdapterInterface::getSlice
|
* @var Elastica_SearchableInterface the object to search in
|
||||||
*/
|
*/
|
||||||
public function getSlice($offset, $length)
|
private $searchable = null;
|
||||||
{
|
|
||||||
$results = $this->getElasticaResults($offset, $length);
|
|
||||||
|
|
||||||
return array_map(function($result) { return $result->getSource(); }, $results);
|
/**
|
||||||
|
* @var Elastica_Query the query to search
|
||||||
|
*/
|
||||||
|
private $query = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see PaginatorAdapterInterface::__construct
|
||||||
|
*
|
||||||
|
* @param Elastica_SearchableInterface the object to search in
|
||||||
|
* @param Elastica_Query the query to search
|
||||||
|
*/
|
||||||
|
public function __construct(Elastica_Searchable $searchable, Elastica_Query $query)
|
||||||
|
{
|
||||||
|
$this->searchable = $searchable;
|
||||||
|
$this->query = $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the paginated results.
|
||||||
|
*
|
||||||
|
* @return Elastica_ResultSet
|
||||||
|
*/
|
||||||
|
protected function getElasticaResults($offset, $itemCountPerPage)
|
||||||
|
{
|
||||||
|
$query = clone $this->query;
|
||||||
|
$query->setFrom($offset);
|
||||||
|
$query->setLimit($itemCountPerPage);
|
||||||
|
|
||||||
|
return $this->searchable->search($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the paginated results.
|
||||||
|
*
|
||||||
|
* @return FOQ\ElasticaBundle\Paginator\PartialResultInterface
|
||||||
|
*/
|
||||||
|
public function getResults($offset, $itemCountPerPage)
|
||||||
|
{
|
||||||
|
return new RawPartialResults($this->getElasticaResults($offset,$itemCountPerPage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of results.
|
||||||
|
*
|
||||||
|
* @return integer The number of results.
|
||||||
|
*/
|
||||||
|
public function getTotalHits()
|
||||||
|
{
|
||||||
|
return $this->searchable->count($this->query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
Paginator/RawPartialResults.php
Normal file
52
Paginator/RawPartialResults.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
use FOQ\ElasticaBundle\Paginator\PartialResultsInterface;
|
||||||
|
use Elastica_ResultSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw partial results transforms to a simple array
|
||||||
|
*/
|
||||||
|
class RawPartialResults implements PartialResultsInterface
|
||||||
|
{
|
||||||
|
protected $resultSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Elastica_ResultSet $resultSet
|
||||||
|
*/
|
||||||
|
public function __construct(Elastica_ResultSet $resultSet)
|
||||||
|
{
|
||||||
|
$this->resultSet = $resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
return array_map(function($result) {
|
||||||
|
return $result->getSource();
|
||||||
|
}, $this->resultSet->getResults());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getTotalHits()
|
||||||
|
{
|
||||||
|
return $this->resultSet->getTotalHits();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getFacets()
|
||||||
|
{
|
||||||
|
if ($this->resultSet->hasFacets()) {
|
||||||
|
return $this->resultSet->getFacets();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,17 +3,16 @@
|
||||||
namespace FOQ\ElasticaBundle\Paginator;
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\TransformedPartialResults;
|
||||||
use Elastica_Searchable;
|
use Elastica_Searchable;
|
||||||
use Elastica_Query;
|
use Elastica_Query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the Pagerfanta\Adapter\AdapterInterface Interface for use with Zend\Paginator\Paginator
|
|
||||||
*
|
|
||||||
* Allows pagination of Elastica_Query
|
* Allows pagination of Elastica_Query
|
||||||
*/
|
*/
|
||||||
class TransformedPaginatorAdapter extends AbstractPaginatorAdapter
|
class TransformedPaginatorAdapter extends RawPaginatorAdapter
|
||||||
{
|
{
|
||||||
protected $transformer;
|
private $transformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Elastica_SearchableInterface the object to search in
|
* @param Elastica_SearchableInterface the object to search in
|
||||||
|
@ -28,12 +27,10 @@ class TransformedPaginatorAdapter extends AbstractPaginatorAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Pagerfanta\Adapter\AdapterInterface::getSlice
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function getSlice($offset, $length)
|
public function getResults($offset, $length)
|
||||||
{
|
{
|
||||||
$results = $this->getElasticaResults($offset, $length);
|
return new TransformedPartialResults($this->getElasticaResults($offset,$length),$this->transformer);
|
||||||
|
|
||||||
return $this->transformer->transform($results);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
Paginator/TransformedPartialResults.php
Normal file
34
Paginator/TransformedPartialResults.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Paginator;
|
||||||
|
|
||||||
|
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\RawPartialResults;
|
||||||
|
use Elastica_ResultSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial transformed result set
|
||||||
|
*/
|
||||||
|
class TransformedPartialResults extends RawPartialResults
|
||||||
|
{
|
||||||
|
protected $transformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Elastica_ResultSet $resultSet
|
||||||
|
* @param \FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface $transformer
|
||||||
|
*/
|
||||||
|
public function __construct(Elastica_ResultSet $resultSet, ElasticaToModelTransformerInterface $transformer)
|
||||||
|
{
|
||||||
|
parent::__construct($resultSet);
|
||||||
|
|
||||||
|
$this->transformer = $transformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
return $this->transformer->transform($this->resultSet->getResults());
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,10 @@
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service" id="service_container" />
|
||||||
</call>
|
</call>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="foq_elastica.paginator.subscriber" class="FOQ\ElasticaBundle\Subscriber\PaginateElasticaQuerySubscriber">
|
||||||
|
<tag name="knp_paginator.subscriber" />
|
||||||
|
</service>
|
||||||
</services>
|
</services>
|
||||||
|
|
||||||
</container>
|
</container>
|
||||||
|
|
33
Subscriber/PaginateElasticaQuerySubscriber.php
Normal file
33
Subscriber/PaginateElasticaQuerySubscriber.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FOQ\ElasticaBundle\Subscriber;
|
||||||
|
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Knp\Component\Pager\Event\ItemsEvent;
|
||||||
|
use FOQ\ElasticaBundle\Paginator\PaginatorAdapterInterface;
|
||||||
|
|
||||||
|
class PaginateElasticaQuerySubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
public function items(ItemsEvent $event)
|
||||||
|
{
|
||||||
|
if ($event->target instanceof PaginatorAdapterInterface) {
|
||||||
|
$results = $event->target->getResults($event->getOffset(), $event->getLimit());
|
||||||
|
|
||||||
|
$event->count = $results->getTotalHits();
|
||||||
|
$event->items = $results->toArray();
|
||||||
|
$facets = $results->getFacets();
|
||||||
|
if (null != $facets) {
|
||||||
|
$event->setCustomPaginationParameter('facets', $facets);
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'knp_pager.items' => array('items', 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue