Completed
Push — master ( 1b3a7e...f4d44d )
by Pavel
04:33
created

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