Completed
Push — master ( 7d3672...a34d6f )
by Simonas
357:48 queued 292:56
created

ONGRFilterManagerExtension   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 6
Bugs 0 Features 1
Metric Value
wmc 21
c 6
b 0
f 1
lcom 1
cbo 9
dl 0
loc 196
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A addFilterFactory() 0 4 1
A getFilterId() 0 4 1
A getFilterManagerId() 0 4 1
A validateFilterNames() 0 16 4
A getFilterFactory() 0 14 2
B addFilterManagers() 0 24 3
A load() 0 11 3
A addFilters() 0 20 3
A addRelation() 0 9 2
A getRelation() 0 7 1
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\FilterManagerBundle\DependencyInjection\Filter\AbstractFilterFactory;
15
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\Definition;
19
use Symfony\Component\DependencyInjection\Reference;
20
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
21
use Symfony\Component\DependencyInjection\Loader;
22
23
/**
24
 * This is the class that loads and manages bundle configuration.
25
 */
26
class ONGRFilterManagerExtension extends Extension
27
{
28
    /**
29
     * @var AbstractFilterFactory[]
30
     */
31
    protected $factories = [];
32
    
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function load(array $configs, ContainerBuilder $container)
37
    {
38
        $configuration = new Configuration();
39
        $config = $this->processConfiguration($configuration, $configs);
40
41
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
42
        $loader->load('services.yml');
43
44
        !isset($config['filters']) ? : $this->addFilters($config['filters'], $container);
45
        !isset($config['managers']) ? : $this->addFilterManagers($config, $container);
46
    }
47
48
    /**
49
     * Adds filter factory.
50
     *
51
     * @param AbstractFilterFactory $factory
52
     */
53
    public function addFilterFactory(AbstractFilterFactory $factory)
54
    {
55
        $this->factories[$factory->getName()] = $factory;
56
    }
57
58
    /**
59
     * Formats filter service id from given name.
60
     *
61
     * @param string $name Filter name.
62
     *
63
     * @return string
64
     */
65
    public static function getFilterId($name)
66
    {
67
        return sprintf('ongr_filter_manager.filter.%s', $name);
68
    }
69
70
    /**
71
     * Formats filter manager service id from given name.
72
     *
73
     * @param string $name Filter manager name.
74
     *
75
     * @return string
76
     */
77
    public static function getFilterManagerId($name)
78
    {
79
        return sprintf('ongr_filter_manager.%s', $name);
80
    }
81
82
    /**
83
     * Adds filters based on configuration.
84
     *
85
     * @param array            $config    Configuration.
86
     * @param ContainerBuilder $container Service container.
87
     */
88
    private function addFilters(array $config, ContainerBuilder $container)
89
    {
90
        $this->validateFilterNames($config);
91
92
        foreach ($config as $type => $filters) {
93
            foreach ($filters as $name => $config) {
94
                $filterDefinition = $this
95
                    ->getFilterFactory($type)
96
                    ->setConfiguration($config)
97
                    ->getDefinition();
98
99
                $this->addRelation($filterDefinition, $config, 'search', 'include');
100
                $this->addRelation($filterDefinition, $config, 'search', 'exclude');
101
                $this->addRelation($filterDefinition, $config, 'reset', 'include');
102
                $this->addRelation($filterDefinition, $config, 'reset', 'exclude');
103
104
                $container->setDefinition(self::getFilterId($name), $filterDefinition);
105
            }
106
        }
107
    }
108
109
    /**
110
     * Checks if filter names are valid.
111
     *
112
     * @param array $filters Filters to validate.
113
     *
114
     * @throws InvalidConfigurationException
115
     */
116
    private function validateFilterNames(array $filters)
117
    {
118
        $existing = [];
119
120
        foreach ($filters as $type => $filters) {
121
            foreach ($filters as $name => $data) {
122
                if (in_array($name, $existing)) {
123
                    throw new InvalidConfigurationException(
124
                        "Found duplicate filter name `{$name}` in `{$type}` filter"
125
                    );
126
                }
127
128
                $existing[] = $name;
129
            }
130
        }
131
    }
132
133
    /**
134
     * Adds filters managers based on configuration.
135
     *
136
     * @param array            $config    Configuration array.
137
     * @param ContainerBuilder $container Service container.
138
     */
139
    private function addFilterManagers(array $config, ContainerBuilder $container)
140
    {
141
        foreach ($config['managers'] as $name => $manager) {
142
            $filterContainer = new Definition('ONGR\FilterManagerBundle\Search\FilterContainer');
143
144
            foreach ($manager['filters'] as $filter) {
145
                $filterContainer->addMethodCall(
146
                    'set',
147
                    [$filter, new Reference(self::getFilterId($filter))]
148
                );
149
            }
150
151
            $managerDefinition = new Definition(
152
                'ONGR\FilterManagerBundle\Search\FilterManager',
153
                [
154
                    $filterContainer,
155
                    new Reference($manager['repository']),
156
                ]
157
            );
158
            $managerDefinition->addTag('es.filter_manager');
159
160
            $container->setDefinition(self::getFilterManagerId($name), $managerDefinition);
161
        }
162
    }
163
164
    /**
165
     * Adds relation to filter.
166
     *
167
     * @param Definition $definition
168
     * @param array      $filter
169
     * @param string     $urlType
170
     * @param string     $relationType
171
     */
172
    private function addRelation(Definition $definition, $filter, $urlType, $relationType)
173
    {
174
        if (!empty($filter['relations'][$urlType][$relationType])) {
175
            $definition->addMethodCall(
176
                'set' . ucfirst($urlType) . 'Relation',
177
                [$this->getRelation($relationType, $filter['relations'][$urlType][$relationType])]
178
            );
179
        }
180
    }
181
182
    /**
183
     * Creates relation definition by given parameters.
184
     *
185
     * @param string $type
186
     * @param array  $relations
187
     *
188
     * @return Definition
189
     */
190
    private function getRelation($type, $relations)
191
    {
192
        return new Definition(
193
            sprintf('ONGR\FilterManagerBundle\Relation\%sRelation', ucfirst($type)),
194
            [$relations]
195
        );
196
    }
197
198
    /**
199
     * Returns filter factory.
200
     *
201
     * @param string $name Factory name.
202
     *
203
     * @return AbstractFilterFactory
204
     *
205
     * @throws InvalidConfigurationException Invaid filter name request.
206
     */
207
    private function getFilterFactory($name)
208
    {
209
        if (array_key_exists($name, $this->factories)) {
210
            return $this->factories[$name];
211
        }
212
        
213
        throw new InvalidConfigurationException(
214
            sprintf(
215
                "Invalid filter name provided in configuration. Got '%s', available: %s",
216
                $name,
217
                implode(', ', array_keys($this->factories))
218
            )
219
        );
220
    }
221
}
222