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());
+ }
+}