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