diff --git a/composer.json b/composer.json index 63ed911c3..9dba8311d 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,8 @@ "symfony/serializer": "^3.4|^4", "symfony/yaml": "^3.4|^4", "friendsofphp/php-cs-fixer": "^2.2", - "symfony/web-profiler-bundle": "^3.4|^4.0" + "symfony/web-profiler-bundle": "^3.4|^4.0", + "phpdocumentor/type-resolver": "~0.2.1" }, "suggest": { "enqueue/elastica-bundle": "The bundle adds extra features to FOSElasticaBundle bundle. Aimed to improve performance." diff --git a/src/Command/ResetTemplatesCommand.php b/src/Command/ResetTemplatesCommand.php new file mode 100644 index 000000000..0ee59cc7f --- /dev/null +++ b/src/Command/ResetTemplatesCommand.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Command; + +use FOS\ElasticaBundle\Index\TemplateResetter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +/** + * Reset search indexes templates. + */ +final class ResetTemplatesCommand extends Command +{ + protected static $defaultName = 'fos:elastica:reset-templates'; + + /** + * Resetter + * + * @var TemplateResetter + */ + private $resetter; + + public function __construct( + TemplateResetter $resetter + ) { + parent::__construct(); + + $this->resetter = $resetter; + } + + protected function configure() + { + $this + ->setName('fos:elastica:reset-templates') + ->addOption( + 'index', + null, + InputOption::VALUE_OPTIONAL, + 'The index template to reset. If no index template name specified than all templates will be reset', + true + ) + ->addOption( + 'force-delete', + null, + InputOption::VALUE_NONE, + 'Delete all indexes that matches index templates patterns. ' . + 'Aware that pattern may match various indexes.' + ) + ->setDescription('Reset search indexes templates') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $indexTemplate = $input->hasParameterOption('--index') ? $input->getOption('index') : null; + $deleteByPattern = (bool) $input->getOption('force-delete'); + + if ($deleteByPattern) { + $helper = $this->getHelper('question'); + $question = new ConfirmationQuestion('You are going to remove all template indexes. Are you sure?', false); + if (!$helper->ask($input, $output, $question)) { + return; + } + } + + if (is_string($indexTemplate)) { + $output->writeln(sprintf('Resetting template %s', $indexTemplate)); + $this->resetter->resetIndex($indexTemplate, $deleteByPattern); + } else { + $output->writeln('Resetting all templates'); + $this->resetter->resetAllIndexes($deleteByPattern); + } + } +} diff --git a/src/Configuration/IndexConfig.php b/src/Configuration/IndexConfig.php index f25788028..0edb50dfc 100644 --- a/src/Configuration/IndexConfig.php +++ b/src/Configuration/IndexConfig.php @@ -20,36 +20,9 @@ namespace FOS\ElasticaBundle\Configuration; -class IndexConfig +class IndexConfig implements IndexConfigInterface { - /** - * The name of the index for ElasticSearch. - * - * @var string - */ - private $elasticSearchName; - - /** - * The internal name of the index. May not be the same as the name used in ElasticSearch, - * especially if aliases are enabled. - * - * @var string - */ - private $name; - - /** - * An array of settings sent to ElasticSearch when creating the index. - * - * @var array - */ - private $settings; - - /** - * All types that belong to this index. - * - * @var TypeConfig[] - */ - private $types; + use IndexConfigTrait; /** * Indicates if the index should use an alias, allowing an index repopulation to occur @@ -75,54 +48,6 @@ public function __construct($name, array $types, array $config) $this->useAlias = isset($config['useAlias']) ? $config['useAlias'] : false; } - /** - * @return string - */ - public function getElasticSearchName() - { - return $this->elasticSearchName; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return array - */ - public function getSettings() - { - return $this->settings; - } - - /** - * @param string $typeName - * - * @return TypeConfig - * - * @throws \InvalidArgumentException - */ - public function getType($typeName) - { - if (!array_key_exists($typeName, $this->types)) { - throw new \InvalidArgumentException(sprintf('Type "%s" does not exist on index "%s"', $typeName, $this->name)); - } - - return $this->types[$typeName]; - } - - /** - * @return \FOS\ElasticaBundle\Configuration\TypeConfig[] - */ - public function getTypes() - { - return $this->types; - } - /** * @return bool */ diff --git a/src/Configuration/IndexConfigInterface.php b/src/Configuration/IndexConfigInterface.php new file mode 100644 index 000000000..ed85ab768 --- /dev/null +++ b/src/Configuration/IndexConfigInterface.php @@ -0,0 +1,40 @@ + + */ +interface IndexConfigInterface +{ + /** + * @return string + */ + public function getElasticSearchName(); + + /** + * @return string + */ + public function getName(); + + /** + * @return array + */ + public function getSettings(); + + /** + * @param string $typeName + * + * @return TypeConfig + * + * @throws \InvalidArgumentException + */ + public function getType($typeName); + + /** + * @return \FOS\ElasticaBundle\Configuration\TypeConfig[] + */ + public function getTypes(); +} diff --git a/src/Configuration/IndexConfigTrait.php b/src/Configuration/IndexConfigTrait.php new file mode 100644 index 000000000..d6bba8e0f --- /dev/null +++ b/src/Configuration/IndexConfigTrait.php @@ -0,0 +1,96 @@ + + */ +trait IndexConfigTrait +{ + /** + * The name of the index for ElasticSearch. + * + * @var string + */ + protected $elasticSearchName; + + /** + * The internal name of the index. May not be the same as the name used in ElasticSearch, + * especially if aliases are enabled. + * + * @var string + */ + protected $name; + + /** + * An array of settings sent to ElasticSearch when creating the index. + * + * @var array + */ + protected $settings; + + /** + * All types that belong to this index. + * + * @var TypeConfig[] + */ + protected $types; + + /** + * @return string + */ + public function getElasticSearchName() + { + return $this->elasticSearchName; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return array + */ + public function getSettings() + { + return $this->settings; + } + + /** + * @param string $typeName + * + * @return TypeConfig + * + * @throws \InvalidArgumentException + */ + public function getType($typeName) + { + if (!array_key_exists($typeName, $this->types)) { + throw new \InvalidArgumentException(sprintf('Type "%s" does not exist on index "%s"', $typeName, $this->name)); + } + + return $this->types[$typeName]; + } + + /** + * @return \FOS\ElasticaBundle\Configuration\TypeConfig[] + */ + public function getTypes() + { + return $this->types; + } +} diff --git a/src/Configuration/IndexTemplateConfig.php b/src/Configuration/IndexTemplateConfig.php new file mode 100644 index 000000000..b05c06172 --- /dev/null +++ b/src/Configuration/IndexTemplateConfig.php @@ -0,0 +1,49 @@ + + */ +class IndexTemplateConfig implements IndexConfigInterface +{ + use IndexConfigTrait; + + /** + * Index name pattern + * + * @var string + */ + private $template; + + /** + * Constructor expects an array as generated by the Container Configuration builder. + * + * @param string $name + * @param TypeConfig[] $types + * @param array $config + */ + public function __construct($name, array $types, array $config) + { + $this->elasticSearchName = isset($config['elasticSearchName']) ? $config['elasticSearchName'] : $name; + $this->name = $name; + $this->settings = isset($config['settings']) ? $config['settings'] : array(); + if (!isset($config['template'])) { + throw new \InvalidArgumentException('Index template value must be set'); + } + $this->template = $config['template']; + $this->types = $types; + } + + /** + * Gets index name pattern + * + * @return string + */ + public function getTemplate() + { + return $this->template; + } +} diff --git a/src/Configuration/ManagerInterface.php b/src/Configuration/ManagerInterface.php index 43deecec0..af3a997be 100644 --- a/src/Configuration/ManagerInterface.php +++ b/src/Configuration/ManagerInterface.php @@ -19,7 +19,7 @@ interface ManagerInterface /** * Returns configuration for an index. * - * @param $index + * @param string $index * * @return IndexConfig */ diff --git a/src/Configuration/Source/TemplateContainerSource.php b/src/Configuration/Source/TemplateContainerSource.php new file mode 100644 index 000000000..b679813c6 --- /dev/null +++ b/src/Configuration/Source/TemplateContainerSource.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Configuration\Source; + +use FOS\ElasticaBundle\Configuration\IndexTemplateConfig; +use FOS\ElasticaBundle\Configuration\TypeConfig; + +/** + * Returns index and type configuration from the container. + */ +class TemplateContainerSource implements SourceInterface +{ + /** + * The internal container representation of information. + * + * @var array + */ + private $configArray; + + public function __construct(array $configArray) + { + $this->configArray = $configArray; + } + + /** + * Should return all configuration available from the data source. + * + * @return IndexTemplateConfig[] + */ + public function getConfiguration() + { + $indexes = array(); + foreach ($this->configArray as $config) { + $types = $this->getTypes($config); + $index = new IndexTemplateConfig($config['name'], $types, array( + 'elasticSearchName' => $config['elasticsearch_name'], + 'settings' => $config['settings'], + 'template' => $config['template'], + )); + + $indexes[$config['name']] = $index; + } + + return $indexes; + } + + /** + * Builds TypeConfig objects for each type. + * + * @param array $config + * + * @return array + */ + protected function getTypes($config) + { + $types = array(); + + if (isset($config['types'])) { + foreach ($config['types'] as $typeConfig) { + $types[$typeConfig['name']] = new TypeConfig( + $typeConfig['name'], + $typeConfig['mapping'], + $typeConfig['config'] + ); + } + } + + return $types; + } +} diff --git a/src/DependencyInjection/Compiler/ConfigSourcePass.php b/src/DependencyInjection/Compiler/ConfigSourcePass.php index 8ea4e70d5..8670b508f 100644 --- a/src/DependencyInjection/Compiler/ConfigSourcePass.php +++ b/src/DependencyInjection/Compiler/ConfigSourcePass.php @@ -17,6 +17,8 @@ class ConfigSourcePass implements CompilerPassInterface { + const SOURCE_TYPE_INDEX_TEMPLATE = 'index_template'; + /** * {@inheritdoc} */ @@ -26,11 +28,18 @@ public function process(ContainerBuilder $container) return; } - $sources = []; + $indexSources = []; + $indexTemplateSources = []; foreach (array_keys($container->findTaggedServiceIds('fos_elastica.config_source')) as $id) { - $sources[] = new Reference($id); + $tag = $container->findDefinition($id)->getTag('fos_elastica.config_source'); + if (isset($tag[0]['source']) && $tag[0]['source'] === self::SOURCE_TYPE_INDEX_TEMPLATE) { + $indexTemplateSources[] = new Reference($id); + } else { + $indexSources[] = new Reference($id); + } } - $container->getDefinition('fos_elastica.config_manager')->replaceArgument(0, $sources); + $container->getDefinition('fos_elastica.config_manager')->replaceArgument(0, $indexSources); + $container->getDefinition('fos_elastica.config_manager.index_templates')->replaceArgument(0, $indexTemplateSources); } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 82d79a0bf..519174e4b 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -49,6 +49,7 @@ public function getConfigTreeBuilder() $this->addClientsSection($rootNode); $this->addIndexesSection($rootNode); + $this->addIndexTemplatesSection($rootNode); $rootNode ->children() @@ -545,4 +546,34 @@ private function createTreeBuilderNode($name) return $node; } + + /** + * Adds the configuration for the "index_templates" key. + * + * @param ArrayNodeDefinition $rootNode + * + * @return void + */ + private function addIndexTemplatesSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->fixXmlConfig('index_template') + ->children() + ->arrayNode('index_templates') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('template_name') + ->info('Defaults to the name of the index template, but can be modified if the index name is different in ElasticSearch') + ->end() + ->scalarNode('template')->isRequired()->end() + ->scalarNode('client')->end() + ->variableNode('settings')->defaultValue([])->end() + ->end() + ->append($this->getTypesNode()) + ->end() + ->end() + ->end() + ; + } } diff --git a/src/DependencyInjection/FOSElasticaExtension.php b/src/DependencyInjection/FOSElasticaExtension.php index 4960d7b9f..498f042b6 100644 --- a/src/DependencyInjection/FOSElasticaExtension.php +++ b/src/DependencyInjection/FOSElasticaExtension.php @@ -39,6 +39,13 @@ class FOSElasticaExtension extends Extension */ private $indexConfigs = []; + /** + * An array of index templates as configured by the extension. + * + * @var array + */ + private $indexTemplateConfigs = array(); + /** * If we've encountered a type mapped to a specific persistence driver, it will be loaded * here. @@ -91,9 +98,23 @@ public function load(array $configs, ContainerBuilder $container) $container->getAlias('fos_elastica.index')->setPublic(true); $container->setParameter('fos_elastica.default_index', $config['default_index']); + if ($usedIndexNames = \array_intersect_key($config['indexes'], $config['index_templates'])) { + throw new \DomainException( + \sprintf( + 'Index names "%s" are already in use and can not be used for index templates names', + \implode('","', \array_keys($usedIndexNames)) + ) + ); + } + $this->loadIndexTemplates($config['index_templates'], $container); + $container->getDefinition('fos_elastica.config_source.container')->replaceArgument(0, $this->indexConfigs); + $container + ->getDefinition('fos_elastica.config_source.template_container') + ->replaceArgument(0, $this->indexTemplateConfigs); $this->loadIndexManager($container); + $this->loadIndexTemplateManager($container); $this->createDefaultManagerAlias($config['default_manager'], $container); } @@ -195,6 +216,59 @@ private function loadIndexes(array $indexes, ContainerBuilder $container) $indexable->replaceArgument(0, $indexableCallbacks); } + /** + * Loads the configured indexes. + * + * @param array $indexTemplates An array of indexes configurations + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws \InvalidArgumentException + * + * @return void + */ + private function loadIndexTemplates(array $indexTemplates, ContainerBuilder $container) + { + $indexableCallbacks = array(); + foreach ($indexTemplates as $name => $indexTemplate) { + $indexId = sprintf('fos_elastica.index_template.%s', $name); + $indexTemplateName = isset($indexTemplate['template_name']) ? $indexTemplate['template_name'] : $name; + + $indexDef = new ChildDefinition('fos_elastica.index_template_prototype'); + $indexDef->setFactory([new Reference('fos_elastica.client'), 'getIndexTemplate']); + $indexDef->replaceArgument(0, $indexTemplateName); + $indexDef->addTag('fos_elastica.index_template', array( + 'name' => $name, + )); + + if (isset($indexTemplate['client'])) { + $client = $this->getClient($indexTemplate['client']); + $indexDef->setFactory([$client, 'getIndexTemplate']); + } + + $container->setDefinition($indexId, $indexDef); + $reference = new Reference($indexId); + + $this->indexTemplateConfigs[$name] = array( + 'elasticsearch_name' => $indexTemplateName, + 'reference' => $reference, + 'name' => $name, + 'settings' => $indexTemplate['settings'], + 'template' => $indexTemplate['template'], + ); + + $this->loadTypes( + (array) $indexTemplate['types'], + $container, + $this->indexTemplateConfigs[$name], + $indexableCallbacks + ); + } + + if ($indexableCallbacks) { + throw new \RuntimeException('`indexable_callback` option is not supported by index templates'); + } + } + /** * Loads the configured index finders. * @@ -229,7 +303,7 @@ private function loadIndexFinder(ContainerBuilder $container, $name, Reference $ * @param array $indexConfig * @param array $indexableCallbacks */ - private function loadTypes(array $types, ContainerBuilder $container, array $indexConfig, array &$indexableCallbacks) + private function loadTypes(array $types, ContainerBuilder $container, array &$indexConfig, array &$indexableCallbacks) { foreach ($types as $name => $type) { $indexName = $indexConfig['name']; @@ -276,7 +350,7 @@ private function loadTypes(array $types, ContainerBuilder $container, array $ind null; } - $this->indexConfigs[$indexName]['types'][$name] = $typeConfig; + $indexConfig['types'][$name] = $typeConfig; if (isset($type['persistence'])) { $this->loadTypePersistenceIntegration($type['persistence'], $container, new Reference($typeId), $indexName, $name); @@ -712,6 +786,23 @@ private function loadIndexManager(ContainerBuilder $container) $managerDef->replaceArgument(0, $indexRefs); } + /** + * Load index template manager + * + * @param ContainerBuilder $container + * + * @return void + */ + private function loadIndexTemplateManager(ContainerBuilder $container) + { + $indexTemplateRefs = array_map(function ($index) { + return $index['reference']; + }, $this->indexTemplateConfigs); + + $managerDef = $container->getDefinition('fos_elastica.index_template_manager'); + $managerDef->replaceArgument(0, $indexTemplateRefs); + } + /** * Makes sure a specific driver has been loaded. * diff --git a/src/Elastica/Client.php b/src/Elastica/Client.php index c766acb93..dce6d2a44 100644 --- a/src/Elastica/Client.php +++ b/src/Elastica/Client.php @@ -31,6 +31,13 @@ class Client extends BaseClient */ private $indexCache = []; + /** + * Stores created index template to avoid recreation. + * + * @var array + */ + private $indexTemplateCache = array(); + /** * Symfony's debugging Stopwatch. * @@ -77,6 +84,15 @@ public function getIndex($name) return $this->indexCache[$name] = new Index($this, $name); } + public function getIndexTemplate($name) + { + if (isset($this->indexTemplateCache[$name])) { + return $this->indexTemplateCache[$name]; + } + + return $this->indexTemplateCache[$name] = new IndexTemplate($this, $name); + } + /** * Sets a stopwatch instance for debugging purposes. * diff --git a/src/Elastica/IndexTemplate.php b/src/Elastica/IndexTemplate.php new file mode 100644 index 000000000..58594118b --- /dev/null +++ b/src/Elastica/IndexTemplate.php @@ -0,0 +1,14 @@ + + */ +class IndexTemplate extends BaseIndexTemplate +{ + +} diff --git a/src/Index/IndexTemplateManager.php b/src/Index/IndexTemplateManager.php new file mode 100644 index 000000000..60719c7b7 --- /dev/null +++ b/src/Index/IndexTemplateManager.php @@ -0,0 +1,43 @@ + + */ +class IndexTemplateManager +{ + /** + * Templates + * + * @var array + */ + private $templates; + + public function __construct(array $templates) + { + $this->templates = $templates; + } + + /** + * Gets an index template by its name. + * + * @param string $name Index template to return + * + * @return IndexTemplate + * + * @throws \InvalidArgumentException if no index template exists for the given name + */ + public function getIndexTemplate($name) + { + if (!isset($this->templates[$name])) { + throw new \InvalidArgumentException(sprintf('The index template "%s" does not exist', $name)); + } + + return $this->templates[$name]; + } +} diff --git a/src/Index/MappingBuilder.php b/src/Index/MappingBuilder.php index 60c6ec6aa..c0a2c7e0a 100644 --- a/src/Index/MappingBuilder.php +++ b/src/Index/MappingBuilder.php @@ -11,7 +11,8 @@ namespace FOS\ElasticaBundle\Index; -use FOS\ElasticaBundle\Configuration\IndexConfig; +use FOS\ElasticaBundle\Configuration\IndexConfigInterface; +use FOS\ElasticaBundle\Configuration\IndexTemplateConfig; use FOS\ElasticaBundle\Configuration\TypeConfig; class MappingBuilder @@ -19,11 +20,11 @@ class MappingBuilder /** * Builds mappings for an entire index. * - * @param IndexConfig $indexConfig + * @param IndexConfigInterface $indexConfig * * @return array */ - public function buildIndexMapping(IndexConfig $indexConfig) + public function buildIndexMapping(IndexConfigInterface $indexConfig) { $typeMappings = []; foreach ($indexConfig->getTypes() as $typeConfig) { @@ -44,6 +45,20 @@ public function buildIndexMapping(IndexConfig $indexConfig) return $mapping; } + /** + * Builds mappings for an entire index template. + * + * @param IndexTemplateConfig $indexTemplateConfig + * + * @return array + */ + public function buildIndexTemplateMapping(IndexTemplateConfig $indexTemplateConfig) + { + $mapping = $this->buildIndexMapping($indexTemplateConfig); + $mapping['template'] = $indexTemplateConfig->getTemplate(); + return $mapping; + } + /** * Builds mappings for a single type. * diff --git a/src/Index/Resetter.php b/src/Index/Resetter.php index b86b8a5b1..da638a769 100644 --- a/src/Index/Resetter.php +++ b/src/Index/Resetter.php @@ -12,9 +12,9 @@ namespace FOS\ElasticaBundle\Index; use Elastica\Exception\ResponseException; -use Elastica\Index; use Elastica\Type\Mapping; use FOS\ElasticaBundle\Configuration\ManagerInterface; +use Elastica\Client; use FOS\ElasticaBundle\Event\IndexResetEvent; use FOS\ElasticaBundle\Event\TypeResetEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -22,7 +22,7 @@ /** * Deletes and recreates indexes. */ -class Resetter +class Resetter implements ResetterInterface { /** * @var AliasProcessor @@ -55,6 +55,7 @@ class Resetter * @param AliasProcessor $aliasProcessor * @param MappingBuilder $mappingBuilder * @param EventDispatcherInterface $eventDispatcher + * @param Client $client */ public function __construct( ManagerInterface $configManager, diff --git a/src/Index/ResetterInterface.php b/src/Index/ResetterInterface.php new file mode 100644 index 000000000..9bb8c5fd1 --- /dev/null +++ b/src/Index/ResetterInterface.php @@ -0,0 +1,26 @@ + + */ +interface ResetterInterface +{ + /** + * Reset all indexes + * + * @return void + */ + public function resetAllIndexes(); + + /** + * Reset index + * + * @param string $indexName + * + * @return void + */ + public function resetIndex($indexName); +} diff --git a/src/Index/TemplateResetter.php b/src/Index/TemplateResetter.php new file mode 100644 index 000000000..8e864ea04 --- /dev/null +++ b/src/Index/TemplateResetter.php @@ -0,0 +1,83 @@ + + */ +class TemplateResetter implements ResetterInterface +{ + /*** + * @var ManagerInterface + */ + private $configManager; + + /** + * @var MappingBuilder + */ + private $mappingBuilder; + + /** + * @var Client + */ + private $client; + + /** + * Index template manager + * + * @var IndexTemplateManager + */ + private $indexTemplateManager; + + public function __construct( + ManagerInterface $configManager, + MappingBuilder $mappingBuilder, + Client $client, + IndexTemplateManager $indexTemplateManager + ) { + $this->configManager = $configManager; + $this->mappingBuilder = $mappingBuilder; + $this->client = $client; + $this->indexTemplateManager = $indexTemplateManager; + } + + public function resetAllIndexes($deleteIndexes = false) + { + foreach ($this->configManager->getIndexNames() as $name) { + $this->resetIndex($name, $deleteIndexes); + } + } + + public function resetIndex($indexName, $deleteIndexes = false) + { + $indexTemplateConfig = $this->configManager->getIndexConfiguration($indexName); + if (!$indexTemplateConfig instanceof IndexTemplateConfig) { + throw new \RuntimeException( + \sprintf('Incorrect index configuration object. Expecting IndexTemplateConfig, but got: %s ', \get_class($indexTemplateConfig)) + ); + } + $indexTemplate = $this->indexTemplateManager->getIndexTemplate($indexName); + + $mapping = $this->mappingBuilder->buildIndexTemplateMapping($indexTemplateConfig); + if ($deleteIndexes) { + $this->deleteTemplateIndexes($indexTemplateConfig); + } + $indexTemplate->create($mapping); + } + + /** + * Delete all template indexes + * + * @param IndexTemplateConfig $template + */ + public function deleteTemplateIndexes(IndexTemplateConfig $template) + { + $this->client->request($template->getTemplate() . '/', Request::DELETE); + } +} diff --git a/src/Resources/config/commands.xml b/src/Resources/config/commands.xml index 9aef8b42f..0b9f752d2 100644 --- a/src/Resources/config/commands.xml +++ b/src/Resources/config/commands.xml @@ -30,6 +30,11 @@ + + + + + diff --git a/src/Resources/config/config.xml b/src/Resources/config/config.xml index 66104a2df..373cd67de 100644 --- a/src/Resources/config/config.xml +++ b/src/Resources/config/config.xml @@ -26,6 +26,10 @@ + + + + diff --git a/src/Resources/config/index.xml b/src/Resources/config/index.xml index 08365810b..1d1d17a81 100644 --- a/src/Resources/config/index.xml +++ b/src/Resources/config/index.xml @@ -20,6 +20,11 @@ + + + + + @@ -30,6 +35,11 @@ + + + + + @@ -39,6 +49,14 @@ + + + + + + + + diff --git a/src/Resources/config/source.xml b/src/Resources/config/source.xml index db00dbfce..8fd283617 100644 --- a/src/Resources/config/source.xml +++ b/src/Resources/config/source.xml @@ -11,5 +11,10 @@ + + + + + diff --git a/tests/Functional/IndexTemplatesTest.php b/tests/Functional/IndexTemplatesTest.php new file mode 100644 index 000000000..cc8cbb7c1 --- /dev/null +++ b/tests/Functional/IndexTemplatesTest.php @@ -0,0 +1,35 @@ + + */ +class IndexTemplatesTest extends WebTestCase +{ + public function testContainer() + { + static::bootKernel(['test_case' => 'Basic']); + + $instance = static::$kernel->getContainer()->get('fos_elastica.index_template.index_template_example_1'); + $this->assertInstanceOf(IndexTemplate::class, $instance); + $this->assertInstanceOf(OriginalIndexTemplate::class, $instance); + + $instance = static::$kernel->getContainer()->get('fos_elastica.config_manager.index_templates'); + $this->assertInstanceOf(ConfigManager::class, $instance); + + $instance = static::$kernel->getContainer()->get('fos_elastica.index_template_manager'); + $this->assertInstanceOf(IndexTemplateManager::class, $instance); + + $instance = static::$kernel->getContainer()->get('fos_elastica.template_resetter'); + $this->assertInstanceOf(TemplateResetter::class, $instance); + } +} diff --git a/tests/Functional/ResetTemplatesCommandTest.php b/tests/Functional/ResetTemplatesCommandTest.php new file mode 100644 index 000000000..ce2ddba6c --- /dev/null +++ b/tests/Functional/ResetTemplatesCommandTest.php @@ -0,0 +1,131 @@ + + */ +class ResetTemplatesCommandTest extends WebTestCase +{ + /** + * Client + * + * @var Client + */ + private $client; + + /** + * Application + * + * @var Application + */ + private $application; + + protected function setUp() + { + static::bootKernel(['test_case' => 'Basic']); + $this->application = $application = new Application(static::$kernel); + // required for old supported Symfony + $application->all(); + + $this->client = static::$kernel->getContainer()->get('fos_elastica.client'); + } + + public function testResetAllTemplates() + { + $this->clearTemplates(); + + $command = $this->application->find('fos:elastica:reset-templates'); + $commandTester = new CommandTester($command); + $commandTester->execute(array( + 'command' => $command->getName(), + )); + + $output = $commandTester->getDisplay(); + $this->assertContains('Resetting all templates', $output); + + $templates = $this->fetchAllTemplates(); + $this->assertArrayHasKey('index_template_2_name', $templates); + $this->assertArrayHasKey('index_template_1_name', $templates); + } + + public function testResetAllTemplatesAndForceDelete() + { + $this->clearTemplates(); + + $command = $this->application->find('fos:elastica:reset-templates'); + $commandTester = new CommandTester($command); + $commandTester->setInputs(['yes']); + $commandTester->execute( + [ + 'command' => $command->getName(), + '--force-delete' => true, + ] + ); + + $output = $commandTester->getDisplay(); + $this->assertContains('You are going to remove all template indexes. Are you sure?', $output); + $this->assertContains('Resetting all templates', $output); + + $templates = $this->fetchAllTemplates(); + $this->assertArrayHasKey('index_template_2_name', $templates); + $this->assertArrayHasKey('index_template_1_name', $templates); + } + + public function testResetExactTemplate() + { + $this->clearTemplates(); + + $command = $this->application->find('fos:elastica:reset-templates'); + $commandTester = new CommandTester($command); + $commandTester->execute(array( + 'command' => $command->getName(), + '--index' => 'index_template_example_1', + )); + + $output = $commandTester->getDisplay(); + $this->assertContains('Resetting template', $output); + $this->assertContains('index_template_example_1', $output); + + $templates = $this->fetchAllTemplates(); + $this->assertArrayHasKey('index_template_1_name', $templates); + } + + public function testResetExactTemplateAndForceDelete() + { + $this->clearTemplates(); + + $command = $this->application->find('fos:elastica:reset-templates'); + $commandTester = new CommandTester($command); + $commandTester->setInputs(['yes']); + $commandTester->execute(array( + 'command' => $command->getName(), + '--index' => 'index_template_example_1', + '--force-delete' => true, + )); + + $output = $commandTester->getDisplay(); + $this->assertContains('You are going to remove all template indexes. Are you sure?', $output); + $this->assertContains('Resetting template', $output); + $this->assertContains('index_template_example_1', $output); + + $templates = $this->fetchAllTemplates(); + $this->assertArrayHasKey('index_template_1_name', $templates); + } + + private function clearTemplates() + { + $this->client->request('_template/*', Request::DELETE); + } + + private function fetchAllTemplates() + { + $reponse = $this->client->request('_template', Request::GET); + return $reponse->getData(); + } +} diff --git a/tests/Functional/app/Basic/config.yml b/tests/Functional/app/Basic/config.yml index c0593087d..48071a1ce 100644 --- a/tests/Functional/app/Basic/config.yml +++ b/tests/Functional/app/Basic/config.yml @@ -94,3 +94,29 @@ fos_elastica: null_mappings: properties: ~ empty_index: ~ + + index_templates: + index_template_example_1: + client: 'default' + template_name: 'index_template_1_name' + template: 'index_template_1_name_*' + settings: + # templates should accept custom settings + number_of_shards: 2 + number_of_replicas: 0 + types: + some_type: + properties: + document_name_field_1: { type: string, index: not_analyzed } + index_template_example_2: + client: 'default' + template_name: 'index_template_2_name' + template: 'index_template_2_name_*' + settings: + # templates should accept custom settings + number_of_shards: 2 + number_of_replicas: 0 + types: + some_type: + properties: + document_name_field_2: { type: string, index: not_analyzed } diff --git a/tests/Unit/Configuration/IndexTemplateConfigTest.php b/tests/Unit/Configuration/IndexTemplateConfigTest.php new file mode 100644 index 000000000..983ee5ad2 --- /dev/null +++ b/tests/Unit/Configuration/IndexTemplateConfigTest.php @@ -0,0 +1,38 @@ + 'index_template_elastic_name1', + 'settings' => array(1), + 'template' => 't*', + ); + $indexTemplate = new IndexTemplateConfig($name, array(), $config); + $this->assertEquals($name, $indexTemplate->getName()); + $this->assertEquals( + $config, + array( + 'elasticSearchName' => $indexTemplate->getElasticSearchName(), + 'settings' => $indexTemplate->getSettings(), + 'template' => $indexTemplate->getTemplate(), + ) + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testIncorrectInstantiate() + { + $name = 'index_template1'; + new IndexTemplateConfig($name, array(), array()); + } +} diff --git a/tests/Unit/Configuration/Source/TemplateContainerSourceTest.php b/tests/Unit/Configuration/Source/TemplateContainerSourceTest.php new file mode 100644 index 000000000..dc962849b --- /dev/null +++ b/tests/Unit/Configuration/Source/TemplateContainerSourceTest.php @@ -0,0 +1,64 @@ + + */ +class TemplateContainerSourceTest extends TestCase +{ + public function testGetEmptyConfiguration() + { + $containerSource = new TemplateContainerSource([]); + $indexes = $containerSource->getConfiguration(); + $this->assertSame([], $indexes); + } + + public function testGetConfiguration() + { + $containerSource = new TemplateContainerSource( + [ + [ + 'name' => 'some_index_template', + 'types' => [ + [ + 'name' => 'some_type', + 'mapping' => [ + 'some_field' => [], + ], + 'config' => [ + 'date_detection' => 'date_detection_value', + ], + ], + ], + 'elasticsearch_name' => 'some_search_name', + 'settings' => [ + 'some_setting' => 'setting_value' + ], + 'template' => 'some_index_config_*', + ], + ] + ); + $indexes = $containerSource->getConfiguration(); + $this->assertInstanceOf(IndexTemplateConfig::class, $indexes['some_index_template']); + $templateConfig = $indexes['some_index_template']; + $this->assertEquals('some_index_template', $templateConfig->getName()); + $this->assertEquals('some_index_config_*', $templateConfig->getTemplate()); + $this->assertEquals( + [ + 'some_setting' => 'setting_value' + ], + $templateConfig->getSettings() + ); + $this->assertEquals('some_search_name', $templateConfig->getElasticSearchName()); + $this->assertInstanceOf(TypeConfig::class, $type = $templateConfig->getType('some_type')); + $this->assertEquals('some_type', $type->getName()); + $this->assertEquals(['some_field' => []], $type->getMapping()); + $this->assertEquals('date_detection_value', $type->getDateDetection()); + } +} diff --git a/tests/Unit/DependencyInjection/ConfigSourcePassTest.php b/tests/Unit/DependencyInjection/ConfigSourcePassTest.php new file mode 100644 index 000000000..57463295d --- /dev/null +++ b/tests/Unit/DependencyInjection/ConfigSourcePassTest.php @@ -0,0 +1,87 @@ +container = $this->prophesize(ContainerBuilder::class); + } + + public function testProcessWithoutConfigManager() + { + $this->container + ->hasDefinition('fos_elastica.config_manager') + ->shouldBeCalled() + ->willReturn(false); + + $pass = new ConfigSourcePass(); + $pass->process($this->container->reveal()); + + $this->container->getDefinition('fos_elastica.config_manager')->shouldNotBeCalled(); + $this->container->getDefinition('fos_elastica.config_manager.index_templates')->shouldNotBeCalled(); + } + + public function testProcessWithConfigManager() + { + $this->container + ->hasDefinition('fos_elastica.config_manager') + ->shouldBeCalled() + ->willReturn(true); + + $this->container + ->findTaggedServiceIds('fos_elastica.config_source') + ->shouldBeCalled() + ->willReturn( + [ + 'index_definition_id' => null, + 'index_template_definition_id' => null, + ] + ); + + $indexDefinition = $this->prophesize(Definition::class); + $indexDefinition->getTag('fos_elastica.config_source') + ->shouldBeCalled() + ->willReturn([]); + $this->container + ->findDefinition('index_definition_id') + ->shouldBeCalled() + ->willReturn($indexDefinition->reveal()); + + + $indexTemplateDefinition = $this->prophesize(Definition::class); + $indexTemplateDefinition->getTag('fos_elastica.config_source') + ->shouldBeCalled() + ->willReturn([]); + $this->container + ->findDefinition('index_template_definition_id') + ->shouldBeCalled() + ->willReturn($indexTemplateDefinition->reveal()); + + $configManagerDefinition = $this->prophesize(Definition::class); + $configManagerDefinition->replaceArgument(0, ['index_definition_id']); + $this->container + ->getDefinition('fos_elastica.config_manager') + ->shouldBeCalled() + ->willReturn($configManagerDefinition); + + $templateConfigManagerDefinition = $this->prophesize(Definition::class); + $templateConfigManagerDefinition->replaceArgument(0, ['index_template_definition_id']); + $this->container + ->getDefinition('fos_elastica.config_manager.index_templates') + ->shouldBeCalled() + ->willReturn($templateConfigManagerDefinition); + + $pass = new ConfigSourcePass(); + $pass->process($this->container->reveal()); + } +} diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 66eab0d58..a6c1fbd22 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -34,6 +34,7 @@ public function testUnconfiguredConfiguration() $this->assertSame([ 'clients' => [], 'indexes' => [], + 'index_templates' => [], 'default_manager' => 'orm', ], $configuration); } @@ -310,6 +311,32 @@ public function testAWSConfig() $this->assertTrue($connection['ssl']); } + public function testIndexTemplates() + { + $configuration = $this->getConfigs( + [ + 'index_templates' => [ + 'some_template' => [ + 'template' => 'some_template_*', + 'client' => 'default', + 'types' => [ + 'some_type' => [ + 'properties' => [ + 'some_field' => [], + ], + ], + ], + ], + ], + ] + ); + $indexTemplate = $configuration['index_templates']['some_template']; + $this->assertSame('some_template_*', $indexTemplate['template']); + $this->assertSame('default', $indexTemplate['client']); + $this->assertSame([], $indexTemplate['settings']); + $this->assertArrayHasKey('some_field', $indexTemplate['types']['some_type']['properties']); + } + private function getConfigs(array $configArray) { $configuration = new Configuration(true); diff --git a/tests/Unit/DependencyInjection/FOSElasticaExtensionTest.php b/tests/Unit/DependencyInjection/FOSElasticaExtensionTest.php index 52bfe5c39..b7acfd1ce 100644 --- a/tests/Unit/DependencyInjection/FOSElasticaExtensionTest.php +++ b/tests/Unit/DependencyInjection/FOSElasticaExtensionTest.php @@ -471,4 +471,49 @@ public function testShouldNotRegisterDoctrineORMListenerIfDisabled() $this->assertFalse($container->hasDefinition('fos_elastica.listener.acme_index.acme_type')); } + + public function testIndexTemplates() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + $extension = new FOSElasticaExtension(); + $extension->load([ + 'fos_elastica' => [ + 'clients' => [ + 'default' => ['host' => 'a_host', 'port' => 'a_port'], + ], + 'indexes' => [ + 'some_index' => [ + 'types' => [], + ], + ], + 'index_templates' => [ + 'some_index_template' => [ + 'template' => 'some_index_template_*', + 'client' => 'default', + 'types' => [ + 'some_type' => [ + 'properties' => ['text' => null], + ], + ], + ], + ], + ], + ], $container); + + $this->assertTrue($container->hasDefinition('fos_elastica.index_template.some_index_template')); + $definition = $container->getDefinition('fos_elastica.index_template.some_index_template'); + $this->assertTrue($definition->hasTag('fos_elastica.index_template')); + $tag = $definition->getTag('fos_elastica.index_template'); + $this->assertSame( + [ + [ + 'name' => 'some_index_template', + ], + ], + $tag + ); + $this->assertTrue($container->hasDefinition('fos_elastica.index_template.some_index_template.some_type')); + } } diff --git a/tests/Unit/Elastica/ClientTest.php b/tests/Unit/Elastica/ClientTest.php index 7a75616b1..15073fceb 100644 --- a/tests/Unit/Elastica/ClientTest.php +++ b/tests/Unit/Elastica/ClientTest.php @@ -57,4 +57,11 @@ public function testRequestsAreLogged() $this->assertInstanceOf(Response::class, $response); } + + public function testGetIndexTemplate() + { + $client = new Client(); + $template = $client->getIndexTemplate('some_index'); + $this->assertSame($template, $client->getIndexTemplate('some_index')); + } } diff --git a/tests/Unit/Elastica/IndexTemplateTest.php b/tests/Unit/Elastica/IndexTemplateTest.php new file mode 100644 index 000000000..907325a16 --- /dev/null +++ b/tests/Unit/Elastica/IndexTemplateTest.php @@ -0,0 +1,20 @@ + + */ +class IndexTemplateTest extends TestCase +{ + public function testInstantiate() + { + $template = new IndexTemplate($this->prophesize(Client::class)->reveal(), 'some_name'); + $this->assertInstanceOf(BaseIndexTemplate::class, $template); + } +} diff --git a/tests/Unit/Index/IndexTemplateManagerTest.php b/tests/Unit/Index/IndexTemplateManagerTest.php new file mode 100644 index 000000000..d8cf6eb88 --- /dev/null +++ b/tests/Unit/Index/IndexTemplateManagerTest.php @@ -0,0 +1,63 @@ + + */ +class IndexTemplateManagerTest extends TestCase +{ + /** + * Test get index template + * + * @param array $templates + * @param string $name + * @param string $expectedTemplate + * @param string|null $expectedException + * + * @return void + * + * @dataProvider provideTestGetIndexTemplate + */ + public function testGetIndexTemplate(array $templates, $name, $expectedTemplate, $expectedException = null) + { + if (null !== $expectedException) { + $this->expectException($expectedException); + } + $templateManager = new IndexTemplateManager($templates); + $this->assertSame($expectedTemplate, $templateManager->getIndexTemplate($name)); + } + + public function provideTestGetIndexTemplate() + { + return [ + 'empty templates' => [ + 'templates' => [], + 'name' => 'any template', + 'expectedTemplate' => [], + 'expectedException' => \InvalidArgumentException::class, + ], + 'expected template found' => [ + 'templates' => [ + 'first template' => $firstTemplate = $this->prophesize(IndexTemplate::class)->reveal(), + 'second template' => $secondTemplate = $this->prophesize(IndexTemplate::class)->reveal(), + ], + 'name' => 'second template', + 'expectedTemplate' => $secondTemplate, + ], + 'expected template not found' => [ + 'templates' => [ + 'first template' => $firstTemplate = $this->prophesize(IndexTemplate::class)->reveal(), + 'second template' => $secondTemplate = $this->prophesize(IndexTemplate::class)->reveal(), + ], + 'name' => 'some template', + 'expectedTemplate' => null, + 'expectedException' => \InvalidArgumentException::class, + ], + ]; + } +} diff --git a/tests/Unit/Index/MappingBuilderTest.php b/tests/Unit/Index/MappingBuilderTest.php index 29a99d957..8faf9ff7a 100644 --- a/tests/Unit/Index/MappingBuilderTest.php +++ b/tests/Unit/Index/MappingBuilderTest.php @@ -11,25 +11,49 @@ namespace FOS\ElasticaBundle\Tests\Unit\Index; +use FOS\ElasticaBundle\Configuration\IndexTemplateConfig; use FOS\ElasticaBundle\Configuration\TypeConfig; use FOS\ElasticaBundle\Index\MappingBuilder; use PHPUnit\Framework\TestCase; class MappingBuilderTest extends TestCase { + /** + * @var TypeConfig + */ + private $typeConfig; + /** * @var MappingBuilder */ private $builder; - protected function setUp() - { - $this->builder = new MappingBuilder(); - } + /** + * @var array + */ + private $typeMapping; - public function testMappingBuilderStoreProperty() + protected function setUp() { - $typeConfig = new TypeConfig('typename', [ + $this->typeMapping = [ + 'properties' => [ + 'storeless' => [ + 'type' => 'text', + ], + 'stored' => [ + 'type' => 'text', + 'store' => true, + ], + 'unstored' => [ + 'type' => 'text', + 'store' => false, + ], + ], + '_parent' => [ + 'type' => 'parent_type', + ], + ]; + $this->typeConfig = new TypeConfig('typename', [ 'properties' => [ 'storeless' => [ 'type' => 'text', @@ -49,8 +73,12 @@ public function testMappingBuilderStoreProperty() 'property' => 'parent_property', ], ]); + $this->builder = new MappingBuilder(); + } - $mapping = $this->builder->buildTypeMapping($typeConfig); + public function testMappingBuilderStoreProperty() + { + $mapping = $this->builder->buildTypeMapping($this->typeConfig); $this->assertArrayNotHasKey('store', $mapping['properties']['storeless']); $this->assertArrayHasKey('store', $mapping['properties']['stored']); @@ -62,4 +90,24 @@ public function testMappingBuilderStoreProperty() $this->assertArrayNotHasKey('identifier', $mapping['_parent']); $this->assertArrayNotHasKey('property', $mapping['_parent']); } + + public function testBuildIndexTemplateMapping() + { + $config = new IndexTemplateConfig( + 'some_template', + [ + $this->typeConfig + ], + ['template' => 'index_template_*'] + ); + $this->assertEquals( + [ + 'template' => 'index_template_*', + 'mappings' => [ + 'typename' => $this->typeMapping + ] + ], + $this->builder->buildIndexTemplateMapping($config) + ); + } } diff --git a/tests/Unit/Index/ResetterTest.php b/tests/Unit/Index/ResetterTest.php index 5b5ee982e..7b79591a5 100644 --- a/tests/Unit/Index/ResetterTest.php +++ b/tests/Unit/Index/ResetterTest.php @@ -22,6 +22,7 @@ use FOS\ElasticaBundle\Index\IndexManager; use FOS\ElasticaBundle\Index\MappingBuilder; use FOS\ElasticaBundle\Index\Resetter; +use FOS\ElasticaBundle\Index\ResetterInterface; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -283,4 +284,9 @@ private function mockType($typeName, $indexName, TypeConfig $typeConfig, IndexCo return $index; } + + public function testResetterImplementsResetterInterface() + { + $this->assertInstanceOf(ResetterInterface::class, $this->resetter); + } } diff --git a/tests/Unit/Index/TemplateResetterTest.php b/tests/Unit/Index/TemplateResetterTest.php new file mode 100644 index 000000000..3a02b968a --- /dev/null +++ b/tests/Unit/Index/TemplateResetterTest.php @@ -0,0 +1,185 @@ + + */ +class TemplateResetterTest extends TestCase +{ + /** + * @var ManagerInterface + */ + private $configManager; + + /** + * @var MappingBuilder + */ + private $mappingBuilder; + + /** + * @var Client + */ + private $client; + + /** + * @var IndexTemplateManager + */ + private $templateManager; + + /** + * @var TemplateResetter + */ + private $resetter; + + protected function setUp() + { + $this->configManager = $this->prophesize(ManagerInterface::class); + $this->mappingBuilder = $this->prophesize(MappingBuilder::class); + $this->client = $this->prophesize(Client::class); + $this->templateManager = $this->prophesize(IndexTemplateManager::class); + $this->resetter = new TemplateResetter( + $this->configManager->reveal(), + $this->mappingBuilder->reveal(), + $this->client->reveal(), + $this->templateManager->reveal() + ); + } + + public function testResetterImplementsResetterInterface() + { + $this->assertInstanceOf(ResetterInterface::class, $this->resetter); + } + + public function testResetAllIndexes() + { + // assemble + $names = ['first_template']; + $mapping = ['properties' => []]; + $this->configManager->getIndexNames() + ->willReturn($names); + $this->configManager->getIndexConfiguration('first_template') + ->willReturn($indexTemplateConfig = $this->prophesize(IndexTemplateConfig::class)->reveal()); + $indexTemplate = $this->prophesize(IndexTemplate::class); + $this->templateManager->getIndexTemplate('first_template') + ->willReturn($indexTemplate->reveal()); + $this->mappingBuilder->buildIndexTemplateMapping($indexTemplateConfig) + ->willReturn($mapping); + + // assert + $indexTemplate->create($mapping) + ->shouldBeCalled(); + $this->client->request(Argument::any(), Request::DELETE) + ->shouldNotBeCalled(); + + // act + $this->resetter->resetAllIndexes(); + } + + public function testResetAllIndexesAndDelete() + { + // assemble + $names = ['first_template']; + $mapping = ['properties' => []]; + $this->configManager->getIndexNames() + ->willReturn($names); + $indexTemplateConfig = $this->prophesize(IndexTemplateConfig::class); + $this->configManager->getIndexConfiguration('first_template') + ->willReturn($indexTemplateConfig->reveal()); + $indexTemplate = $this->prophesize(IndexTemplate::class); + $this->templateManager->getIndexTemplate('first_template') + ->willReturn($indexTemplate->reveal()); + $this->mappingBuilder->buildIndexTemplateMapping($indexTemplateConfig) + ->willReturn($mapping); + + // assert + $indexTemplate->create($mapping) + ->shouldBeCalled(); + $this->client->request('first_template/', Request::DELETE) + ->shouldBeCalled(); + $indexTemplateConfig->getTemplate() + ->shouldBeCalled() + ->willReturn('first_template'); + + // act + $this->resetter->resetAllIndexes(true); + } + + public function testResetIndex() + { + // assemble + $name = 'first_template'; + $mapping = ['properties' => []]; + $this->configManager->getIndexConfiguration('first_template') + ->willReturn($indexTemplateConfig = $this->prophesize(IndexTemplateConfig::class)->reveal()); + $indexTemplate = $this->prophesize(IndexTemplate::class); + $this->templateManager->getIndexTemplate('first_template') + ->willReturn($indexTemplate->reveal()); + $this->mappingBuilder->buildIndexTemplateMapping($indexTemplateConfig) + ->willReturn($mapping); + + // assert + $indexTemplate->create($mapping) + ->shouldBeCalled(); + $this->client->request(Argument::any(), Request::DELETE) + ->shouldNotBeCalled(); + + // act + $this->resetter->resetIndex($name); + } + + public function testResetIndexIndexeAndDelete() + { + // assemble + $name = 'first_template'; + $mapping = ['properties' => []]; + $indexTemplateConfig = $this->prophesize(IndexTemplateConfig::class); + $this->configManager->getIndexConfiguration('first_template') + ->willReturn($indexTemplateConfig->reveal()); + $indexTemplate = $this->prophesize(IndexTemplate::class); + $this->templateManager->getIndexTemplate('first_template') + ->willReturn($indexTemplate->reveal()); + $this->mappingBuilder->buildIndexTemplateMapping($indexTemplateConfig) + ->willReturn($mapping); + + // assert + $indexTemplate->create($mapping) + ->shouldBeCalled(); + $this->client->request('first_template/', Request::DELETE) + ->shouldBeCalled(); + $indexTemplateConfig->getTemplate() + ->shouldBeCalled() + ->willReturn('first_template'); + + // act + $this->resetter->resetIndex($name, true); + } + + public function testDeleteTemplateIndexes() + { + // assemble + $name = 'some_template'; + $template = $this->prophesize(IndexTemplateConfig::class); + + // assert + $template->getTemplate() + ->shouldBeCalled() + ->willReturn($name); + $this->client->request('some_template/', Request::DELETE) + ->shouldBeCalled(); + + $this->resetter->deleteTemplateIndexes($template->reveal()); + } +}