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;
|
||||
|
||||
use FOQ\ElasticaBundle\Paginator\PaginatorAdapterInterface;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use Elastica_Query;
|
||||
|
||||
interface PaginatedFinderInterface
|
||||
{
|
||||
|
@ -13,4 +15,12 @@ interface PaginatedFinderInterface
|
|||
* @return Pagerfanta paginated results
|
||||
*/
|
||||
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;
|
||||
|
||||
use FOQ\ElasticaBundle\Paginator\RawPaginatorAdapter;
|
||||
use FOQ\ElasticaBundle\Paginator\FantaPaginatorAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use Elastica_Searchable;
|
||||
use Elastica_Query;
|
||||
|
@ -42,7 +43,7 @@ class RawFinder implements FinderInterface, PaginatedFinderInterface
|
|||
$queryObject = Elastica_Query::create($query);
|
||||
$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
|
||||
* @return RawPaginatorAdapter
|
||||
*/
|
||||
protected function createPaginatorAdapter(Elastica_Query $query)
|
||||
public function createPaginatorAdapter(Elastica_Query $query)
|
||||
{
|
||||
return new RawPaginatorAdapter($this->searchable, $query);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use FOQ\ElasticaBundle\Finder\FinderInterface;
|
|||
use FOQ\ElasticaBundle\Finder\PaginatedFinderInterface;
|
||||
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
||||
use FOQ\ElasticaBundle\Paginator\TransformedPaginatorAdapter;
|
||||
use FOQ\ElasticaBundle\Paginator\FantaPaginatorAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use Elastica_Searchable;
|
||||
use Elastica_Query;
|
||||
|
@ -67,7 +68,7 @@ class TransformedFinder implements FinderInterface, PaginatedFinderInterface
|
|||
$queryObject = Elastica_Query::create($query);
|
||||
$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
|
||||
* @return TransformedPaginatorAdapter
|
||||
*/
|
||||
protected function createPaginatorAdapter(Elastica_Query $query)
|
||||
public function createPaginatorAdapter(Elastica_Query $query)
|
||||
{
|
||||
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;
|
||||
|
||||
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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
$results = $this->getElasticaResults($offset, $length);
|
||||
private $searchable = null;
|
||||
|
||||
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;
|
||||
|
||||
use FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
|
||||
use FOQ\ElasticaBundle\Paginator\TransformedPartialResults;
|
||||
use Elastica_Searchable;
|
||||
use Elastica_Query;
|
||||
|
||||
/**
|
||||
* Implements the Pagerfanta\Adapter\AdapterInterface Interface for use with Zend\Paginator\Paginator
|
||||
*
|
||||
* 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
|
||||
|
@ -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 $this->transformer->transform($results);
|
||||
return new TransformedPartialResults($this->getElasticaResults($offset,$length),$this->transformer);
|
||||
}
|
||||
}
|
||||
|
|
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" />
|
||||
</call>
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.paginator.subscriber" class="FOQ\ElasticaBundle\Subscriber\PaginateElasticaQuerySubscriber">
|
||||
<tag name="knp_paginator.subscriber" />
|
||||
</service>
|
||||
</services>
|
||||
|
||||
</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