Completed
Push — standalone ( f8b7d4...64a47f )
by Philip
04:50
created

RestEntityLoader::findClass()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 11.0151

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 19
cts 20
cp 0.95
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 20
nc 11
nop 1
crap 11.0151

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