Completed
Push — master ( 07e238...0f15f1 )
by Pavel
09:14
created

processEntityConfiguration()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 45
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 6.0208

Importance

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