Completed
Push — standalone ( 46923f...8c7d4e )
by Philip
03:55
created

RestResourceLoader::load()   F

Complexity

Conditions 20
Paths 6406

Size

Total Lines 184
Code Lines 116

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 93
CRAP Score 20.0036

Importance

Changes 0
Metric Value
dl 0
loc 184
ccs 93
cts 95
cp 0.9789
rs 2
c 0
b 0
f 0
cc 20
eloc 116
nc 6406
nop 2
crap 20.0036

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