Passed
Pull Request — master (#21)
by Pavel
06:33
created

processEntityConfiguration()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 55
Code Lines 41

Duplication

Lines 16
Ratio 29.09 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 16
loc 55
ccs 0
cts 49
cp 0
rs 7.8235
c 0
b 0
f 0
cc 7
eloc 41
nc 20
nop 2
crap 56

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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