FOSElasticaBundle/Provider/DoctrineProvider.php

92 lines
2.9 KiB
PHP

<?php
namespace FOQ\ElasticaBundle\Provider;
use Doctrine\Common\Persistence\ObjectManager;
use Elastica_Type;
use Elastica_Document;
use Closure;
use InvalidArgumentException;
class DoctrineProvider implements ProviderInterface
{
protected $type;
protected $objectManager;
protected $objectClass;
protected $options = array(
'batch_size' => 100,
'clear_object_manager' => true,
'create_query_builder_method' => 'createQueryBuilder'
);
public function __construct(Elastica_Type $type, ObjectManager $objectManager, $objectClass, array $options = array())
{
$this->type = $type;
$this->objectManager = $objectManager;
$this->objectClass = $objectClass;
$this->options = array_merge($this->options, $options);
}
/**
* Insert the repository objects in the type index
*
* @param Closure $loggerClosure
*/
public function populate(Closure $loggerClosure)
{
$queryBuilder = $this->createQueryBuilder();
$nbObjects = $queryBuilder->getQuery()->count();
$getters = $this->buildGetters();
for ($offset = 0; $offset < $nbObjects; $offset += $this->options['batch_size']) {
$loggerClosure(sprintf('%0.1f%% (%d/%d)', 100*$offset/$nbObjects, $offset, $nbObjects));
$this->type->addDocuments(array_map(function($object) use ($getters) {
return new Elastica_Document($object->getId(), array_map(function($getter) use ($object) {
return (string) $object->$getter();
}, $getters));
}, $queryBuilder->limit($this->options['batch_size'])->skip($offset)->getQuery()->execute()->toArray()));
if ($this->options['clear_object_manager']) {
$this->objectManager->clear();
}
}
}
/**
* Preprocesses getters based on the type mappings
*
* @return null
**/
public function buildGetters()
{
$getters = array();
$mappings = $this->type->getMapping();
// skip index name
$mappings = reset($mappings);
// skip type name
$mappings = reset($mappings);
$mappings = $mappings['properties'];
foreach ($mappings as $property => $mappingOptions) {
$getter = 'get'.ucfirst($property);
if (!method_exists($this->objectClass, $getter)) {
throw new InvalidArgumentException(sprintf('The getter %s::%s does not exist', $this->objectClass, $getter));
}
$getters[$property] = $getter;
}
return $getters;
}
/**
* Creates the query buider used to fetch the documents to index
*
* @return Query
**/
protected function createQueryBuilder()
{
return $this->objectManager->getRepository($this->objectClass)->{$this->options['create_query_builder_method']}();
}
}