Completed
Pull Request — master (#15)
by Pavel
19:37
created

CrudsEntitiesConfigurator::generateControllerId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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