Completed
Push — master ( 839f22...1b3a7e )
by Pavel
04:14
created

CrudsEntitiesConfigurator::getLoaderDefinition()   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($mount, $name, $actionName, $path, $action, ['POST'], ['class' => $class]);
110 2
    }
111
112 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...
113
    {
114 2
        $definition = new Definition(ReadController::class);
115 2
        $definition->setArguments(
116
            [
117 2
                $repository,
118 2
                $this->getEvm(),
119
            ]
120 2
        );
121
122 2
        $actionName   = 'read';
123 2
        $controllerId = $this->generateControllerId($name, $actionName);
124 2
        $this->container->setDefinition($controllerId, $definition);
125
126 2
        $action = $controllerId.':'.ReadController::ACTION;
127 2
        $this->registerRoute($mount, $name, $actionName, $path, $action, ['GET', 'POST'], ['class' => $class]);
128 2
    }
129
130 2
    public function registerUpdateAction($mount, $name, $path, $repository, $processor, $manager, $class)
131
    {
132 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...
133 2
            $processor = new Reference('cruds.processor.property_access');
134 2
        } else {
135
            $processor = new Reference($this->filterReference($processor));
136
        }
137
138 2
        $definition = new Definition(UpdateController::class);
139 2
        $definition->setArguments(
140
            [
141 2
                $repository,
142 2
                $processor,
143 2
                $manager,
144 2
                $this->getEvm(),
145
            ]
146 2
        );
147
148 2
        $actionName   = 'update';
149 2
        $controllerId = $this->generateControllerId($name, $actionName);
150 2
        $this->container->setDefinition($controllerId, $definition);
151
152 2
        $action = $controllerId.':'.UpdateController::ACTION;
153 2
        $this->registerRoute($mount, $name, $actionName, $path, $action, ['POST'], ['class' => $class]);
154 2
    }
155
156 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...
157
    {
158 2
        $definition = new Definition(DeleteController::class);
159 2
        $definition->setArguments(
160
            [
161 2
                $repository,
162 2
                $manager,
163 2
                $this->getEvm(),
164
            ]
165 2
        );
166
167 2
        $actionName   = 'delete';
168 2
        $controllerId = $controllerId = $this->generateControllerId($name, $actionName);
169 2
        $this->container->setDefinition($controllerId, $definition);
170
171 2
        $action = $controllerId.':'.DeleteController::ACTION;
172 2
        $this->registerRoute($mount, $name, $actionName, $path, $action, ['POST'], ['class' => $class]);
173 2
    }
174
175 2
    public function registerSearchAction($mount, $name, $path, $class, $repository, $criteria)
176
    {
177
178 2
        if (is_array($criteria)) {
179
            $filterArray = [];
180
            foreach ($criteria as $filter => $reference) {
181
                $filterArray[$filter] = new Reference($this->filterReference($reference));
182
            }
183
            $criteriaConfigurator = new Definition(NestedCriteriaConfigurator::class);
184
            $criteriaConfigurator->setArguments([$filterArray]);
185
        } else {
186 2
            $criteriaConfigurator = new Reference($this->filterReference($criteria));
187
        }
188
189 2
        $definition = new Definition(SearchController::class);
190 2
        $definition->setArguments(
191
            [
192 2
                $class,
193 2
                $repository,
194 2
                $criteriaConfigurator,
195 2
                $this->getEvm(),
196
            ]
197 2
        );
198
199 2
        $actionName   = 'search';
200 2
        $controllerId = $this->generateControllerId($name, $actionName);
201 2
        $this->container->setDefinition($controllerId, $definition);
202
203 2
        $action = $controllerId.':'.SearchController::ACTION;
204 2
        $this->registerRoute($mount, $name, $actionName, $path, $action, ['GET', 'POST'], ['class' => $class]);
205 2
    }
206
207 2
    private function getLoaderDefinition()
208
    {
209 2
        return $this->container->getDefinition('cruds.api.router_loader');
210
    }
211
212
    /**
213
     * @param string $name
214
     *
215
     * @return string
216
     */
217 2
    private function normalize($name)
218
    {
219 2
        return str_replace('-', '_', $name);
220
    }
221
222
    /**
223
     * @param string $reference
224
     *
225
     * @return string
226
     */
227 2
    private function filterReference($reference)
228
    {
229 2
        return ltrim($reference, '@');
230
    }
231
232
    /**
233
     * @param string $mount
234
     * @param string $name
235
     * @param string $actionName
236
     * @param string $path
237
     * @param string $action
238
     * @param array  $methods
239
     * @param array  $options
240
     *
241
     * @return Definition
242
     * @throws \InvalidArgumentException
243
     */
244 2
    private function registerRoute($mount, $name, $actionName, $path, $action, array $methods, array $options = [])
245
    {
246 2
        return $this->getLoaderDefinition()->addMethodCall(
247 2
            'addRoute',
248
            [
249 2
                $mount,
250 2
                $this->normalize('cruds.routing.'.$name.'.'.$actionName),
251 2
                $path,
252 2
                $action,
253 2
                $methods,
254 2
                array_replace(
255
                    [
256 2
                        'action' => $actionName,
257 2
                        'mount'  => $mount,
258 2
                    ],
259
                    $options
260 2
                ),
261
            ]
262 2
        );
263
    }
264
265
    /**
266
     * @param string $name
267
     * @param string $actionName
268
     *
269
     * @return string
270
     */
271 2
    private function generateControllerId($name, $actionName)
272
    {
273 2
        return $this->normalize('cruds.generated_controller.'.$name.'.'.$actionName);
274
    }
275
276
    /**
277
     * @return Reference
278
     */
279 2
    private function getEvm()
280
    {
281 2
        return new Reference('event_dispatcher');
282
    }
283
}
284