These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the ONGR package. |
||
5 | * |
||
6 | * (c) NFQ Technologies UAB <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace ONGR\FilterManagerBundle\DependencyInjection; |
||
13 | |||
14 | use ONGR\ElasticsearchDSL\Aggregation\TermsAggregation; |
||
15 | use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
||
16 | use Symfony\Component\Config\Definition\Builder\ParentNodeDefinitionInterface; |
||
17 | use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
||
18 | use Symfony\Component\Config\Definition\ConfigurationInterface; |
||
19 | |||
20 | /** |
||
21 | * This is the class that validates and merges configuration from app/config files. |
||
22 | */ |
||
23 | class Configuration implements ConfigurationInterface |
||
24 | { |
||
25 | /** |
||
26 | * {@inheritdoc} |
||
27 | */ |
||
28 | public function getConfigTreeBuilder() |
||
29 | { |
||
30 | $treeBuilder = new TreeBuilder(); |
||
31 | $rootNode = $treeBuilder->root('ongr_filter_manager'); |
||
32 | |||
33 | $this->addManagersSection($rootNode); |
||
34 | $this->addFiltersSection($rootNode); |
||
35 | $this->addCacheSection($rootNode); |
||
36 | |||
37 | return $treeBuilder; |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * @param ArrayNodeDefinition $rootNode |
||
42 | */ |
||
43 | private function addManagersSection(ArrayNodeDefinition $rootNode) |
||
44 | { |
||
45 | $rootNode |
||
46 | ->children() |
||
47 | ->arrayNode('managers') |
||
48 | ->requiresAtLeastOneElement() |
||
49 | ->useAttributeAsKey('name') |
||
50 | ->prototype('array') |
||
51 | ->children() |
||
52 | ->scalarNode('name') |
||
53 | ->info('Filter manager name') |
||
54 | ->end() |
||
55 | ->arrayNode('filters') |
||
56 | ->info('Filter names to include in manager.') |
||
57 | ->prototype('scalar')->end() |
||
58 | ->end() |
||
59 | ->scalarNode('repository') |
||
60 | ->isRequired() |
||
61 | ->info('ElasticsearchBundle repository used for fetching data.') |
||
62 | ->end() |
||
63 | ->end() |
||
64 | ->end() |
||
65 | ->end() |
||
66 | ->end(); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * @param ArrayNodeDefinition $rootNode |
||
71 | */ |
||
72 | private function addFiltersSection(ArrayNodeDefinition $rootNode) |
||
73 | { |
||
74 | $rootNode |
||
75 | ->children() |
||
76 | ->arrayNode('filters') |
||
77 | ->validate() |
||
78 | ->ifTrue( |
||
79 | function ($v) { |
||
80 | $v = array_filter($v); |
||
81 | |||
82 | return empty($v); |
||
83 | } |
||
84 | ) |
||
85 | ->thenInvalid('At least single filter must be configured.') |
||
86 | ->end() |
||
87 | ->children() |
||
88 | ->append($this->buildFilterTree('choice')) |
||
89 | ->append($this->buildFilterTree('dynamic_aggregate')) |
||
90 | ->append($this->buildFilterTree('multi_dynamic_aggregate')) |
||
91 | ->append($this->buildFilterTree('multi_choice')) |
||
92 | ->append($this->buildFilterTree('match')) |
||
93 | ->append($this->buildFilterTree('fuzzy')) |
||
94 | ->append($this->buildFilterTree('sort')) |
||
95 | ->append($this->buildFilterTree('pager')) |
||
96 | ->append($this->buildFilterTree('range')) |
||
97 | ->append($this->buildFilterTree('date_range')) |
||
98 | ->append($this->buildFilterTree('field_value')) |
||
99 | ->append($this->buildFilterTree('document_value')) |
||
100 | ->end() |
||
101 | ->end() |
||
102 | ->end(); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * @param ArrayNodeDefinition $rootNode |
||
107 | */ |
||
108 | private function addCacheSection(ArrayNodeDefinition $rootNode) |
||
109 | { |
||
110 | $rootNode |
||
111 | ->children() |
||
112 | ->arrayNode('cache') |
||
113 | ->addDefaultsIfNotSet() |
||
114 | ->children() |
||
115 | ->scalarNode('engine') |
||
116 | ->info('Caching engine service name.') |
||
117 | ->defaultValue('es.cache_engine') |
||
118 | ->end() |
||
119 | ->arrayNode('exclude') |
||
120 | ->info('Array of filter names to exclude from caching.') |
||
121 | ->prototype('scalar')->end() |
||
122 | ->end() |
||
123 | ->integerNode('life_time') |
||
124 | ->info('Cached search life time.') |
||
125 | ->defaultValue(10800) |
||
126 | ->end() |
||
127 | ->end() |
||
128 | ->end() |
||
129 | ->end(); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Builds filter config tree for given filter name. |
||
134 | * |
||
135 | * @param string $filterName |
||
136 | * |
||
137 | * @return ArrayNodeDefinition |
||
138 | */ |
||
139 | private function buildFilterTree($filterName) |
||
140 | { |
||
141 | $filter = new ArrayNodeDefinition($filterName); |
||
142 | |||
143 | /** @var ParentNodeDefinitionInterface $node */ |
||
144 | $node = $filter |
||
145 | ->requiresAtLeastOneElement() |
||
146 | ->useAttributeAsKey('name') |
||
147 | ->prototype('array') |
||
148 | ->children() |
||
149 | ->scalarNode('name')->end() |
||
150 | ->arrayNode('relations') |
||
151 | ->children() |
||
152 | ->append($this->buildRelationsTree('search')) |
||
153 | ->append($this->buildRelationsTree('reset')) |
||
154 | ->end() |
||
155 | ->end() |
||
156 | ->scalarNode('field') |
||
157 | ->info('Document field name.') |
||
158 | ->end() |
||
159 | ->arrayNode('tags') |
||
160 | ->info('Filter tags that will be passed to view data.') |
||
161 | ->prototype('scalar')->end() |
||
162 | ->end() |
||
163 | ->end(); |
||
164 | |||
165 | if ($filterName != 'field_value') { |
||
166 | $node |
||
167 | ->children() |
||
168 | ->scalarNode('request_field') |
||
169 | ->info('URL parameter name.') |
||
170 | ->isRequired() |
||
171 | ->end() |
||
172 | ->end(); |
||
173 | } |
||
174 | |||
175 | switch ($filterName) { |
||
176 | case 'choice': |
||
177 | View Code Duplication | case 'multi_choice': |
|
0 ignored issues
–
show
|
|||
178 | $node |
||
179 | ->children() |
||
180 | ->integerNode('size') |
||
181 | ->info('Result size to return.') |
||
182 | ->end() |
||
183 | ->arrayNode('sort') |
||
184 | ->children() |
||
185 | ->enumNode('type') |
||
186 | ->values(['_term', '_count']) |
||
187 | ->defaultValue('_term') |
||
188 | ->end() |
||
189 | ->enumNode('order') |
||
190 | ->values(['asc', 'desc']) |
||
191 | ->defaultValue('asc') |
||
192 | ->end() |
||
193 | ->arrayNode('priorities')->prototype('scalar')->end() |
||
194 | ->end() |
||
195 | ->end() |
||
196 | ->end(); |
||
197 | break; |
||
198 | case 'dynamic_aggregate': |
||
199 | View Code Duplication | case 'multi_dynamic_aggregate': |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
200 | $node |
||
201 | ->children() |
||
202 | ->scalarNode('name_field') |
||
203 | ->info('Name of the field to provide the aggregated values from.') |
||
204 | ->end() |
||
205 | ->arrayNode('sort') |
||
206 | ->children() |
||
207 | ->enumNode('type') |
||
208 | ->values(['_term', '_count']) |
||
209 | ->defaultValue('_term') |
||
210 | ->end() |
||
211 | ->enumNode('order') |
||
212 | ->values(['asc', 'desc']) |
||
213 | ->defaultValue('asc') |
||
214 | ->end() |
||
215 | ->arrayNode('priorities')->prototype('scalar')->end() |
||
216 | ->end() |
||
217 | ->end() |
||
218 | ->end(); |
||
219 | break; |
||
220 | case 'match': |
||
221 | $node |
||
222 | ->children() |
||
223 | ->scalarNode('operator') |
||
224 | ->info('The operator flag.') |
||
225 | ->end() |
||
226 | ->scalarNode('fuzziness') |
||
227 | ->info('The maximum edit distance.') |
||
228 | ->end() |
||
229 | ->end(); |
||
230 | break; |
||
231 | case 'fuzzy': |
||
232 | $node |
||
233 | ->children() |
||
234 | ->scalarNode('fuzziness') |
||
235 | ->info('The maximum edit distance.') |
||
236 | ->end() |
||
237 | ->integerNode('prefix_length') |
||
238 | ->info( |
||
239 | 'The number of initial characters which will not be “fuzzified”. |
||
240 | This helps to reduce the number of terms which must be examined.' |
||
241 | ) |
||
242 | ->end() |
||
243 | ->integerNode('max_expansions') |
||
244 | ->info('The maximum number of terms that the fuzzy query will expand to.') |
||
245 | ->end() |
||
246 | ->end(); |
||
247 | break; |
||
248 | case 'sort': |
||
249 | $node |
||
250 | ->children() |
||
251 | ->arrayNode('choices') |
||
252 | ->prototype('array') |
||
253 | ->beforeNormalization() |
||
254 | ->always( |
||
255 | function ($v) { |
||
256 | if (empty($v['fields']) && !empty($v['field'])) { |
||
257 | $field = ['field' => $v['field']]; |
||
258 | if (array_key_exists('order', $v)) { |
||
259 | $field['order'] = $v['order']; |
||
260 | } |
||
261 | if (array_key_exists('mode', $v)) { |
||
262 | $field['mode'] = $v['mode']; |
||
263 | } |
||
264 | $v['fields'][] = $field; |
||
265 | } |
||
266 | |||
267 | if (empty($v['label'])) { |
||
268 | $v['label'] = $v['fields'][0]['field']; |
||
269 | } |
||
270 | |||
271 | return $v; |
||
272 | } |
||
273 | ) |
||
274 | ->end() |
||
275 | ->addDefaultsIfNotSet() |
||
276 | ->children() |
||
277 | ->scalarNode('label')->end() |
||
278 | ->scalarNode('field')->end() |
||
279 | ->scalarNode('order')->defaultValue('asc')->end() |
||
280 | ->scalarNode('mode')->defaultNull()->end() |
||
281 | ->scalarNode('key')->info('Custom parameter value')->end() |
||
282 | ->booleanNode('default')->defaultFalse()->end() |
||
283 | ->arrayNode('fields') |
||
284 | ->isRequired() |
||
285 | ->requiresAtLeastOneElement() |
||
286 | ->prototype('array') |
||
287 | ->children() |
||
288 | ->scalarNode('field')->isRequired()->end() |
||
289 | ->scalarNode('order')->defaultValue('asc')->end() |
||
290 | ->scalarNode('mode')->defaultNull()->end() |
||
291 | ->end() |
||
292 | ->end() |
||
293 | ->end() |
||
294 | ->end() |
||
295 | ->end() |
||
296 | ->end(); |
||
297 | break; |
||
298 | case 'pager': |
||
299 | $node |
||
300 | ->children() |
||
301 | ->integerNode('count_per_page') |
||
302 | ->info('Item count per page') |
||
303 | ->defaultValue(10) |
||
304 | ->end() |
||
305 | ->integerNode('max_pages') |
||
306 | ->info('Max pages displayed in pager at once.') |
||
307 | ->defaultValue(8) |
||
308 | ->end() |
||
309 | ->end(); |
||
310 | break; |
||
311 | case 'range': |
||
312 | case 'date_range': |
||
313 | $node |
||
314 | ->children() |
||
315 | ->booleanNode('inclusive') |
||
316 | ->info('Whether filter should match range ends.') |
||
317 | ->defaultFalse() |
||
318 | ->end() |
||
319 | ->end(); |
||
320 | break; |
||
321 | case 'field_value': |
||
322 | $node |
||
323 | ->children() |
||
324 | ->scalarNode('value') |
||
325 | ->info('Value which will be used for filtering.') |
||
326 | ->isRequired() |
||
327 | ->end(); |
||
328 | break; |
||
329 | case 'document_value': |
||
330 | $node |
||
331 | ->children() |
||
332 | ->scalarNode('document_field') |
||
333 | ->info('Field name from document object to pass to the filter.') |
||
334 | ->isRequired() |
||
335 | ->end(); |
||
336 | break; |
||
337 | default: |
||
338 | // Default config is enough. |
||
339 | break; |
||
340 | } |
||
341 | |||
342 | return $filter; |
||
343 | } |
||
344 | |||
345 | /** |
||
346 | * Builds relations config tree for given relation name. |
||
347 | * |
||
348 | * @param string $relationType |
||
349 | * |
||
350 | * @return ArrayNodeDefinition |
||
351 | */ |
||
352 | private function buildRelationsTree($relationType) |
||
353 | { |
||
354 | $filter = new ArrayNodeDefinition($relationType); |
||
355 | |||
356 | $filter |
||
357 | ->validate() |
||
358 | ->ifTrue( |
||
359 | function ($v) { |
||
360 | return empty($v['include']) && empty($v['exclude']); |
||
361 | } |
||
362 | ) |
||
363 | ->thenInvalid('Relation must have "include" or "exclude" fields specified.') |
||
364 | ->end() |
||
365 | ->validate() |
||
366 | ->ifTrue( |
||
367 | function ($v) { |
||
368 | return !empty($v['include']) && !empty($v['exclude']); |
||
369 | } |
||
370 | ) |
||
371 | ->thenInvalid('Relation must have only "include" or "exclude" fields specified.') |
||
372 | ->end() |
||
373 | ->children() |
||
374 | ->arrayNode('include') |
||
375 | ->beforeNormalization() |
||
376 | ->ifString() |
||
377 | ->then( |
||
378 | function ($v) { |
||
379 | return [$v]; |
||
380 | } |
||
381 | )->end() |
||
382 | ->prototype('scalar')->end() |
||
383 | ->end() |
||
384 | ->arrayNode('exclude') |
||
385 | ->beforeNormalization() |
||
386 | ->ifString() |
||
387 | ->then( |
||
388 | function ($v) { |
||
389 | return [$v]; |
||
390 | } |
||
391 | ) |
||
392 | ->end() |
||
393 | ->prototype('scalar')->end() |
||
394 | ->end() |
||
395 | ->end(); |
||
396 | |||
397 | return $filter; |
||
398 | } |
||
399 | } |
||
400 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.