configArray = $configArray; } /** * Generates the configuration tree. * * @return \Symfony\Component\Config\Definition\NodeInterface */ public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('fos_elastica', 'array'); $this->addClientsSection($rootNode); $this->addIndexesSection($rootNode); $rootNode ->children() ->scalarNode('default_client')->end() ->scalarNode('default_index')->end() ->scalarNode('default_manager')->defaultValue('orm')->end() ->end() ; return $treeBuilder; } /** * Generates the configuration tree. * * @return \Symfony\Component\DependencyInjection\Configuration\NodeInterface */ public function getConfigTree() { return $this->getConfigTreeBuilder()->buildTree(); } /** * Adds the configuration for the "clients" key */ private function addClientsSection(ArrayNodeDefinition $rootNode) { $rootNode ->fixXmlConfig('client') ->children() ->arrayNode('clients') ->useAttributeAsKey('id') ->prototype('array') ->performNoDeepMerging() ->beforeNormalization() ->ifTrue(function($v) { return isset($v['host']) && isset($v['port']); }) ->then(function($v) { return array( 'servers' => array( array( 'host' => $v['host'], 'port' => $v['port'], ) ) ); }) ->end() ->beforeNormalization() ->ifTrue(function($v) { return isset($v['url']); }) ->then(function($v) { return array( 'servers' => array( array( 'url' => $v['url'], ) ) ); }) ->end() ->children() ->arrayNode('servers') ->prototype('array') ->children() ->scalarNode('url')->end() ->scalarNode('host')->end() ->scalarNode('port')->end() ->end() ->end() ->end() ->scalarNode('timeout')->end() ->scalarNode('headers')->end() ->end() ->end() ->end() ->end() ; } /** * Adds the configuration for the "indexes" key */ private function addIndexesSection(ArrayNodeDefinition $rootNode) { $rootNode ->fixXmlConfig('index') ->children() ->arrayNode('indexes') ->useAttributeAsKey('name') ->prototype('array') ->performNoDeepMerging() ->children() ->scalarNode('index_name')->end() ->scalarNode('client')->end() ->scalarNode('finder') ->treatNullLike(true) ->defaultFalse() ->end() ->arrayNode('type_prototype') ->children() ->scalarNode('index_analyzer')->end() ->scalarNode('search_analyzer')->end() ->arrayNode('persistence') ->validate() ->ifTrue(function($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['listener']); }) ->thenInvalid('Propel doesn\'t support listeners') ->ifTrue(function($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['repository']); }) ->thenInvalid('Propel doesn\'t support the "repository" parameter') ->end() ->children() ->scalarNode('driver') ->validate() ->ifNotInArray($this->supportedDrivers) ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode($this->supportedDrivers)) ->end() ->end() ->scalarNode('identifier')->defaultValue('id')->end() ->arrayNode('provider') ->children() ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end() ->scalarNode('batch_size')->defaultValue(100)->end() ->scalarNode('clear_object_manager')->defaultTrue()->end() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('listener') ->children() ->scalarNode('insert')->defaultTrue()->end() ->scalarNode('update')->defaultTrue()->end() ->scalarNode('delete')->defaultTrue()->end() ->scalarNode('service')->end() ->variableNode('is_indexable_callback')->defaultNull()->end() ->end() ->end() ->arrayNode('finder') ->children() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('elastica_to_model_transformer') ->addDefaultsIfNotSet() ->children() ->scalarNode('hydrate')->defaultTrue()->end() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('model_to_elastica_transformer') ->addDefaultsIfNotSet() ->children() ->scalarNode('service')->end() ->end() ->end() ->end() ->end() ->end() ->end() ->variableNode('settings')->defaultValue(array())->end() ->end() ->append($this->getTypesNode()) ->end() ->end() ->end() ; } /** * Returns the array node used for "types". */ protected function getTypesNode() { $builder = new TreeBuilder(); $node = $builder->root('types'); $node ->useAttributeAsKey('name') ->prototype('array') ->treatNullLike(array()) ->children() ->scalarNode('index_analyzer')->end() ->scalarNode('search_analyzer')->end() ->arrayNode('persistence') ->validate() ->ifTrue(function($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['listener']); }) ->thenInvalid('Propel doesn\'t support listeners') ->ifTrue(function($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['repository']); }) ->thenInvalid('Propel doesn\'t support the "repository" parameter') ->end() ->children() ->scalarNode('driver') ->validate() ->ifNotInArray($this->supportedDrivers) ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode($this->supportedDrivers)) ->end() ->end() ->scalarNode('model')->end() ->scalarNode('repository')->end() ->scalarNode('identifier')->defaultValue('id')->end() ->arrayNode('provider') ->children() ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end() ->scalarNode('batch_size')->defaultValue(100)->end() ->scalarNode('clear_object_manager')->defaultTrue()->end() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('listener') ->children() ->scalarNode('insert')->defaultTrue()->end() ->scalarNode('update')->defaultTrue()->end() ->scalarNode('delete')->defaultTrue()->end() ->scalarNode('service')->end() ->variableNode('is_indexable_callback')->defaultNull()->end() ->end() ->end() ->arrayNode('finder') ->children() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('elastica_to_model_transformer') ->addDefaultsIfNotSet() ->children() ->scalarNode('hydrate')->defaultTrue()->end() ->scalarNode('service')->end() ->end() ->end() ->arrayNode('model_to_elastica_transformer') ->addDefaultsIfNotSet() ->children() ->scalarNode('service')->end() ->end() ->end() ->end() ->end() ->end() ->append($this->getMappingsNode()) ->append($this->getSourceNode()) ->append($this->getBoostNode()) ->append($this->getRoutingNode()) ->end() ; return $node; } /** * Returns the array node used for "mappings". */ protected function getMappingsNode() { $builder = new TreeBuilder(); $node = $builder->root('mappings'); $nestings = $this->getNestings(); $childrenNode = $node ->useAttributeAsKey('name') ->prototype('array') ->treatNullLike(array()) ->addDefaultsIfNotSet() ->children(); $this->addFieldConfig($childrenNode, $nestings); return $node; } /** * @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $node The node to which to attach the field config to * @param array $nestings the nested mappings for the current field level */ protected function addFieldConfig($node, $nestings) { $node ->scalarNode('type')->defaultValue('string')->end() ->scalarNode('boost')->end() ->scalarNode('store')->end() ->scalarNode('index')->end() ->scalarNode('index_analyzer')->end() ->scalarNode('search_analyzer')->end() ->scalarNode('analyzer')->end() ->scalarNode('term_vector')->end() ->scalarNode('null_value')->end() ->booleanNode('include_in_all')->defaultValue(true)->end() ->booleanNode('enabled')->defaultValue(true)->end() ->scalarNode('lat_lon')->end() ->scalarNode('index_name')->end() ->booleanNode('omit_norms')->end() ->scalarNode('index_options')->end() ->scalarNode('ignore_above')->end() ->scalarNode('position_offset_gap')->end() ->arrayNode('_parent') ->treatNullLike(array()) ->children() ->scalarNode('type')->end() ->scalarNode('identifier')->defaultValue('id')->end() ->end() ->end(); if (isset($nestings['fields'])) { $this->addNestedFieldConfig($node, $nestings, 'fields'); } if (isset($nestings['properties'])) { $this->addNestedFieldConfig($node, $nestings, 'properties'); } } /** * @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $node The node to which to attach the nested config to * @param array $nestings The nestings for the current field level * @param string $property the name of the nested property ('fields' or 'properties') */ protected function addNestedFieldConfig($node, $nestings, $property) { $childrenNode = $node ->arrayNode($property) ->useAttributeAsKey('name') ->prototype('array') ->treatNullLike(array()) ->addDefaultsIfNotSet() ->children(); $this->addFieldConfig($childrenNode, $nestings[$property]); $childrenNode ->end() ->end() ->end() ; } /** * @return array The unique nested mappings for all types */ protected function getNestings() { if (!isset($this->configArray[0]['indexes'])) { return array(); } $nestings = array(); foreach ($this->configArray[0]['indexes'] as $index) { if (empty($index['types'])) { continue; } foreach ($index['types'] as $type) { $nestings = array_merge_recursive($nestings, $this->getNestingsForType($type['mappings'], $nestings)); } } return $nestings; } /** * @param array $mappings The mappings for the current type * @return array The nested mappings defined for this type */ protected function getNestingsForType(array $mappings = null) { if ($mappings === null) { return array(); } $nestings = array(); foreach ($mappings as $field) { if (isset($field['fields'])) { $this->addPropertyNesting($field, $nestings, 'fields'); } else if (isset($field['properties'])) { $this->addPropertyNesting($field, $nestings, 'properties'); } } return $nestings; } /** * @param array $field The field mapping definition * @param array $nestings The nestings array * @param string $property The nested property name ('fields' or 'properties') */ protected function addPropertyNesting($field, &$nestings, $property) { if (!isset($nestings[$property])) { $nestings[$property] = array(); } $nestings[$property] = array_merge_recursive($nestings[$property], $this->getNestingsForType($field[$property])); } /** * Returns the array node used for "_source". */ protected function getSourceNode() { $builder = new TreeBuilder(); $node = $builder->root('_source'); $node ->children() ->arrayNode('excludes') ->useAttributeAsKey('name') ->prototype('scalar')->end() ->end() ->arrayNode('includes') ->useAttributeAsKey('name') ->prototype('scalar')->end() ->end() ->scalarNode('compress')->end() ->scalarNode('compress_threshold')->end() ->scalarNode('enabled')->end() ->end() ; return $node; } /** * Returns the array node used for "_boost". */ protected function getBoostNode() { $builder = new TreeBuilder(); $node = $builder->root('_boost'); $node ->children() ->scalarNode('name')->end() ->scalarNode('null_value')->end() ->end() ; return $node; } /** * Returns the array node used for "_routing". */ protected function getRoutingNode() { $builder = new TreeBuilder(); $node = $builder->root('_routing'); $node ->children() ->scalarNode('required')->end() ->scalarNode('path')->end() ->end() ; return $node; } }