RestResourceLoader::load()   F
last analyzed

Complexity

Conditions 19
Paths 3206

Size

Total Lines 195

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 114
CRAP Score 19.0018

Importance

Changes 0
Metric Value
dl 0
loc 195
ccs 114
cts 116
cp 0.9828
rs 0.2799
c 0
b 0
f 0
cc 19
nc 3206
nop 2
crap 19.0018

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Routing;
4
5
use Dontdrinkandroot\RestBundle\Controller\DoctrineRestResourceController;
6
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Method;
7
use Dontdrinkandroot\RestBundle\Metadata\ClassMetadata;
8
use Dontdrinkandroot\RestBundle\Metadata\PropertyMetadata;
9
use Metadata\MetadataFactoryInterface;
10
use Symfony\Component\Config\FileLocatorInterface;
11
use Symfony\Component\Config\Loader\Loader;
12
use Symfony\Component\Finder\Finder;
13
use Symfony\Component\Finder\SplFileInfo;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\Routing\Route;
16
use Symfony\Component\Routing\RouteCollection;
17
18
/**
19
 * @author Philip Washington Sorst <[email protected]>
20
 */
21
class RestResourceLoader extends Loader
22
{
23
    /**
24
     * @var FileLocatorInterface
25
     */
26
    private $fileLocator;
27
28
    /**
29
     * @var MetadataFactoryInterface
30
     */
31
    private $metadataFactory;
32
33 12
    public function __construct(
34
        FileLocatorInterface $fileLocator,
35
        MetadataFactoryInterface $metadataFactory
36
    ) {
37 12
        $this->fileLocator = $fileLocator;
38 12
        $this->metadataFactory = $metadataFactory;
39 12
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 12
    public function load($resource, $type = null)
45
    {
46 12
        $locatedResource = $this->fileLocator->locate($resource);
47 12
        $files = [];
48 12
        if (is_dir($locatedResource)) {
49 10
            $finder = new Finder();
50 10
            foreach ($finder->in($locatedResource)->name('*.php')->files() as $file) {
51
                /** @var SplFileInfo $file */
52 10
                $files[] = $file->getRealPath();
53
            }
54
        } else {
55 2
            $files[] = $locatedResource;
56
        }
57
58 12
        $routes = new RouteCollection();
59
60 12
        foreach ($files as $file) {
61 12
            $class = $this->findClass($file);
62 12
            if (false === $class) {
63
                throw new \Exception(sprintf('Couldn\'t find class for %s', $file));
64
            }
65
            /** @var ClassMetadata $classMetadata */
66 12
            $classMetadata = $this->metadataFactory->getMetadataForClass($class);
67 12
            if ($classMetadata->isRestResource()) {
68
69 12
                $namePrefix = $classMetadata->getNamePrefix();
70 12
                $pathPrefix = $classMetadata->getPathPrefix();
71 12
                $controller = $this->getController($classMetadata);
72
73
                $defaults = [
74 12
                    '_entityClass' => $class,
75 12
                    '_format'      => 'json'
76
                ];
77
78 12
                if (null !== $method = $classMetadata->getMethod(Method::LIST)) {
79 12
                    $listRoute = new Route($pathPrefix);
80 12
                    $listRoute->setMethods(Request::METHOD_GET);
81 12
                    $listRoute->setDefaults(
82 12
                        array_merge(
83 12
                            $defaults,
84
                            [
85 12
                                '_controller'      => $controller . ':listAction',
86 12
                                '_defaultincludes' => $method->defaultIncludes
87
                            ]
88
                        )
89
                    );
90 12
                    $routes->add($namePrefix . '.list', $listRoute);
91
                }
92
93 12
                if (null !== $method = $classMetadata->getMethod(Method::POST)) {
94 10
                    $postRoute = new Route($pathPrefix);
95 10
                    $postRoute->setMethods(Request::METHOD_POST);
96 10
                    $postRoute->setDefaults(
97 10
                        array_merge(
98 10
                            $defaults,
99
                            [
100 10
                                '_controller'      => $controller . ':postAction',
101 10
                                '_defaultincludes' => $method->defaultIncludes
102
                            ]
103
                        )
104
                    );
105 10
                    $routes->add($namePrefix . '.post', $postRoute);
106
                }
107
108 12
                if (null !== $method = $classMetadata->getMethod(Method::GET)) {
109 12
                    $getRoute = new Route($pathPrefix . '/{id}');
110 12
                    $getRoute->setMethods(Request::METHOD_GET);
111 12
                    $getRoute->setDefaults(
112 12
                        array_merge(
113 12
                            $defaults,
114
                            [
115 12
                                '_controller'      => $controller . ':getAction',
116 12
                                '_defaultincludes' => $method->defaultIncludes
117
                            ]
118
                        )
119
                    );
120 12
                    $routes->add($namePrefix . '.get', $getRoute);
121
                }
122
123 12
                if (null !== $method = $classMetadata->getMethod(Method::PUT)) {
124 10
                    $putRoute = new Route($pathPrefix . '/{id}');
125 10
                    $putRoute->setMethods([Request::METHOD_PUT, Request::METHOD_PATCH]);
126 10
                    $putRoute->setDefaults(
127 10
                        array_merge(
128 10
                            $defaults,
129
                            [
130 10
                                '_controller'      => $controller . ':putAction',
131 10
                                '_defaultincludes' => $method->defaultIncludes
132
                            ]
133
                        )
134
                    );
135 10
                    $routes->add($namePrefix . '.put', $putRoute);
136
                }
137
138 12
                if (null !== $method = $classMetadata->getMethod(Method::DELETE)) {
139 10
                    $deleteRoute = new Route($pathPrefix . '/{id}');
140 10
                    $deleteRoute->setMethods(Request::METHOD_DELETE);
141 10
                    $deleteRoute->setDefaults(
142 10
                        array_merge(
143 10
                            $defaults,
144
                            [
145 10
                                '_controller'      => $controller . ':deleteAction',
146 10
                                '_defaultincludes' => $method->defaultIncludes
147
                            ]
148
                        )
149
                    );
150 10
                    $routes->add($namePrefix . '.delete', $deleteRoute);
151
                }
152
153
                /** @var PropertyMetadata $propertyMetadata */
154 12
                foreach ($classMetadata->propertyMetadata as $propertyMetadata) {
155 12
                    if ($propertyMetadata->isSubResource()) {
156
157 10
                        $subResourcePath = strtolower($propertyMetadata->name);
158 10
                        if (null !== $propertyMetadata->getSubResourcePath()) {
159
                            $subResourcePath = $propertyMetadata->getSubResourcePath();
160
                        }
161
162 10
                        if (null !== $method = $propertyMetadata->getMethod(Method::LIST)) {
163 10
                            $subResourceFullPath = $pathPrefix . '/{id}/' . $subResourcePath;
164 10
                            $subResourceRoute = new Route($subResourceFullPath);
165 10
                            $subResourceRoute->setMethods(Request::METHOD_GET);
166 10
                            $subResourceRoute->setDefaults(
167 10
                                array_merge(
168 10
                                    $defaults,
169
                                    [
170 10
                                        '_controller'      => $controller . ':listSubresourceAction',
171 10
                                        'subresource'      => $propertyMetadata->name,
172 10
                                        '_defaultincludes' => $method->defaultIncludes
173
                                    ]
174
                                )
175
                            );
176 10
                            $routes->add($namePrefix . '.' . $propertyMetadata->name . '.list', $subResourceRoute);
177
                        }
178
179 10
                        if (null !== $method = $propertyMetadata->getMethod(Method::POST)) {
180 10
                            $subResourceFullPath = $pathPrefix . '/{id}/' . $subResourcePath;
181 10
                            $subResourceRoute = new Route($subResourceFullPath);
182 10
                            $subResourceRoute->setMethods(Request::METHOD_POST);
183 10
                            $subResourceRoute->setDefaults(
184 10
                                array_merge(
185 10
                                    $defaults,
186
                                    [
187 10
                                        '_controller'      => $controller . ':postSubresourceAction',
188 10
                                        'subresource'      => $propertyMetadata->name,
189 10
                                        '_defaultincludes' => $method->defaultIncludes
190
                                    ]
191
                                )
192
                            );
193 10
                            $routes->add($namePrefix . '.' . $propertyMetadata->name . '.post', $subResourceRoute);
194
                        }
195
196 10
                        if (null !== $method = $propertyMetadata->getMethod(Method::PUT)) {
197 10
                            $subResourceFullPath = $pathPrefix . '/{id}/' . $subResourcePath . '/{subId}';
198 10
                            $subResourceRoute = new Route($subResourceFullPath);
199 10
                            $subResourceRoute->setMethods(Request::METHOD_PUT);
200 10
                            $subResourceRoute->setDefaults(
201 10
                                array_merge(
202 10
                                    $defaults,
203
                                    [
204 10
                                        '_controller'      => $controller . ':putSubresourceAction',
205 10
                                        'subresource'      => $propertyMetadata->name,
206 10
                                        '_defaultincludes' => $method->defaultIncludes
207
                                    ]
208
                                )
209
                            );
210 10
                            $routes->add($namePrefix . '.' . $propertyMetadata->name . '.put', $subResourceRoute);
211
                        }
212
213 10
                        if (null !== $method = $propertyMetadata->getMethod(Method::DELETE)) {
214 10
                            if ($propertyMetadata->isCollection()) {
215 10
                                $subResourceFullPath = $pathPrefix . '/{id}/' . $subResourcePath . '/{subId}';
216
                            } else {
217 10
                                $subResourceFullPath = $pathPrefix . '/{id}/' . $subResourcePath;
218
                            }
219 10
                            $subResourceRoute = new Route($subResourceFullPath);
220 10
                            $subResourceRoute->setMethods(Request::METHOD_DELETE);
221 10
                            $subResourceRoute->setDefaults(
222 10
                                array_merge(
223 10
                                    $defaults,
224
                                    [
225 10
                                        '_controller' => $controller . ':deleteSubresourceAction',
226 10
                                        'subresource' => $propertyMetadata->name,
227
                                    ]
228
                                )
229
                            );
230 12
                            $routes->add($namePrefix . '.' . $propertyMetadata->name . '.delete', $subResourceRoute);
231
                        }
232
                    }
233
                }
234
            }
235
        }
236
237 12
        return $routes;
238
    }
239
240
    /**
241
     * Taken from {@see AnnotationFileLoader}
242
     * TODO: Evaluate if there is a library method or extract.
243
     *
244
     * @param $file
245
     *
246
     * @return bool|string
247
     */
248 12
    protected function findClass($file)
249
    {
250 12
        $class = false;
251 12
        $namespace = false;
252 12
        $tokens = token_get_all(file_get_contents($file));
253 12
        for ($i = 0; isset($tokens[$i]); ++$i) {
254 12
            $token = $tokens[$i];
255
256 12
            if (!isset($token[1])) {
257 12
                continue;
258
            }
259
260 12
            if (true === $class && T_STRING === $token[0]) {
261 12
                return $namespace . '\\' . $token[1];
262
            }
263
264 12
            if (true === $namespace && T_STRING === $token[0]) {
265 12
                $namespace = $token[1];
266 12
                while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) {
267 12
                    $namespace .= $tokens[$i][1];
268
                }
269 12
                $token = $tokens[$i];
270
            }
271
272 12
            if (T_CLASS === $token[0]) {
273 12
                $class = true;
274
            }
275
276 12
            if (T_NAMESPACE === $token[0]) {
277 12
                $namespace = true;
278
            }
279
        }
280
281
        return false;
282
    }
283
284
    /**
285
     * {@inheritdoc}
286
     */
287 12
    public function supports($resource, $type = null)
288
    {
289 12
        return 'ddr_rest' === $type;
290
    }
291
292
    /**
293
     * @param ClassMetadata $classMetadata
294
     *
295
     * @return string
296
     */
297 12
    protected function getController(ClassMetadata $classMetadata)
298
    {
299 12
        $controller = DoctrineRestResourceController::class;
300 12
        if (null !== $classMetadata->getController()) {
301
            $controller = $classMetadata->getController();
302
        }
303
304 12
        if (strpos($controller, ':') !== false) {
305
            throw new \RuntimeException(sprintf('Short controller notation is not permitted for "%s"', $controller));
306
        }
307
308 12
        if (strpos($controller, '\\') !== false) {
309 12
            $controller .= ':';
310
        }
311
312 12
        return $controller;
313
    }
314
}
315