Completed
Push — master ( 0f15f1...06dce9 )
by Pavel
09:44
created

processEntityConfiguration()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 50
Code Lines 37

Duplication

Lines 14
Ratio 28 %

Code Coverage

Tests 36
CRAP Score 7.049

Importance

Changes 0
Metric Value
dl 14
loc 50
ccs 36
cts 40
cp 0.9
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 37
nc 20
nop 2
crap 7.049
1
<?php
2
3
namespace ScayTrase\Api\Cruds\DependencyInjection;
4
5
use Doctrine\Common\Persistence\ObjectManager;
6
use Doctrine\ORM\EntityRepository;
7
use ScayTrase\Api\Cruds\Controller\CountController;
8
use ScayTrase\Api\Cruds\Controller\CreateController;
9
use ScayTrase\Api\Cruds\Controller\DeleteController;
10
use ScayTrase\Api\Cruds\Controller\ReadController;
11
use ScayTrase\Api\Cruds\Controller\SearchController;
12
use ScayTrase\Api\Cruds\Controller\UpdateController;
13
use ScayTrase\Api\Cruds\Criteria\NestedCriteriaConfigurator;
14
use Symfony\Component\DependencyInjection\ContainerBuilder;
15
use Symfony\Component\DependencyInjection\Definition;
16
use Symfony\Component\DependencyInjection\DefinitionDecorator;
17
use Symfony\Component\DependencyInjection\Reference;
18
19
final class CrudsEntitiesConfigurator
20
{
21
    /** @var  ContainerBuilder */
22
    private $container;
23
24
    /**
25
     * CrudsEntitiesConfigurator constructor.
26
     *
27
     * @param ContainerBuilder $container
28
     */
29 22
    public function __construct(ContainerBuilder $container)
30
    {
31 22
        $this->container = $container;
32 22
    }
33
34 22
    public function processEntityConfiguration($name, $config)
35
    {
36 22
        $class      = $config['class'];
37 22
        $actions    = $config['actions'];
38 22
        $prefix     = $config['prefix'];
39 22
        $manager    = $config['manager'];
40 22
        $repository = $config['repository'];
41 22
        $mount      = $config['mount'];
42
43 22 View Code Duplication
        if (null === $manager) {
1 ignored issue
show
Duplication introduced by
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...
44 22
            $manager = new Definition(ObjectManager::class);
45 22
            $manager->setFactory([new Reference('doctrine'), 'getManagerForClass']);
46 22
            $manager->setArguments([$class]);
47 22
        } else {
48
            $manager = new Reference($this->filterReference($manager));
49
        }
50
51 22 View Code Duplication
        if (null === $repository) {
1 ignored issue
show
Duplication introduced by
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...
52 22
            $repositoryDefinition = new Definition(EntityRepository::class);
53 22
            $repositoryDefinition->setFactory([$manager, 'getRepository']);
54 22
            $repositoryDefinition->setArguments([$class]);
55 22
        } else {
56
            $repositoryDefinition = new Reference($this->filterReference($repository));
57
        }
58
59 22
        foreach ($actions as $action => $actionConfig) {
60 22
            if (!$actionConfig['enabled']) {
61
                continue;
62
            }
63
64 22
            $actionConfig['name']       = $name;
65 22
            $actionConfig['class']      = $class;
66 22
            $actionConfig['mount']      = $mount;
67 22
            $actionConfig['repository'] = $repositoryDefinition;
68 22
            $actionConfig['path']       = $prefix . $actionConfig['path'];
69 22
            $actionConfig['manager']    = $manager;
70 22
            $actionConfig['prefix']     = $prefix;
71 22
            $function                   = new \ReflectionMethod($this, 'register' . ucfirst($action) . 'Action');
72 22
            $args                       = [];
73
74 22
            foreach ($function->getParameters() as $parameter) {
75 22
                if (array_key_exists($parameter->getName(), $actionConfig)) {
1 ignored issue
show
Bug introduced by
Consider using $parameter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
76 22
                    $args[] = $actionConfig[$parameter->getName()];
1 ignored issue
show
Bug introduced by
Consider using $parameter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
77 22
                } else {
78
                    $args[] = $parameter->getDefaultValue();
79
                }
80 22
            }
81 22
            $function->invokeArgs($this, $args);
82 22
        }
83 22
    }
84
85
    /**
86
     * @param string $reference
87
     *
88
     * @return string
89
     */
90 22
    private function filterReference($reference)
91
    {
92 22
        return ltrim($reference, '@');
93
    }
94
95 22
    public function registerCreateAction($mount, $name, $class, $factory, $processor, $path, $manager)
96
    {
97 22
        if (null === $factory) {
98 22
            $factory = new DefinitionDecorator('cruds.factory.reflection');
99 22
            $factory->setArguments([$class, []]);
100 22
        } else {
101
            $factory = new Reference($this->filterReference($factory));
102
        }
103
104 22 View Code Duplication
        if (null === $processor) {
0 ignored issues
show
Duplication introduced by
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...
105 22
            $processor = new Reference('cruds.processor.property_access');
106 22
        } else {
107
            $processor = new Reference($this->filterReference($processor));
108
        }
109
110 22
        $definition = new Definition(CreateController::class);
111 22
        $definition->setArguments(
112
            [
113 22
                $processor,
114 22
                $manager,
115 22
                $factory,
116 22
                $this->getEvm(),
117
            ]
118 22
        );
119 22
        $definition->setPublic(true);
120
121 22
        $actionName   = 'create';
122 22
        $controllerId = $this->generateControllerId($name, $actionName);
123 22
        $this->container->setDefinition($controllerId, $definition);
124
125 22
        $action = $controllerId . ':' . CreateController::ACTION;
126 22
        $this->registerRoute(
127 22
            $mount,
128 22
            $name,
129 22
            $actionName,
130 22
            $path,
131 22
            $action,
132 22
            ['POST'],
133 22
            ['class' => $class, 'arguments' => ['data']]
134 22
        );
135 22
    }
136
137
    /**
138
     * @return Reference
139
     */
140 22
    private function getEvm()
141
    {
142 22
        return new Reference('event_dispatcher');
143
    }
144
145
    /**
146
     * @param string $name
147
     * @param string $actionName
148
     *
149
     * @return string
150
     */
151 22
    private function generateControllerId($name, $actionName)
152
    {
153 22
        return $this->normalize('cruds.generated_controller.' . $name . '.' . $actionName);
154
    }
155
156
    /**
157
     * @param string $name
158
     *
159
     * @return string
160
     */
161 22
    private function normalize($name)
162
    {
163 22
        return str_replace('-', '_', $name);
164
    }
165
166
    /**
167
     * @param string $mount
168
     * @param string $name
169
     * @param string $actionName
170
     * @param string $path
171
     * @param string $action
172
     * @param array  $methods
173
     * @param array  $options
174
     *
175
     * @return Definition
176
     * @throws \InvalidArgumentException
177
     */
178 22
    private function registerRoute($mount, $name, $actionName, $path, $action, array $methods, array $options = [])
179
    {
180 22
        return $this->getLoaderDefinition()->addMethodCall(
181 22
            'addRoute',
182
            [
183 22
                $mount,
184 22
                $this->normalize('cruds.routing.' . $name . '.' . $actionName),
185 22
                $path,
186 22
                $action,
187 22
                $methods,
188 22
                array_replace(
189
                    [
190 22
                        'action' => $actionName,
191 22
                        'mount'  => $mount,
192 22
                    ],
193
                    $options
194 22
                ),
195
            ]
196 22
        );
197
    }
198
199 22
    private function getLoaderDefinition()
200
    {
201 22
        return $this->container->getDefinition('cruds.api.router_loader');
202
    }
203
204 22 View Code Duplication
    public function registerReadAction($mount, $name, $path, $repository, $class)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
205
    {
206 22
        $definition = new Definition(ReadController::class);
207 22
        $definition->setArguments(
208
            [
209 22
                $repository,
210 22
                $this->getEvm(),
211
            ]
212 22
        );
213
214 22
        $actionName   = 'read';
215 22
        $controllerId = $this->generateControllerId($name, $actionName);
216 22
        $this->container->setDefinition($controllerId, $definition);
217
218 22
        $action = $controllerId . ':' . ReadController::ACTION;
219 22
        $this->registerRoute(
220 22
            $mount,
221 22
            $name,
222 22
            $actionName,
223 22
            $path,
224 22
            $action,
225 22
            ['GET', 'POST'],
226 22
            ['class' => $class, 'arguments' => ['identifier']]
227 22
        );
228 22
    }
229
230 22
    public function registerUpdateAction($mount, $name, $path, $repository, $processor, $manager, $class)
231
    {
232 22 View Code Duplication
        if (null === $processor) {
0 ignored issues
show
Duplication introduced by
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...
233 22
            $processor = new Reference('cruds.processor.property_access');
234 22
        } else {
235
            $processor = new Reference($this->filterReference($processor));
236
        }
237
238 22
        $definition = new Definition(UpdateController::class);
239 22
        $definition->setArguments(
240
            [
241 22
                $repository,
242 22
                $processor,
243 22
                $manager,
244 22
                $this->getEvm(),
245
            ]
246 22
        );
247
248 22
        $actionName   = 'update';
249 22
        $controllerId = $this->generateControllerId($name, $actionName);
250 22
        $this->container->setDefinition($controllerId, $definition);
251
252 22
        $action = $controllerId . ':' . UpdateController::ACTION;
253 22
        $this->registerRoute(
254 22
            $mount,
255 22
            $name,
256 22
            $actionName,
257 22
            $path,
258 22
            $action,
259 22
            ['POST', 'PATCH'],
260 22
            ['class' => $class, 'arguments' => ['identifier', 'data']]
261 22
        );
262 22
    }
263
264 22 View Code Duplication
    public function registerDeleteAction($mount, $name, $path, $repository, $manager, $class)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
265
    {
266 22
        $definition = new Definition(DeleteController::class);
267 22
        $definition->setArguments(
268
            [
269 22
                $repository,
270 22
                $manager,
271 22
                $this->getEvm(),
272
            ]
273 22
        );
274
275 22
        $actionName   = 'delete';
276 22
        $controllerId = $controllerId = $this->generateControllerId($name, $actionName);
277 22
        $this->container->setDefinition($controllerId, $definition);
278
279 22
        $action = $controllerId . ':' . DeleteController::ACTION;
280 22
        $this->registerRoute(
281 22
            $mount,
282 22
            $name,
283 22
            $actionName,
284 22
            $path,
285 22
            $action,
286 22
            ['POST', 'DELETE'],
287 22
            ['class' => $class, 'arguments' => ['identifier']]
288 22
        );
289 22
    }
290
291 22
    public function registerSearchAction($mount, $name, $path, $class, $repository, $criteria, $count_path, $prefix)
292
    {
293
294 22
        if (is_array($criteria)) {
295
            $filterArray = [];
296
            foreach ($criteria as $filter => $reference) {
297
                $filterArray[$filter] = new Reference($this->filterReference($reference));
298
            }
299
            $criteriaConfigurator = new Definition(NestedCriteriaConfigurator::class);
300
            $criteriaConfigurator->setArguments([$filterArray]);
301
        } else {
302 22
            $criteriaConfigurator = new Reference($this->filterReference($criteria));
303
        }
304
305 22
        $definition = new Definition(SearchController::class);
306 22
        $definition->setArguments(
307
            [
308 22
                $class,
309 22
                $repository,
310 22
                $criteriaConfigurator,
311 22
                $this->getEvm(),
312
            ]
313 22
        );
314
315 22
        $actionName   = 'search';
316 22
        $controllerId = $this->generateControllerId($name, $actionName);
317 22
        $this->container->setDefinition($controllerId, $definition);
318
319 22
        $action = $controllerId . ':' . SearchController::ACTION;
320 22
        $this->registerRoute(
321 22
            $mount,
322 22
            $name,
323 22
            $actionName,
324 22
            $path,
325 22
            $action,
326 22
            ['GET', 'POST'],
327 22
            ['class' => $class, 'arguments' => ['criteria', 'order', 'limit', 'offset']]
328 22
        );
329
330 22
        $definition = new Definition(CountController::class);
331 22
        $definition->setArguments(
332
            [
333 22
                $class,
334 22
                $repository,
335 22
                $criteriaConfigurator,
336 22
                $this->getEvm(),
337
            ]
338 22
        );
339
340 22
        $actionName   = 'count';
341 22
        $controllerId = $this->generateControllerId($name, $actionName);
342 22
        $this->container->setDefinition($controllerId, $definition);
343
344 22
        $action = $controllerId . ':' . CountController::ACTION;
345 22
        $this->registerRoute(
346 22
            $mount,
347 22
            $name,
348 22
            $actionName,
349 22
            $prefix . $count_path,
350 22
            $action,
351 22
            ['GET', 'POST'],
352 22
            ['class' => $class, 'arguments' => ['criteria']]
353 22
        );
354 22
    }
355
}
356