Merge pull request #80 from Exercise/repopulate-index
Allow single indexes and types to be repopulated
This commit is contained in:
commit
661c324e43
|
@ -15,33 +15,115 @@ use Symfony\Component\Console\Output\Output;
|
|||
class PopulateCommand extends ContainerAwareCommand
|
||||
{
|
||||
/**
|
||||
* @see Command
|
||||
* @var FOQ\ElasticaBundle\IndexManager
|
||||
*/
|
||||
private $indexManager;
|
||||
|
||||
/**
|
||||
* @var FOQ\ElasticaBundle\Provider\ProviderRegistry
|
||||
*/
|
||||
private $providerRegistry;
|
||||
|
||||
/**
|
||||
* @var FOQ\ElasticaBundle\Resetter
|
||||
*/
|
||||
private $resetter;
|
||||
|
||||
/**
|
||||
* @see Symfony\Component\Console\Command\Command::configure()
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('foq:elastica:populate')
|
||||
->setDescription('Populates search indexes from providers');
|
||||
->addOption('index', null, InputOption::VALUE_OPTIONAL, 'The index to repopulate')
|
||||
->addOption('type', null, InputOption::VALUE_OPTIONAL, 'The type to repopulate')
|
||||
->setDescription('Populates search indexes from providers')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @see Symfony\Component\Console\Command\Command::initialize()
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->indexManager = $this->getContainer()->get('foq_elastica.index_manager');
|
||||
$this->providerRegistry = $this->getContainer()->get('foq_elastica.provider_registry');
|
||||
$this->resetter = $this->getContainer()->get('foq_elastica.resetter');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Symfony\Component\Console\Command\Command::execute()
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln('Reseting indexes');
|
||||
$this->getContainer()->get('foq_elastica.reseter')->reset();
|
||||
$index = $input->getOption('index');
|
||||
$type = $input->getOption('type');
|
||||
|
||||
$output->writeln('Populating indexes');
|
||||
$this->getContainer()->get('foq_elastica.populator')->populate(function($text) use ($output) {
|
||||
$output->writeLn($text);
|
||||
});
|
||||
if (null === $index && null !== $type) {
|
||||
throw new \InvalidArgumentException('Cannot specify type option without an index.');
|
||||
}
|
||||
|
||||
$output->writeln('Refreshing indexes');
|
||||
array_map(function($index) {
|
||||
$index->refresh();
|
||||
}, $this->getContainer()->get('foq_elastica.index_manager')->getAllIndexes());
|
||||
if (null !== $index) {
|
||||
if (null !== $type) {
|
||||
$this->populateIndexType($output, $index, $type);
|
||||
} else {
|
||||
$this->populateIndex($output, $index);
|
||||
}
|
||||
} else {
|
||||
$indexes = array_keys($this->indexManager->getAllIndexes());
|
||||
|
||||
$output->writeln('Done');
|
||||
foreach ($indexes as $index) {
|
||||
$this->populateIndex($output, $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates an index, populates its types, and refreshes the index.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param string $index
|
||||
*/
|
||||
private function populateIndex(OutputInterface $output, $index)
|
||||
{
|
||||
$output->writeln(sprintf('Resetting: %s', $index));
|
||||
$this->resetter->resetIndex($index);
|
||||
|
||||
$providers = $this->providerRegistry->getIndexProviders($index);
|
||||
|
||||
foreach ($providers as $type => $provider) {
|
||||
$loggerClosure = function($message) use ($output, $index, $type) {
|
||||
$output->writeln(sprintf('Populating: %s/%s, %s', $index, $type, $message));
|
||||
};
|
||||
|
||||
$provider->populate($loggerClosure);
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('Refreshing: %s', $index));
|
||||
$this->indexManager->getIndex($index)->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes/remaps an index type, populates it, and refreshes the index.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param string $index
|
||||
* @param string $type
|
||||
*/
|
||||
private function populateIndexType(OutputInterface $output, $index, $type)
|
||||
{
|
||||
$output->writeln(sprintf('Resetting: %s/%s', $index, $type));
|
||||
$this->resetter->resetIndexType($index, $type);
|
||||
|
||||
$loggerClosure = function($message) use ($output, $index, $type) {
|
||||
$output->writeln(sprintf('Populating: %s/%s, %s', $index, $type, $message));
|
||||
};
|
||||
|
||||
$provider = $this->providerRegistry->getProvider($index, $type);
|
||||
$provider->populate($loggerClosure);
|
||||
|
||||
$output->writeln(sprintf('Refreshing: %s', $index));
|
||||
$this->indexManager->getIndex($index)->refresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,18 +22,17 @@ class SearchCommand extends ContainerAwareCommand
|
|||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setDefinition(array(
|
||||
new InputArgument('type', InputArgument::REQUIRED, 'The type to search in'),
|
||||
new InputArgument('query', InputArgument::REQUIRED, 'The text to search'),
|
||||
))
|
||||
->setName('foq:elastica:search')
|
||||
->addArgument('type', InputArgument::REQUIRED, 'The type to search in')
|
||||
->addArgument('query', InputArgument::REQUIRED, 'The text to search')
|
||||
->addOption('index', null, InputOption::VALUE_NONE, 'The index to search in')
|
||||
->addOption('limit', null, InputOption::VALUE_REQUIRED, 'The maximum number of documents to return', 20)
|
||||
->addOption('show-field', null, InputOption::VALUE_REQUIRED, 'Field to show, null uses the first field')
|
||||
->addOption('show-source', null, InputOption::VALUE_NONE, 'Show the documents sources')
|
||||
->addOption('show-id', null, InputOption::VALUE_NONE, 'Show the documents ids')
|
||||
->addOption('explain', null, InputOption::VALUE_NONE, 'Enables explanation for each hit on how its score was computed.')
|
||||
->setName('foq:elastica:search')
|
||||
->setDescription('Searches documents in a given type and index');
|
||||
->setDescription('Searches documents in a given type and index')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
class AddProviderPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('foq_elastica.populator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$providers = array();
|
||||
foreach ($container->findTaggedServiceIds('foq_elastica.provider') as $id => $attributes) {
|
||||
$providers[$id] = new Reference($id);
|
||||
}
|
||||
|
||||
$container->getDefinition('foq_elastica.populator')->replaceArgument(0, $providers);
|
||||
}
|
||||
}
|
70
DependencyInjection/Compiler/RegisterProvidersPass.php
Normal file
70
DependencyInjection/Compiler/RegisterProvidersPass.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
|
||||
class RegisterProvidersPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* Mapping of class names to booleans indicating whether the class
|
||||
* implements ProviderInterface.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $implementations = array();
|
||||
|
||||
/**
|
||||
* @see Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface::process()
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('foq_elastica.provider_registry')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Infer the default index name from the service alias
|
||||
$defaultIndex = substr($container->getAlias('foq_elastica.index'), 19);
|
||||
|
||||
$registry = $container->getDefinition('foq_elastica.provider_registry');
|
||||
$providers = $container->findTaggedServiceIds('foq_elastica.provider');
|
||||
|
||||
foreach ($providers as $providerId => $tags) {
|
||||
$index = $type = null;
|
||||
$class = $container->getDefinition($providerId)->getClass();
|
||||
|
||||
if (!$class || !$this->isProviderImplementation($class)) {
|
||||
throw new \InvalidArgumentException(sprintf('Elastica provider "%s" with class "%s" must implement ProviderInterface.', $providerId, $class));
|
||||
}
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (!isset($tag['type'])) {
|
||||
throw new \InvalidArgumentException(sprintf('Elastica provider "%s" must specify the "type" attribute.', $providerId));
|
||||
}
|
||||
|
||||
$index = isset($tag['index']) ? $tag['index'] : $defaultIndex;
|
||||
$type = $tag['type'];
|
||||
}
|
||||
|
||||
$registry->addMethodCall('addProvider', array($index, $type, $providerId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the class implements ProviderInterface.
|
||||
*
|
||||
* @param string $class
|
||||
* @return boolean
|
||||
*/
|
||||
private function isProviderImplementation($class)
|
||||
{
|
||||
if (!isset($this->implementations[$class])) {
|
||||
$refl = new \ReflectionClass($class);
|
||||
$this->implementations[$class] = $refl->implementsInterface('FOQ\ElasticaBundle\Provider\ProviderInterface');
|
||||
}
|
||||
|
||||
return $this->implementations[$class];
|
||||
}
|
||||
}
|
|
@ -43,12 +43,12 @@ class FOQElasticaExtension extends Extension
|
|||
|
||||
$clientIdsByName = $this->loadClients($config['clients'], $container);
|
||||
$indexIdsByName = $this->loadIndexes($config['indexes'], $container, $clientIdsByName, $config['default_client']);
|
||||
$indexDefsByName = array_map(function($id) use ($container) {
|
||||
return $container->getDefinition($id);
|
||||
$indexRefsByName = array_map(function($id) {
|
||||
return new Reference($id);
|
||||
}, $indexIdsByName);
|
||||
|
||||
$this->loadIndexManager($indexDefsByName, $container->getDefinition($indexIdsByName[$config['default_index']]), $container);
|
||||
$this->loadReseter($this->indexConfigs, $container);
|
||||
$this->loadIndexManager($indexRefsByName, $container);
|
||||
$this->loadResetter($this->indexConfigs, $container);
|
||||
|
||||
$container->setAlias('foq_elastica.client', sprintf('foq_elastica.client.%s', $config['default_client']));
|
||||
$container->setAlias('foq_elastica.index', sprintf('foq_elastica.index.%s', $config['default_index']));
|
||||
|
@ -213,8 +213,7 @@ class FOQElasticaExtension extends Extension
|
|||
$objectPersisterId = $this->loadObjectPersister($typeConfig, $typeDef, $container, $indexName, $typeName, $modelToElasticaTransformerId);
|
||||
|
||||
if (isset($typeConfig['provider'])) {
|
||||
$providerId = $this->loadTypeProvider($typeConfig, $container, $objectPersisterId, $typeDef, $indexName, $typeName);
|
||||
$container->getDefinition('foq_elastica.populator')->addMethodCall('addProvider', array($providerId, new Reference($providerId)));
|
||||
$this->loadTypeProvider($typeConfig, $container, $objectPersisterId, $typeDef, $indexName, $typeName);
|
||||
}
|
||||
if (isset($typeConfig['finder'])) {
|
||||
$this->loadTypeFinder($typeConfig, $container, $elasticaToModelTransformerId, $typeDef, $indexName, $typeName);
|
||||
|
@ -282,25 +281,14 @@ class FOQElasticaExtension extends Extension
|
|||
if (isset($typeConfig['provider']['service'])) {
|
||||
return $typeConfig['provider']['service'];
|
||||
}
|
||||
$abstractProviderId = sprintf('foq_elastica.provider.prototype.%s', $typeConfig['driver']);
|
||||
|
||||
$providerId = sprintf('foq_elastica.provider.%s.%s', $indexName, $typeName);
|
||||
$providerDef = new DefinitionDecorator($abstractProviderId);
|
||||
$providerDef->replaceArgument(0, $typeDef);
|
||||
|
||||
// Doctrine has a mandatory service as second argument
|
||||
$argPos = ('propel' === $typeConfig['driver']) ? 1 : 2;
|
||||
|
||||
$providerDef->replaceArgument($argPos, new Reference($objectPersisterId));
|
||||
$providerDef->replaceArgument($argPos + 1, $typeConfig['model']);
|
||||
|
||||
$options = array('batch_size' => $typeConfig['provider']['batch_size']);
|
||||
|
||||
if ('propel' !== $typeConfig['driver']) {
|
||||
$options['query_builder_method'] = $typeConfig['provider']['query_builder_method'];
|
||||
$options['clear_object_manager'] = $typeConfig['provider']['clear_object_manager'];
|
||||
}
|
||||
|
||||
$providerDef->replaceArgument($argPos + 2, $options);
|
||||
$providerDef = new DefinitionDecorator('foq_elastica.provider.prototype.' . $typeConfig['driver']);
|
||||
$providerDef->addTag('foq_elastica.provider', array('index' => $indexName, 'type' => $typeName));
|
||||
$providerDef->replaceArgument(0, new Reference($objectPersisterId));
|
||||
$providerDef->replaceArgument(1, $typeConfig['model']);
|
||||
// Propel provider can simply ignore Doctrine-specific options
|
||||
$providerDef->replaceArgument(2, array_diff_key($typeConfig['provider'], array('service' => 1)));
|
||||
$container->setDefinition($providerId, $providerDef);
|
||||
|
||||
return $providerId;
|
||||
|
@ -371,24 +359,25 @@ class FOQElasticaExtension extends Extension
|
|||
/**
|
||||
* Loads the index manager
|
||||
*
|
||||
* @return null
|
||||
* @param array $indexRefsByName
|
||||
* @param ContainerBuilder $container
|
||||
**/
|
||||
protected function loadIndexManager(array $indexDefs, $defaultIndexId, ContainerBuilder $container)
|
||||
protected function loadIndexManager(array $indexRefsByName, ContainerBuilder $container)
|
||||
{
|
||||
$managerDef = $container->getDefinition('foq_elastica.index_manager');
|
||||
$managerDef->replaceArgument(0, $indexDefs);
|
||||
$managerDef->replaceArgument(0, $indexRefsByName);
|
||||
$managerDef->replaceArgument(1, new Reference('foq_elastica.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the reseter
|
||||
* Loads the resetter
|
||||
*
|
||||
* @return null
|
||||
**/
|
||||
protected function loadReseter(array $indexConfigs, ContainerBuilder $container)
|
||||
protected function loadResetter(array $indexConfigs, ContainerBuilder $container)
|
||||
{
|
||||
$reseterDef = $container->getDefinition('foq_elastica.reseter');
|
||||
$reseterDef->replaceArgument(0, $indexConfigs);
|
||||
$resetterDef = $container->getDefinition('foq_elastica.resetter');
|
||||
$resetterDef->replaceArgument(0, $indexConfigs);
|
||||
}
|
||||
|
||||
protected function loadDriver(ContainerBuilder $container, $driver)
|
||||
|
|
|
@ -2,106 +2,85 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle\Doctrine;
|
||||
|
||||
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use FOQ\ElasticaBundle\Persister\ObjectPersisterInterface;
|
||||
use Elastica_Type;
|
||||
use Elastica_Document;
|
||||
use Closure;
|
||||
use InvalidArgumentException;
|
||||
use FOQ\ElasticaBundle\Provider\AbstractProvider as BaseAbstractProvider;
|
||||
|
||||
abstract class AbstractProvider implements ProviderInterface
|
||||
abstract class AbstractProvider extends BaseAbstractProvider
|
||||
{
|
||||
/**
|
||||
* Elastica type
|
||||
*
|
||||
* @var Elastica_Type
|
||||
*/
|
||||
protected $type;
|
||||
protected $managerRegistry;
|
||||
|
||||
/**
|
||||
* Manager registry
|
||||
* Constructor.
|
||||
*
|
||||
* @var object
|
||||
* @param ObjectPersisterInterface $objectPersister
|
||||
* @param string $objectClass
|
||||
* @param array $options
|
||||
* @param ManagerRegistry $managerRegistry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* Object persister
|
||||
*
|
||||
* @var ObjectPersisterInterface
|
||||
*/
|
||||
protected $objectPersister;
|
||||
|
||||
/**
|
||||
* Provider options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = array(
|
||||
'batch_size' => 100,
|
||||
'clear_object_manager' => true,
|
||||
'query_builder_method' => 'createQueryBuilder'
|
||||
);
|
||||
|
||||
public function __construct(Elastica_Type $type, $registry, ObjectPersisterInterface $objectPersister, $objectClass, array $options = array())
|
||||
public function __construct(ObjectPersisterInterface $objectPersister, $objectClass, array $options, $managerRegistry)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->registry = $registry;
|
||||
$this->objectClass = $objectClass;
|
||||
$this->objectPersister = $objectPersister;
|
||||
$this->options = array_merge($this->options, $options);
|
||||
parent::__construct($objectPersister, $objectClass, array_merge(array(
|
||||
'clear_object_manager' => true,
|
||||
'query_builder_method' => 'createQueryBuilder',
|
||||
), $options));
|
||||
|
||||
$this->managerRegistry = $managerRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the repository objects in the type index
|
||||
*
|
||||
* @param Closure $loggerClosure
|
||||
* @see FOQ\ElasticaBundle\Provider\ProviderInterface::populate()
|
||||
*/
|
||||
public function populate(Closure $loggerClosure)
|
||||
public function populate(\Closure $loggerClosure = null)
|
||||
{
|
||||
$queryBuilder = $this->createQueryBuilder();
|
||||
$nbObjects = $this->countObjects($queryBuilder);
|
||||
$nbObjects = $this->countObjects($queryBuilder);
|
||||
|
||||
for ($offset = 0; $offset < $nbObjects; $offset += $this->options['batch_size']) {
|
||||
if ($loggerClosure) {
|
||||
$stepStartTime = microtime(true);
|
||||
}
|
||||
|
||||
$stepStartTime = microtime(true);
|
||||
$objects = $this->fetchSlice($queryBuilder, $this->options['batch_size'], $offset);
|
||||
|
||||
$this->objectPersister->insertMany($objects);
|
||||
|
||||
if ($this->options['clear_object_manager']) {
|
||||
$this->registry->getManagerForClass($this->objectClass)->clear();
|
||||
$this->managerRegistry->getManagerForClass($this->objectClass)->clear();
|
||||
}
|
||||
|
||||
$stepNbObjects = count($objects);
|
||||
$stepCount = $stepNbObjects+$offset;
|
||||
$objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime);
|
||||
$loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', 100*$stepCount/$nbObjects, $stepCount, $nbObjects, $objectsPerSecond));
|
||||
if ($loggerClosure) {
|
||||
$stepNbObjects = count($objects);
|
||||
$stepCount = $stepNbObjects + $offset;
|
||||
$percentComplete = 100 * $stepCount / $nbObjects;
|
||||
$objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime);
|
||||
$loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the objects of a query builder
|
||||
* Counts objects that would be indexed using the query builder.
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @return int
|
||||
**/
|
||||
* @param object $queryBuilder
|
||||
* @return integer
|
||||
*/
|
||||
protected abstract function countObjects($queryBuilder);
|
||||
|
||||
/**
|
||||
* Fetches a slice of objects
|
||||
* Fetches a slice of objects using the query builder.
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @param int limit
|
||||
* @param int offset
|
||||
* @return array of objects
|
||||
**/
|
||||
* @param object $queryBuilder
|
||||
* @param integer $limit
|
||||
* @param integer $offset
|
||||
* @return array
|
||||
*/
|
||||
protected abstract function fetchSlice($queryBuilder, $limit, $offset);
|
||||
|
||||
/**
|
||||
* Creates the query builder used to fetch the documents to index
|
||||
* Creates the query builder, which will be used to fetch objects to index.
|
||||
*
|
||||
* @return query builder
|
||||
**/
|
||||
* @return object
|
||||
*/
|
||||
protected abstract function createQueryBuilder();
|
||||
}
|
||||
|
|
|
@ -2,42 +2,49 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle\Doctrine\MongoDB;
|
||||
|
||||
use Doctrine\ODM\MongoDB\Query\Builder;
|
||||
use FOQ\ElasticaBundle\Doctrine\AbstractProvider;
|
||||
use FOQ\ElasticaBundle\Exception\InvalidArgumentTypeException;
|
||||
|
||||
class Provider extends AbstractProvider
|
||||
{
|
||||
/**
|
||||
* Counts the objects of a query builder
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @return int
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::countObjects()
|
||||
*/
|
||||
protected function countObjects($queryBuilder)
|
||||
{
|
||||
return $queryBuilder->getQuery()->count();
|
||||
if (!$queryBuilder instanceof Builder) {
|
||||
throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ODM\MongoDB\Query\Builder');
|
||||
}
|
||||
|
||||
return $queryBuilder
|
||||
->getQuery()
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a slice of objects
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @param int limit
|
||||
* @param int offset
|
||||
* @return array of objects
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::fetchSlice()
|
||||
*/
|
||||
protected function fetchSlice($queryBuilder, $limit, $offset)
|
||||
{
|
||||
return $queryBuilder->limit($limit)->skip($offset)->getQuery()->execute()->toArray();
|
||||
if (!$queryBuilder instanceof Builder) {
|
||||
throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ODM\MongoDB\Query\Builder');
|
||||
}
|
||||
|
||||
return $queryBuilder
|
||||
->limit($limit)
|
||||
->skip($offset)
|
||||
->getQuery()
|
||||
->execute()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the query builder used to fetch the documents to index
|
||||
*
|
||||
* @return query builder
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::createQueryBuilder()
|
||||
*/
|
||||
protected function createQueryBuilder()
|
||||
{
|
||||
return $this->registry
|
||||
return $this->managerRegistry
|
||||
->getManagerForClass($this->objectClass)
|
||||
->getRepository($this->objectClass)
|
||||
->{$this->options['query_builder_method']}();
|
||||
|
|
|
@ -2,51 +2,59 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use FOQ\ElasticaBundle\Doctrine\AbstractProvider;
|
||||
use FOQ\ElasticaBundle\Exception\InvalidArgumentTypeException;
|
||||
|
||||
class Provider extends AbstractProvider
|
||||
{
|
||||
/**
|
||||
* Counts the objects of a query builder
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @return int
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::countObjects()
|
||||
*/
|
||||
protected function countObjects($queryBuilder)
|
||||
{
|
||||
$qb = clone $queryBuilder;
|
||||
$qb->select($qb->expr()->count($queryBuilder->getRootAlias()))
|
||||
->resetDQLPart('orderBy'); // no need to order the query. It does not change the count and make the query less efficient.
|
||||
if (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getSingleScalarResult();
|
||||
/* Clone the query builder before altering its field selection and DQL,
|
||||
* lest we leave the query builder in a bad state for fetchSlice().
|
||||
*/
|
||||
$qb = clone $queryBuilder;
|
||||
|
||||
return $qb
|
||||
->select($qb->expr()->count($queryBuilder->getRootAlias()))
|
||||
// Remove ordering for efficiency; it doesn't affect the count
|
||||
->resetDQLPart('orderBy')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a slice of objects
|
||||
*
|
||||
* @param queryBuilder
|
||||
* @param int limit
|
||||
* @param int offset
|
||||
* @return array of objects
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::fetchSlice()
|
||||
*/
|
||||
protected function fetchSlice($queryBuilder, $limit, $offset)
|
||||
{
|
||||
$queryBuilder->setFirstResult($offset);
|
||||
$queryBuilder->setMaxResults($limit);
|
||||
if (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
|
||||
}
|
||||
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
return $queryBuilder
|
||||
->setFirstResult($offset)
|
||||
->setMaxResults($limit)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the query builder used to fetch the documents to index
|
||||
*
|
||||
* @return query builder
|
||||
**/
|
||||
* @see FOQ\ElasticaBundle\Doctrine\AbstractProvider::createQueryBuilder()
|
||||
*/
|
||||
protected function createQueryBuilder()
|
||||
{
|
||||
return $this->registry
|
||||
return $this->managerRegistry
|
||||
->getManagerForClass($this->objectClass)
|
||||
->getRepository($this->objectClass)
|
||||
// ORM query builders require an alias argument
|
||||
->{$this->options['query_builder_method']}('a');
|
||||
}
|
||||
}
|
||||
|
|
11
Exception/InvalidArgumentTypeException.php
Normal file
11
Exception/InvalidArgumentTypeException.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Exception;
|
||||
|
||||
class InvalidArgumentTypeException extends \InvalidArgumentException
|
||||
{
|
||||
public function __construct($value, $expectedType)
|
||||
{
|
||||
parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
|
||||
}
|
||||
}
|
|
@ -2,18 +2,22 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use FOQ\ElasticaBundle\DependencyInjection\Compiler\AddProviderPass;
|
||||
use FOQ\ElasticaBundle\DependencyInjection\Compiler\RegisterProvidersPass;
|
||||
use FOQ\ElasticaBundle\DependencyInjection\Compiler\TransformerPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class FOQElasticaBundle extends Bundle
|
||||
{
|
||||
/**
|
||||
* @see Symfony\Component\HttpKernel\Bundle\Bundle::build()
|
||||
*/
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->addCompilerPass(new AddProviderPass());
|
||||
$container->addCompilerPass(new RegisterProvidersPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$container->addCompilerPass(new TransformerPass());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,21 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class IndexManager
|
||||
{
|
||||
protected $indexes;
|
||||
protected $defaultIndex;
|
||||
protected $indexesByName;
|
||||
protected $defaultIndexName;
|
||||
|
||||
public function __construct(array $indexes, $defaultIndex)
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $indexesByName
|
||||
* @param string $defaultIndexName
|
||||
*/
|
||||
public function __construct(array $indexesByName, $defaultIndexName)
|
||||
{
|
||||
$this->indexes = $indexes;
|
||||
$this->defaultIndex = $defaultIndex;
|
||||
$this->indexesByName = $indexesByName;
|
||||
$this->defaultIndexName = $defaultIndexName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,33 +26,36 @@ class IndexManager
|
|||
*/
|
||||
public function getAllIndexes()
|
||||
{
|
||||
return $this->indexes;
|
||||
return $this->indexesByName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an index by its name
|
||||
*
|
||||
* @param string $name Index to return, or the default index if null
|
||||
* @return Elastica_Index
|
||||
**/
|
||||
public function getIndex($name)
|
||||
* @throws InvalidArgumentException if no index exists for the given name
|
||||
*/
|
||||
public function getIndex($name = null)
|
||||
{
|
||||
if (!$name) {
|
||||
return $this->getDefaultIndex();
|
||||
}
|
||||
if (!isset($this->indexes[$name])) {
|
||||
throw new InvalidArgumentException(sprintf('The index "%s" does not exist', $name));
|
||||
if (null === $name) {
|
||||
$name = $this->defaultIndexName;
|
||||
}
|
||||
|
||||
return $this->indexes[$name];
|
||||
if (!isset($this->indexesByName[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('The index "%s" does not exist', $name));
|
||||
}
|
||||
|
||||
return $this->indexesByName[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default index
|
||||
*
|
||||
* @return Elastica_Index
|
||||
**/
|
||||
*/
|
||||
public function getDefaultIndex()
|
||||
{
|
||||
return $this->defaultIndex;
|
||||
return $this->getIndex($this->defaultIndexName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
use Elastica_Type;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Stores the configured mappings for all types
|
||||
* Responsible for applying configured mappings to elastica types
|
||||
*/
|
||||
class MappingRegistry
|
||||
{
|
||||
/**
|
||||
* Configured mappings. See http://www.elasticsearch.org/guide/reference/mapping/
|
||||
* array(
|
||||
* "index_name/type_name" => array(type_object, mapping_array)
|
||||
* )
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mappings = null;
|
||||
|
||||
/**
|
||||
* Instanciates a new MappingSetter
|
||||
*
|
||||
* @param array mappings
|
||||
*/
|
||||
public function __construct($mappings)
|
||||
{
|
||||
$this->mappings = $mappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply mappings to all elastica types
|
||||
**/
|
||||
public function applyMappings()
|
||||
{
|
||||
foreach ($this->mappings as $pair) {
|
||||
list($type, $mappings) = $pair;
|
||||
$type->setMapping($mappings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type mapping field names
|
||||
*
|
||||
* @param Elastica_Type $type
|
||||
* @return array list of fields names
|
||||
*/
|
||||
public function getTypeFieldNames(Elastica_Type $type)
|
||||
{
|
||||
$key = sprintf('%s/%s', $type->getIndex()->getName(), $type->getType());
|
||||
if (!isset($this->mappings[$key])) {
|
||||
throw new InvalidArgumentException(sprintf('This type is not registered: "%s".', $key));
|
||||
}
|
||||
|
||||
return array_keys($this->mappings[$key][1]);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
||||
use Closure;
|
||||
|
||||
class Populator
|
||||
{
|
||||
protected $providers;
|
||||
|
||||
public function __construct(array $providers)
|
||||
{
|
||||
foreach ($providers as $name => $provider) {
|
||||
$this->addProvider($name, $provider);
|
||||
}
|
||||
}
|
||||
|
||||
public function addProvider($name, ProviderInterface $provider)
|
||||
{
|
||||
$this->providers[$name] = $provider;
|
||||
}
|
||||
|
||||
public function populate(Closure $loggerClosure)
|
||||
{
|
||||
foreach ($this->providers as $name => $provider) {
|
||||
$provider->populate(function($text) use ($name, $loggerClosure) {
|
||||
$loggerClosure(sprintf('Indexing %s, %s', $name, $text));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,64 +2,28 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle\Propel;
|
||||
|
||||
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
||||
use FOQ\ElasticaBundle\Persister\ObjectPersisterInterface;
|
||||
use Elastica_Type;
|
||||
use Elastica_Document;
|
||||
use Closure;
|
||||
use InvalidArgumentException;
|
||||
use FOQ\ElasticaBundle\Provider\AbstractProvider;
|
||||
|
||||
/**
|
||||
* Propel provider
|
||||
*
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class Provider implements ProviderInterface
|
||||
class Provider extends AbstractProvider
|
||||
{
|
||||
/**
|
||||
* Elastica type
|
||||
*
|
||||
* @var Elastica_Type
|
||||
* @see FOQ\ElasticaBundle\Provider\ProviderInterface::populate()
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Object persister
|
||||
*
|
||||
* @var ObjectPersisterInterface
|
||||
*/
|
||||
protected $objectPersister;
|
||||
|
||||
/**
|
||||
* Provider options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = array(
|
||||
'batch_size' => 100,
|
||||
);
|
||||
|
||||
public function __construct(Elastica_Type $type, ObjectPersisterInterface $objectPersister, $objectClass, array $options = array())
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->objectClass = $objectClass;
|
||||
$this->objectPersister = $objectPersister;
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the repository objects in the type index
|
||||
*
|
||||
* @param Closure $loggerClosure
|
||||
*/
|
||||
public function populate(Closure $loggerClosure)
|
||||
public function populate(\Closure $loggerClosure = null)
|
||||
{
|
||||
$queryClass = $this->objectClass . 'Query';
|
||||
$nbObjects = $queryClass::create()->count();
|
||||
$nbObjects = $queryClass::create()->count();
|
||||
|
||||
for ($offset = 0; $offset < $nbObjects; $offset += $this->options['batch_size']) {
|
||||
if ($loggerClosure) {
|
||||
$stepStartTime = microtime(true);
|
||||
}
|
||||
|
||||
$stepStartTime = microtime(true);
|
||||
$objects = $queryClass::create()
|
||||
->limit($this->options['batch_size'])
|
||||
->offset($offset)
|
||||
|
@ -67,10 +31,13 @@ class Provider implements ProviderInterface
|
|||
|
||||
$this->objectPersister->insertMany($objects->getArrayCopy());
|
||||
|
||||
$stepNbObjects = count($objects);
|
||||
$stepCount = $stepNbObjects+$offset;
|
||||
$objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime);
|
||||
$loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', 100*$stepCount/$nbObjects, $stepCount, $nbObjects, $objectsPerSecond));
|
||||
if ($loggerClosure) {
|
||||
$stepNbObjects = count($objects);
|
||||
$stepCount = $stepNbObjects + $offset;
|
||||
$percentComplete = 100 * $stepCount / $nbObjects;
|
||||
$objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime);
|
||||
$loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
30
Provider/AbstractProvider.php
Normal file
30
Provider/AbstractProvider.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Provider;
|
||||
|
||||
use FOQ\ElasticaBundle\Persister\ObjectPersisterInterface;
|
||||
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
||||
|
||||
abstract class AbstractProvider implements ProviderInterface
|
||||
{
|
||||
protected $objectClass;
|
||||
protected $objectPersister;
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ObjectPersisterInterface $objectPersister
|
||||
* @param string $objectClass
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(ObjectPersisterInterface $objectPersister, $objectClass, array $options = array())
|
||||
{
|
||||
$this->objectPersister = $objectPersister;
|
||||
$this->objectClass = $objectClass;
|
||||
|
||||
$this->options = array_merge(array(
|
||||
'batch_size' => 100,
|
||||
), $options);
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace FOQ\ElasticaBundle\Provider;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* Insert application domain objects into elastica types
|
||||
*
|
||||
|
@ -12,9 +10,9 @@ use Closure;
|
|||
interface ProviderInterface
|
||||
{
|
||||
/**
|
||||
* Add all domain objects of a repository to the elastica type
|
||||
* Persists all domain objects to ElasticSearch for this provider.
|
||||
*
|
||||
* @param Closure $loggerClosure
|
||||
*/
|
||||
function populate(Closure $loggerClosure);
|
||||
function populate(\Closure $loggerClosure = null);
|
||||
}
|
||||
|
|
102
Provider/ProviderRegistry.php
Normal file
102
Provider/ProviderRegistry.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Provider;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* References persistence providers for each index and type.
|
||||
*/
|
||||
class ProviderRegistry implements ContainerAwareInterface
|
||||
{
|
||||
private $container;
|
||||
private $providers = array();
|
||||
|
||||
/**
|
||||
* Registers a provider for the specified index and type.
|
||||
*
|
||||
* @param string $index
|
||||
* @param string $type
|
||||
* @param string $providerId
|
||||
*/
|
||||
public function addProvider($index, $type, $providerId)
|
||||
{
|
||||
if (!isset($this->providers[$index])) {
|
||||
$this->providers[$index] = array();
|
||||
}
|
||||
|
||||
$this->providers[$index][$type] = $providerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all registered providers.
|
||||
*
|
||||
* Providers will be indexed by "index/type" strings in the returned array.
|
||||
*
|
||||
* @return array of ProviderInterface instances
|
||||
*/
|
||||
public function getAllProviders()
|
||||
{
|
||||
$providers = array();
|
||||
|
||||
foreach ($this->providers as $index => $indexProviders) {
|
||||
foreach ($indexProviders as $type => $providerId) {
|
||||
$providers[sprintf('%s/%s', $index, $type)] = $this->container->get($providerId);
|
||||
}
|
||||
}
|
||||
|
||||
return $providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all providers for an index.
|
||||
*
|
||||
* Providers will be indexed by "type" strings in the returned array.
|
||||
*
|
||||
* @param string $index
|
||||
* @return array of ProviderInterface instances
|
||||
* @throws InvalidArgumentException if no providers were registered for the index
|
||||
*/
|
||||
public function getIndexProviders($index)
|
||||
{
|
||||
if (!isset($this->providers[$index])) {
|
||||
throw new \InvalidArgumentException(sprintf('No providers were registered for index "%s".', $index));
|
||||
}
|
||||
|
||||
$providers = array();
|
||||
|
||||
foreach ($this->providers[$index] as $type => $providerId) {
|
||||
$providers[$type] = $this->container->get($providerId);
|
||||
}
|
||||
|
||||
return $providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the provider for an index and type.
|
||||
*
|
||||
* @param string $index
|
||||
* @param string $type
|
||||
* @return ProviderInterface
|
||||
* @throws InvalidArgumentException if no provider was registered for the index and type
|
||||
*/
|
||||
public function getProvider($index, $type)
|
||||
{
|
||||
if (!isset($this->providers[$index][$type])) {
|
||||
throw new \InvalidArgumentException(sprintf('No provider was registered for index "%s" and type "%s".', $index, $type));
|
||||
}
|
||||
|
||||
return $this->container->get($this->providers[$index][$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer()
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
}
|
16
README.md
16
README.md
|
@ -203,20 +203,20 @@ You can change this value in the provider configuration.
|
|||
##### Change the document identifier field
|
||||
|
||||
By default, ElasticaBundle will use the `id` field of your entities as the elasticsearch document identifier.
|
||||
You can change this value in the provider configuration.
|
||||
You can change this value in the persistence configuration.
|
||||
|
||||
persistence:
|
||||
driver: orm
|
||||
model: Application\UserBundle\Entity\User
|
||||
provider:
|
||||
identifier: id
|
||||
identifier: id
|
||||
|
||||
#### Manual provider
|
||||
|
||||
Create a service with the tag "foq_elastica.provider".
|
||||
Create a service with the tag "foq_elastica.provider" and attributes for the
|
||||
index and type for which the service will provide.
|
||||
|
||||
<service id="acme.search_provider.user" class="Acme\UserBundle\Search\UserProvider">
|
||||
<tag name="foq_elastica.provider" />
|
||||
<tag name="foq_elastica.provider" index="website" type="user" />
|
||||
<argument type="service" id="foq_elastica.index.website.user" />
|
||||
</service>
|
||||
|
||||
|
@ -243,9 +243,11 @@ Its class must implement `FOQ\ElasticaBundle\Provider\ProviderInterface`.
|
|||
*
|
||||
* @param Closure $loggerClosure
|
||||
*/
|
||||
public function populate(Closure $loggerClosure)
|
||||
public function populate(Closure $loggerClosure = null)
|
||||
{
|
||||
$loggerClosure('Indexing users');
|
||||
if ($loggerClosure) {
|
||||
$loggerClosure('Indexing users');
|
||||
}
|
||||
|
||||
$this->userType->addDocuments(array(
|
||||
array('username' => 'Bob')
|
||||
|
|
35
Reseter.php
35
Reseter.php
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
use Elastica_Exception_Response;
|
||||
|
||||
/**
|
||||
* Deletes and recreates indexes
|
||||
**/
|
||||
class Reseter
|
||||
{
|
||||
/**
|
||||
* Index settings and mappings
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $indexConfigs;
|
||||
|
||||
public function __construct(array $indexConfigs)
|
||||
{
|
||||
$this->indexConfigs = $indexConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all indexes
|
||||
*
|
||||
* @return null
|
||||
**/
|
||||
public function reset()
|
||||
{
|
||||
foreach ($this->indexConfigs as $indexConfig) {
|
||||
$indexConfig['index']->create($indexConfig['config'], true);
|
||||
}
|
||||
}
|
||||
}
|
79
Resetter.php
Normal file
79
Resetter.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle;
|
||||
|
||||
/**
|
||||
* Deletes and recreates indexes
|
||||
*/
|
||||
class Resetter
|
||||
{
|
||||
protected $indexConfigsByName;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $indexConfigsByName
|
||||
*/
|
||||
public function __construct(array $indexConfigsByName)
|
||||
{
|
||||
$this->indexConfigsByName = $indexConfigsByName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes and recreates all indexes
|
||||
*/
|
||||
public function resetAllIndexes()
|
||||
{
|
||||
foreach ($this->indexConfigsByName as $indexConfig) {
|
||||
$indexConfig['index']->create($indexConfig['config'], true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes and recreates the named index
|
||||
*
|
||||
* @param string $indexName
|
||||
* @throws InvalidArgumentException if no index exists for the given name
|
||||
*/
|
||||
public function resetIndex($indexName)
|
||||
{
|
||||
$indexConfig = $this->getIndexConfig($indexName);
|
||||
$indexConfig['index']->create($indexConfig['config'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes and recreates a mapping type for the named index
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $typeName
|
||||
* @throws InvalidArgumentException if no index or type mapping exists for the given names
|
||||
*/
|
||||
public function resetIndexType($indexName, $typeName)
|
||||
{
|
||||
$indexConfig = $this->getIndexConfig($indexName);
|
||||
|
||||
if (!isset($indexConfig['config']['mappings'][$typeName])) {
|
||||
throw new \InvalidArgumentException(sprintf('The mapping for index "%s" and type "%s" does not exist.', $indexName, $typeName));
|
||||
}
|
||||
|
||||
$type = $indexConfig['index']->getType($typeName);
|
||||
$type->delete();
|
||||
$type->setMapping($indexConfig['config']['mappings'][$typeName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an index config by its name
|
||||
*
|
||||
* @param string $index Index name
|
||||
* @return array
|
||||
* @throws InvalidArgumentException if no index config exists for the given name
|
||||
*/
|
||||
protected function getIndexConfig($indexName)
|
||||
{
|
||||
if (!isset($this->indexConfigsByName[$indexName])) {
|
||||
throw new \InvalidArgumentException(sprintf('The configuration for index "%s" does not exist.', $indexName));
|
||||
}
|
||||
|
||||
return $this->indexConfigsByName[$indexName];
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
<parameter key="foq_elastica.data_collector.class">FOQ\ElasticaBundle\DataCollector\ElasticaDataCollector</parameter>
|
||||
<parameter key="foq_elastica.manager.class">FOQ\ElasticaBundle\Manager\RepositoryManager</parameter>
|
||||
<parameter key="foq_elastica.elastica_to_model_transformer.collection.class">FOQ\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection</parameter>
|
||||
<parameter key="foq_elastica.provider_registry.class">FOQ\ElasticaBundle\Provider\ProviderRegistry</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
|
@ -37,11 +38,7 @@
|
|||
<argument /> <!-- default index -->
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.populator" class="FOQ\ElasticaBundle\Populator">
|
||||
<argument /> <!-- providers -->
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.reseter" class="FOQ\ElasticaBundle\Reseter">
|
||||
<service id="foq_elastica.resetter" class="FOQ\ElasticaBundle\Resetter">
|
||||
<argument /> <!-- index configs -->
|
||||
</service>
|
||||
|
||||
|
@ -66,6 +63,11 @@
|
|||
<argument type="collection" /> <!-- options -->
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.provider_registry" class="%foq_elastica.provider_registry.class%">
|
||||
<call method="setContainer">
|
||||
<argument type="service" id="service_container" />
|
||||
</call>
|
||||
</service>
|
||||
</services>
|
||||
|
||||
</container>
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
<services>
|
||||
|
||||
<service id="foq_elastica.provider.prototype.mongodb" class="FOQ\ElasticaBundle\Doctrine\MongoDB\Provider" public="false" abstract="true">
|
||||
<argument /> <!-- type -->
|
||||
<argument type="service" id="doctrine.odm.mongodb" />
|
||||
<service id="foq_elastica.provider.prototype.mongodb" class="FOQ\ElasticaBundle\Doctrine\MongoDB\Provider" public="true" abstract="true">
|
||||
<argument /> <!-- object persister -->
|
||||
<argument /> <!-- model -->
|
||||
<argument type="collection" /> <!-- options -->
|
||||
<argument type="service" id="doctrine.odm.mongodb" />
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.listener.prototype.mongodb" class="FOQ\ElasticaBundle\Doctrine\MongoDB\Listener" public="false" abstract="true">
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
<services>
|
||||
|
||||
<service id="foq_elastica.provider.prototype.orm" class="FOQ\ElasticaBundle\Doctrine\ORM\Provider" public="false" abstract="true">
|
||||
<argument /> <!-- type -->
|
||||
<argument type="service" id="doctrine" />
|
||||
<service id="foq_elastica.provider.prototype.orm" class="FOQ\ElasticaBundle\Doctrine\ORM\Provider" public="true" abstract="true">
|
||||
<argument /> <!-- object persister -->
|
||||
<argument /> <!-- model -->
|
||||
<argument type="collection" /> <!-- options -->
|
||||
<argument type="service" id="doctrine" />
|
||||
</service>
|
||||
|
||||
<service id="foq_elastica.listener.prototype.orm" class="FOQ\ElasticaBundle\Doctrine\ORM\Listener" public="false" abstract="true">
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
<services>
|
||||
|
||||
<service id="foq_elastica.provider.prototype.propel" class="FOQ\ElasticaBundle\Propel\Provider" public="false" abstract="true">
|
||||
<argument /> <!-- type -->
|
||||
<service id="foq_elastica.provider.prototype.propel" class="FOQ\ElasticaBundle\Propel\Provider" public="true" abstract="true">
|
||||
<argument /> <!-- object persister -->
|
||||
<argument /> <!-- model -->
|
||||
<argument type="collection" /> <!-- options -->
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\DependencyInjection\Compiler;
|
||||
|
||||
use FOQ\ElasticaBundle\DependencyInjection\Compiler\RegisterProvidersPass;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
class RegisterProvidersPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testProcessShouldRegisterTaggedProviders()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$pass = new RegisterProvidersPass();
|
||||
|
||||
$registryDefinition = new Definition();
|
||||
|
||||
$container->setDefinition('foq_elastica.provider_registry', $registryDefinition);
|
||||
$container->setAlias('foq_elastica.index', 'foq_elastica.index.foo');
|
||||
|
||||
$container->setDefinition('provider.foo.a', $this->createProviderDefinition(array('type' => 'a')));
|
||||
$container->setDefinition('provider.foo.b', $this->createProviderDefinition(array('index' => 'foo', 'type' => 'b')));
|
||||
$container->setDefinition('provider.bar.a', $this->createProviderDefinition(array('index' => 'bar', 'type' => 'a')));
|
||||
|
||||
$pass->process($container);
|
||||
|
||||
$calls = $registryDefinition->getMethodCalls();
|
||||
|
||||
$this->assertEquals(array('addProvider', array('foo', 'a', 'provider.foo.a')), $calls[0]);
|
||||
$this->assertEquals(array('addProvider', array('foo', 'b', 'provider.foo.b')), $calls[1]);
|
||||
$this->assertEquals(array('addProvider', array('bar', 'a', 'provider.bar.a')), $calls[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testProcessShouldRequireProviderImplementation()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$pass = new RegisterProvidersPass();
|
||||
|
||||
$container->setDefinition('foq_elastica.provider_registry', new Definition());
|
||||
$container->setAlias('foq_elastica.index', 'foq_elastica.index.foo');
|
||||
|
||||
$providerDef = $this->createProviderDefinition();
|
||||
$providerDef->setClass('stdClass');
|
||||
|
||||
$container->setDefinition('provider.foo.a', $providerDef);
|
||||
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testProcessShouldRequireTypeAttribute()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$pass = new RegisterProvidersPass();
|
||||
|
||||
$container->setDefinition('foq_elastica.provider_registry', new Definition());
|
||||
$container->setAlias('foq_elastica.index', 'foq_elastica.index.foo');
|
||||
|
||||
$container->setDefinition('provider.foo.a', $this->createProviderDefinition());
|
||||
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
private function createProviderDefinition(array $attributes = array())
|
||||
{
|
||||
$provider = $this->getMock('FOQ\ElasticaBundle\Provider\ProviderInterface');
|
||||
|
||||
$definition = new Definition(get_class($provider));
|
||||
$definition->addTag('foq_elastica.provider', $attributes);
|
||||
|
||||
return $definition;
|
||||
}
|
||||
}
|
183
Tests/Doctrine/AbstractProviderTest.php
Normal file
183
Tests/Doctrine/AbstractProviderTest.php
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\Doctrine;
|
||||
|
||||
class AbstractProviderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $objectClass;
|
||||
private $objectManager;
|
||||
private $objectPersister;
|
||||
private $options;
|
||||
private $managerRegistry;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (!interface_exists('Doctrine\Common\Persistence\ManagerRegistry')) {
|
||||
$this->markTestSkipped('Doctrine Common is not available.');
|
||||
}
|
||||
|
||||
$this->objectClass = 'objectClass';
|
||||
$this->options = array();
|
||||
|
||||
$this->objectPersister = $this->getMockObjectPersister();
|
||||
$this->managerRegistry = $this->getMockManagerRegistry();
|
||||
$this->objectManager = $this->getMockObjectManager();
|
||||
|
||||
$this->managerRegistry->expects($this->any())
|
||||
->method('getManagerForClass')
|
||||
->with($this->objectClass)
|
||||
->will($this->returnValue($this->objectManager));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providePopulateIterations
|
||||
*/
|
||||
public function testPopulateIterations($nbObjects, $objectsByIteration, $batchSize)
|
||||
{
|
||||
$this->options['batch_size'] = $batchSize;
|
||||
|
||||
$provider = $this->getMockAbstractProvider();
|
||||
|
||||
$queryBuilder = new \stdClass();
|
||||
|
||||
$provider->expects($this->once())
|
||||
->method('createQueryBuilder')
|
||||
->will($this->returnValue($queryBuilder));
|
||||
|
||||
$provider->expects($this->once())
|
||||
->method('countObjects')
|
||||
->with($queryBuilder)
|
||||
->will($this->returnValue($nbObjects));
|
||||
|
||||
$providerInvocationOffset = 2;
|
||||
|
||||
foreach ($objectsByIteration as $i => $objects) {
|
||||
$offset = $objects[0] - 1;
|
||||
|
||||
$provider->expects($this->at($providerInvocationOffset + $i))
|
||||
->method('fetchSlice')
|
||||
->with($queryBuilder, $batchSize, $offset)
|
||||
->will($this->returnValue($objects));
|
||||
|
||||
$this->objectPersister->expects($this->at($i))
|
||||
->method('insertMany')
|
||||
->with($objects);
|
||||
|
||||
$this->objectManager->expects($this->at($i))
|
||||
->method('clear');
|
||||
}
|
||||
|
||||
$provider->populate();
|
||||
}
|
||||
|
||||
public function providePopulateIterations()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
100,
|
||||
array(range(1,100)),
|
||||
100,
|
||||
),
|
||||
array(
|
||||
105,
|
||||
array(range(1, 50), range(51, 100), range(101, 105)),
|
||||
50,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function testPopulateShouldNotClearObjectManager()
|
||||
{
|
||||
$nbObjects = 1;
|
||||
$objects = array(1);
|
||||
$this->options['clear_object_manager'] = false;
|
||||
|
||||
$provider = $this->getMockAbstractProvider();
|
||||
|
||||
$provider->expects($this->any())
|
||||
->method('countObjects')
|
||||
->will($this->returnValue($nbObjects));
|
||||
|
||||
$provider->expects($this->any())
|
||||
->method('fetchSlice')
|
||||
->will($this->returnValue($objects));
|
||||
|
||||
$this->objectManager->expects($this->never())
|
||||
->method('clear');
|
||||
|
||||
$provider->populate();
|
||||
}
|
||||
|
||||
public function testPopulateInvokesLoggerClosure()
|
||||
{
|
||||
$nbObjects = 1;
|
||||
$objects = array(1);
|
||||
|
||||
$provider = $this->getMockAbstractProvider();
|
||||
|
||||
$provider->expects($this->any())
|
||||
->method('countObjects')
|
||||
->will($this->returnValue($nbObjects));
|
||||
|
||||
$provider->expects($this->any())
|
||||
->method('fetchSlice')
|
||||
->will($this->returnValue($objects));
|
||||
|
||||
$loggerClosureInvoked = false;
|
||||
$loggerClosure = function () use (&$loggerClosureInvoked) {
|
||||
$loggerClosureInvoked = true;
|
||||
};
|
||||
|
||||
$provider->populate();
|
||||
$this->assertFalse($loggerClosureInvoked);
|
||||
|
||||
$provider->populate($loggerClosure);
|
||||
$this->assertTrue($loggerClosureInvoked);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FOQ\ElasticaBundle\Doctrine\AbstractProvider
|
||||
*/
|
||||
private function getMockAbstractProvider()
|
||||
{
|
||||
return $this->getMockForAbstractClass('FOQ\ElasticaBundle\Doctrine\AbstractProvider', array(
|
||||
$this->objectPersister,
|
||||
$this->objectClass,
|
||||
$this->options,
|
||||
$this->managerRegistry,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Doctrine\Common\Persistence\ManagerRegistry
|
||||
*/
|
||||
private function getMockManagerRegistry()
|
||||
{
|
||||
return $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FOQ\ElasticaBundle\Tests\Doctrine\ObjectManager
|
||||
*/
|
||||
private function getMockObjectManager()
|
||||
{
|
||||
return $this->getMock(__NAMESPACE__ . '\ObjectManager');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FOQ\ElasticaBundle\Persister\ObjectPersisterInterface
|
||||
*/
|
||||
private function getMockObjectPersister()
|
||||
{
|
||||
return $this->getMock('FOQ\ElasticaBundle\Persister\ObjectPersisterInterface');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Doctrine\Common\Persistence\ObjectManager does not include a clear() method
|
||||
* in its interface, so create a new interface for mocking.
|
||||
*/
|
||||
interface ObjectManager
|
||||
{
|
||||
function clear();
|
||||
}
|
|
@ -6,37 +6,42 @@ use FOQ\ElasticaBundle\IndexManager;
|
|||
|
||||
class IndexManagerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var FOQ\ElasticaBundle\Tests\IndexManager
|
||||
*/
|
||||
private $indexManager = null;
|
||||
private $defaultIndexName;
|
||||
private $indexesByName;
|
||||
private $indexManager;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->indexManager = new IndexManager(array('index1' => 'test1', 'index2' => 'test2'), 'defaultIndex');
|
||||
$this->defaultIndexName = 'index2';
|
||||
$this->indexesByName = array(
|
||||
'index1' => 'test1',
|
||||
'index2' => 'test2',
|
||||
);
|
||||
$this->indexManager = new IndexManager($this->indexesByName, $this->defaultIndexName);
|
||||
}
|
||||
|
||||
public function testThatWeCanGetAllIndexes()
|
||||
public function testGetAllIndexes()
|
||||
{
|
||||
$this->assertEquals(array('index1' => 'test1', 'index2' => 'test2'), $this->indexManager->getAllIndexes());
|
||||
$this->assertEquals($this->indexesByName, $this->indexManager->getAllIndexes());
|
||||
}
|
||||
|
||||
public function testGetIndex()
|
||||
{
|
||||
$this->assertEquals($this->indexesByName['index1'], $this->indexManager->getIndex('index1'));
|
||||
$this->assertEquals($this->indexesByName['index2'], $this->indexManager->getIndex('index2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testThatWeCannotGetIndexWhichWasNotSet()
|
||||
public function testGetIndexShouldThrowExceptionForInvalidName()
|
||||
{
|
||||
$this->indexManager->getIndex('index8');
|
||||
$this->indexManager->getIndex('index3');
|
||||
}
|
||||
|
||||
public function testThatWeCanGetDefaultIndex()
|
||||
|
||||
public function testGetDefaultIndex()
|
||||
{
|
||||
$this->assertEquals('defaultIndex', $this->indexManager->getIndex(false));
|
||||
$this->assertEquals('defaultIndex', $this->indexManager->getDefaultIndex());
|
||||
}
|
||||
|
||||
public function testThatWeCanGetIndex()
|
||||
{
|
||||
$this->assertEquals('test2', $this->indexManager->getIndex('index2'));
|
||||
$this->assertEquals('test2', $this->indexManager->getIndex());
|
||||
$this->assertEquals('test2', $this->indexManager->getDefaultIndex());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\MappingRegistry;
|
||||
|
||||
use FOQ\ElasticaBundle\MappingRegistry;
|
||||
use Elastica_Type;
|
||||
use Elastica_Index;
|
||||
|
||||
class MappingRegistryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Elastica_Type') || !class_exists('Elastica_Index')) {
|
||||
$this->markTestSkipped('The Elastica library classes are not available');
|
||||
}
|
||||
}
|
||||
|
||||
public function testThatCanApplyMappings()
|
||||
{
|
||||
$typeMock = $this->getMockBuilder('Elastica_Type')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$typeMock->expects($this->once())
|
||||
->method('setMapping')
|
||||
->with($this->equalTo(array('mappingArray')));
|
||||
|
||||
$mapping = new MappingRegistry(array(
|
||||
'index/type' => array($typeMock, array('mappingArray'))
|
||||
));
|
||||
|
||||
$mapping->applyMappings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidTypesParametersProvider
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testThatCannotGetTypeFieldForTypeWhichNotExists($indexName, $typeName)
|
||||
{
|
||||
$type = $this->getTypeMock('index', 'type');
|
||||
$mapping = new MappingRegistry(array(
|
||||
'index/type' => array($type, array('mappingArray'))
|
||||
));
|
||||
|
||||
$mapping->getTypeFieldNames($this->getTypeMock($indexName, $typeName));
|
||||
}
|
||||
|
||||
public function testThatCanGetTypeField()
|
||||
{
|
||||
$type = $this->getTypeMock('index', 'type');
|
||||
$mapping = new MappingRegistry(array(
|
||||
'index/type' => array($type, array('mappingArray'))
|
||||
));
|
||||
|
||||
$mapping->getTypeFieldNames($this->getTypeMock('index', 'type'));
|
||||
}
|
||||
|
||||
public static function invalidTypesParametersProvider()
|
||||
{
|
||||
return array(
|
||||
array('index1', 'type'),
|
||||
array('index', 'type2')
|
||||
);
|
||||
}
|
||||
|
||||
private function getTypeMock($indexName, $typeName)
|
||||
{
|
||||
$typeMock = $this->getMockBuilder('Elastica_Type')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$indexMock = $this->getMockBuilder('Elastica_Index')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$indexMock->expects($this->any())
|
||||
->method('getName')
|
||||
->will($this->returnValue($indexName));
|
||||
|
||||
$typeMock->expects($this->any())
|
||||
->method('getIndex')
|
||||
->will($this->returnValue($indexMock));
|
||||
|
||||
$typeMock->expects($this->any())
|
||||
->method('getType')
|
||||
->will($this->returnValue($typeName));
|
||||
|
||||
return $typeMock;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\Populator;
|
||||
|
||||
use FOQ\ElasticaBundle\Populator;
|
||||
use FOQ\ElasticaBundle\Provider\ProviderInterface;
|
||||
use Closure;
|
||||
|
||||
class PopulatorMock extends Populator
|
||||
{
|
||||
public $providers = array();
|
||||
}
|
||||
|
||||
class PopulatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testThatWeCanAddProvider()
|
||||
{
|
||||
$provider = $this->getMock('FOQ\ElasticaBundle\Provider\ProviderInterface', array('populate'));
|
||||
|
||||
$populator = new PopulatorMock(array());
|
||||
$populator->addProvider('l3l0Provider', $provider);
|
||||
|
||||
$this->assertEquals(count($populator->providers), 1);
|
||||
$this->assertArrayHasKey('l3l0Provider', $populator->providers);
|
||||
$this->assertInstanceOf('FOQ\ElasticaBundle\Provider\ProviderInterface', $populator->providers['l3l0Provider']);
|
||||
}
|
||||
|
||||
public function testThatPopulateThroughProviders()
|
||||
{
|
||||
$provider = $this->getMock('FOQ\ElasticaBundle\Provider\ProviderInterface', array('populate'));
|
||||
$provider->expects($this->once())
|
||||
->method('populate');
|
||||
|
||||
$provider2 = $this->getMock('FOQ\ElasticaBundle\Provider\ProviderInterface', array('populate'));
|
||||
$provider2->expects($this->once())
|
||||
->method('populate');
|
||||
|
||||
$populator = new Populator(array('l3l0Provider' => $provider, 'secondProvider' => $provider2));
|
||||
$populator->populate(function ($text) { return $text; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException PHPUnit_Framework_Error
|
||||
*/
|
||||
public function testThatAddProviderHaveToImpelementProviderInterface()
|
||||
{
|
||||
$populator = new Populator(array());
|
||||
$populator->addProvider('provider', new \stdClass());
|
||||
$populator->populate(function ($text) { return $text; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException PHPUnit_Framework_Error
|
||||
*/
|
||||
public function testThatProvidersPassToTheContructorHaveToImplementProviderInterface()
|
||||
{
|
||||
$populator = new Populator(array('provider' => new \stdClass()));
|
||||
$populator->populate(function ($text) { return $text; });
|
||||
}
|
||||
}
|
86
Tests/Provider/ProviderRegistryTest.php
Normal file
86
Tests/Provider/ProviderRegistryTest.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\Provider;
|
||||
|
||||
use FOQ\ElasticaBundle\Provider\ProviderRegistry;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
class ProviderRegistryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $container;
|
||||
private $registry;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||
|
||||
// Mock ContainerInterface::get() to return the service ID
|
||||
$this->container->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnArgument(0));
|
||||
|
||||
$this->registry = new ProviderRegistry();
|
||||
$this->registry->setContainer($this->container);
|
||||
|
||||
$this->registry->addProvider('foo', 'a', 'provider.foo.a');
|
||||
$this->registry->addProvider('foo', 'b', 'provider.foo.b');
|
||||
$this->registry->addProvider('foo', 'c', 'provider.foo.c');
|
||||
$this->registry->addProvider('bar', 'a', 'provider.bar.a');
|
||||
$this->registry->addProvider('bar', 'b', 'provider.bar.b');
|
||||
}
|
||||
|
||||
public function testGetAllProviders()
|
||||
{
|
||||
$allProviders = array(
|
||||
'foo/a' => 'provider.foo.a',
|
||||
'foo/b' => 'provider.foo.b',
|
||||
'foo/c' => 'provider.foo.c',
|
||||
'bar/a' => 'provider.bar.a',
|
||||
'bar/b' => 'provider.bar.b',
|
||||
);
|
||||
|
||||
$this->assertEquals($allProviders, $this->registry->getAllProviders());
|
||||
}
|
||||
|
||||
public function testGetIndexProviders()
|
||||
{
|
||||
$fooProviders = array(
|
||||
'a' => 'provider.foo.a',
|
||||
'b' => 'provider.foo.b',
|
||||
'c' => 'provider.foo.c',
|
||||
);
|
||||
|
||||
$barProviders = array(
|
||||
'a' => 'provider.bar.a',
|
||||
'b' => 'provider.bar.b',
|
||||
);
|
||||
|
||||
$this->assertEquals($fooProviders, $this->registry->getIndexProviders('foo'));
|
||||
$this->assertEquals($barProviders, $this->registry->getIndexProviders('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testGetIndexProvidersWithInvalidIndex()
|
||||
{
|
||||
$this->registry->getIndexProviders('baz');
|
||||
}
|
||||
|
||||
public function testGetProvider()
|
||||
{
|
||||
$this->assertEquals('provider.foo.a', $this->registry->getProvider('foo', 'a'));
|
||||
$this->assertEquals('provider.foo.b', $this->registry->getProvider('foo', 'b'));
|
||||
$this->assertEquals('provider.foo.c', $this->registry->getProvider('foo', 'c'));
|
||||
$this->assertEquals('provider.bar.a', $this->registry->getProvider('bar', 'a'));
|
||||
$this->assertEquals('provider.bar.b', $this->registry->getProvider('bar', 'b'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testGetProviderWithInvalidIndexAndType()
|
||||
{
|
||||
$this->registry->getProvider('bar', 'c');
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\Reseter;
|
||||
|
||||
use FOQ\ElasticaBundle\Reseter;
|
||||
use FOQ\ElasticaBundle\IndexManager;
|
||||
use Elastica_Exception_Response;
|
||||
use Elastica_Response;
|
||||
|
||||
class Index
|
||||
{
|
||||
public $deleted = false;
|
||||
public $created = false;
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->deleted = true;
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->created = true;
|
||||
}
|
||||
}
|
||||
|
||||
class NewIndex
|
||||
{
|
||||
public $deleted = false;
|
||||
public $created = false;
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$jsonResponse = json_encode(array('index' => 'is_new'));
|
||||
|
||||
throw new Elastica_Exception_Response(new Elastica_Response($jsonResponse));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->created = true;
|
||||
}
|
||||
}
|
||||
|
||||
class ReseterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Elastica_Exception_Response') || !class_exists('Elastica_Response')) {
|
||||
$this->markTestSkipped('The Elastica library classes are not available');
|
||||
}
|
||||
}
|
||||
|
||||
public function testThatResetMethodRecreateAllIndexes()
|
||||
{
|
||||
$indexConfig = array();
|
||||
$indexConfig['index_1'] = array();
|
||||
$indexConfig['index_1']['index'] = new Index();
|
||||
$indexConfig['index_1']['config'] = array();
|
||||
$indexConfig['index_2'] = array();
|
||||
$indexConfig['index_2']['index'] = new Index();
|
||||
$indexConfig['index_2']['config'] = array();
|
||||
|
||||
|
||||
$reseter = new Reseter($indexConfig);
|
||||
$reseter->reset();
|
||||
|
||||
$this->assertTrue($indexConfig['index_1']['index']->created);
|
||||
$this->assertTrue($indexConfig['index_2']['index']->created);
|
||||
}
|
||||
|
||||
}
|
138
Tests/ResetterTest.php
Normal file
138
Tests/ResetterTest.php
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
namespace FOQ\ElasticaBundle\Tests\Resetter;
|
||||
|
||||
use FOQ\ElasticaBundle\Resetter;
|
||||
|
||||
class ResetterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $indexConfigsByName;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->indexConfigsByName = array(
|
||||
'foo' => array(
|
||||
'index' => $this->getMockElasticaIndex(),
|
||||
'config' => array(
|
||||
'mappings' => array(
|
||||
'a' => $this->getMockElasticaTypeMapping(),
|
||||
'b' => $this->getMockElasticaTypeMapping(),
|
||||
),
|
||||
),
|
||||
),
|
||||
'bar' => array(
|
||||
'index' => $this->getMockElasticaIndex(),
|
||||
'config' => array(
|
||||
'mappings' => array(
|
||||
'a' => $this->getMockElasticaTypeMapping(),
|
||||
'b' => $this->getMockElasticaTypeMapping(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function testResetAllIndexes()
|
||||
{
|
||||
$this->indexConfigsByName['foo']['index']->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->indexConfigsByName['foo']['config'], true);
|
||||
|
||||
$this->indexConfigsByName['bar']['index']->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->indexConfigsByName['bar']['config'], true);
|
||||
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetAllIndexes();
|
||||
}
|
||||
|
||||
public function testResetIndex()
|
||||
{
|
||||
$this->indexConfigsByName['foo']['index']->expects($this->once())
|
||||
->method('create')
|
||||
->with($this->indexConfigsByName['foo']['config'], true);
|
||||
|
||||
$this->indexConfigsByName['bar']['index']->expects($this->never())
|
||||
->method('create');
|
||||
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndex('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testResetIndexShouldThrowExceptionForInvalidIndex()
|
||||
{
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndex('baz');
|
||||
}
|
||||
|
||||
public function testResetIndexType()
|
||||
{
|
||||
$type = $this->getMockElasticaType();
|
||||
|
||||
$this->indexConfigsByName['foo']['index']->expects($this->once())
|
||||
->method('getType')
|
||||
->with('a')
|
||||
->will($this->returnValue($type));
|
||||
|
||||
$type->expects($this->once())
|
||||
->method('delete');
|
||||
|
||||
$type->expects($this->once())
|
||||
->method('setMapping')
|
||||
->with($this->indexConfigsByName['foo']['config']['mappings']['a']);
|
||||
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndexType('foo', 'a');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testResetIndexTypeShouldThrowExceptionForInvalidIndex()
|
||||
{
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndexType('baz', 'a');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testResetIndexTypeShouldThrowExceptionForInvalidType()
|
||||
{
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndexType('foo', 'c');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Elastica_Index
|
||||
*/
|
||||
private function getMockElasticaIndex()
|
||||
{
|
||||
return $this->getMockBuilder('Elastica_Index')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Elastica_Type
|
||||
*/
|
||||
private function getMockElasticaType()
|
||||
{
|
||||
return $this->getMockBuilder('Elastica_Type')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Elastica_Type_Mapping
|
||||
*/
|
||||
private function getMockElasticaTypeMapping()
|
||||
{
|
||||
return $this->getMockBuilder('Elastica_Type_Mapping')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
"php": ">=5.3.2",
|
||||
"symfony/framework-bundle": "2.1.*",
|
||||
"symfony/console": "2.1.*",
|
||||
"ruflin/elastica": "*"
|
||||
"ruflin/elastica": ">=0.19.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "FOQ\\ElasticaBundle": "" }
|
||||
|
|
Loading…
Reference in a new issue