Completed
Push — master ( d6cf83...a2ccb4 )
by Philip
13:40
created

AnnotationDriver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
namespace Dontdrinkandroot\RestBundle\Metadata\Driver;
3
4
use Doctrine\Common\Annotations\Reader;
5
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Excluded;
6
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Includable;
7
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Postable;
8
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Puttable;
9
use Dontdrinkandroot\RestBundle\Metadata\Annotation\RootResource;
10
use Dontdrinkandroot\RestBundle\Metadata\Annotation\SubResource;
11
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Virtual;
12
use Dontdrinkandroot\RestBundle\Metadata\ClassMetadata;
13
use Dontdrinkandroot\RestBundle\Metadata\PropertyMetadata;
14
use Metadata\Driver\DriverInterface;
15
16
class AnnotationDriver implements DriverInterface
17
{
18
    /**
19
     * @var Reader
20
     */
21
    private $reader;
22
23
    /**
24
     * @var DriverInterface
25
     */
26
    private $doctrineDriver;
27
28 88
    public function __construct(Reader $reader, DriverInterface $doctrineDriver)
29
    {
30 88
        $this->reader = $reader;
31 88
        $this->doctrineDriver = $doctrineDriver;
32 88
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37 66
    public function loadMetadataForClass(\ReflectionClass $class)
38
    {
39
        /** @var ClassMetadata $ddrRestClassMetadata */
40 66
        $ddrRestClassMetadata = $this->doctrineDriver->loadMetadataForClass($class);
41 66
        if (null === $ddrRestClassMetadata) {
42
            $ddrRestClassMetadata = new ClassMetadata($class->getName());
43
        }
44
45
        /** @var RootResource $restResourceAnnotation */
46 66
        $restResourceAnnotation = $this->reader->getClassAnnotation($class, RootResource::class);
47 66
        if (null !== $restResourceAnnotation) {
48
49 64
            $ddrRestClassMetadata->setRestResource(true);
50
51 64
            if (null !== $restResourceAnnotation->namePrefix) {
52
                $ddrRestClassMetadata->setNamePrefix($restResourceAnnotation->namePrefix);
53
            }
54
55 64
            if (null !== $restResourceAnnotation->pathPrefix) {
56 42
                $ddrRestClassMetadata->setPathPrefix($restResourceAnnotation->pathPrefix);
57
            }
58
59 64
            if (null !== $restResourceAnnotation->service) {
60
                $ddrRestClassMetadata->setService($restResourceAnnotation->service);
61
            }
62
63 64
            if (null !== $restResourceAnnotation->controller) {
64
                $ddrRestClassMetadata->setController($restResourceAnnotation->controller);
65
            }
66
67 64
            $ddrRestClassMetadata->idField = $restResourceAnnotation->idField;
68
69 64
            if (null !== $restResourceAnnotation->methods) {
70 64
                $methods = [];
71 64
                $methodAnnotations = $restResourceAnnotation->methods;
72 64
                foreach ($methodAnnotations as $methodAnnotation) {
73 64
                    $methods[$methodAnnotation->name] = $methodAnnotation;
74
                }
75 64
                $ddrRestClassMetadata->setMethods($methods);
76
            }
77
78 64
            if (null !== $restResourceAnnotation->methods) {
79 64
                $ddrRestClassMetadata->setMethods($restResourceAnnotation->methods);
80
            }
81
        }
82
83 66
        foreach ($class->getProperties() as $reflectionProperty) {
84
85 66
            $propertyMetadata = $ddrRestClassMetadata->getPropertyMetadata($reflectionProperty->getName());
86 66
            if (null === $propertyMetadata) {
87 46
                $propertyMetadata = new PropertyMetadata($class->getName(), $reflectionProperty->getName());
88
            }
89
90
            /** @var Puttable $puttable */
91 66
            if (null !== $puttable = $this->reader->getPropertyAnnotation($reflectionProperty, Puttable::class)) {
92 52
                $propertyMetadata->setPuttable($puttable);
93
            }
94
95
            /** @var Postable $postable */
96 66
            if (null !== $postable = $this->reader->getPropertyAnnotation($reflectionProperty, Postable::class)) {
97 52
                $propertyMetadata->setPostable($postable);
98
            }
99
100
            /** @var Includable $includable */
101 66
            $includable = $this->reader->getPropertyAnnotation($reflectionProperty, Includable::class);
102 66
            if (null !== $includable) {
103 54
                $this->parseIncludable($propertyMetadata, $includable);
104
            }
105
106 66
            $excluded = $this->reader->getPropertyAnnotation($reflectionProperty, Excluded::class);
107 66
            if (null !== $excluded) {
108 46
                $propertyMetadata->setExcluded(true);
109
            }
110
111
            /** @var SubResource $subResourceAnnotation */
112 66
            $subResourceAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, SubResource::class);
113 66
            if (null !== $subResourceAnnotation) {
114
115 50
                $propertyMetadata->setSubResource(true);
116
117 50
                if (null !== $subResourceAnnotation->path) {
118
                    $propertyMetadata->setSubResourcePath($subResourceAnnotation->path);
119
                }
120
121 50
                if (null !== $subResourceAnnotation->methods) {
122 50
                    $methods = [];
123 50
                    $methodAnnotations = $subResourceAnnotation->methods;
124 50
                    foreach ($methodAnnotations as $methodAnnotation) {
125 50
                        $methods[$methodAnnotation->name] = $methodAnnotation;
126
                    }
127 50
                    $propertyMetadata->setMethods($methods);
128
                }
129
            }
130
131 66
            $ddrRestClassMetadata->addPropertyMetadata($propertyMetadata);
132
        }
133
134 66
        foreach ($class->getMethods() as $reflectionMethod) {
135
            /** @var Virtual $virtualAnnotation */
136 66
            $virtualAnnotation = $this->reader->getMethodAnnotation($reflectionMethod, Virtual::class);
137 66
            if (null !== $virtualAnnotation) {
138
139
                $name = $this->methodToPropertyName($reflectionMethod);
140
141
                $propertyMetadata = $ddrRestClassMetadata->getPropertyMetadata($name);
142
                if (null === $propertyMetadata) {
143
                    $propertyMetadata = new PropertyMetadata($class->getName(), $name);
144
                }
145
                $propertyMetadata->setVirtual(true);
146
147
                /** @var Includable|null $includableAnnotation */
148
                if (null !== $includable = $this->reader->getMethodAnnotation(
149
                        $reflectionMethod,
150
                        Includable::class
151
                    )
152
                ) {
153
                    $this->parseIncludable($propertyMetadata, $includable);
154
                }
155
156
                $ddrRestClassMetadata->addPropertyMetadata($propertyMetadata);
157
            }
158
        }
159
160 66
        return $ddrRestClassMetadata;
161
    }
162
163
    private function methodToPropertyName(\ReflectionMethod $reflectionMethod): string
164
    {
165
        $name = $reflectionMethod->getName();
166
        if (0 === strpos($name, 'get')) {
167
            return lcfirst(substr($name, 3));
168
        }
169
170
        if (0 === strpos($name, 'is')) {
171
            return lcfirst(substr($name, 2));
172
        }
173
174
        if (0 === strpos($name, 'has')) {
175
            return lcfirst(substr($name, 3));
176
        }
177
178
        return $name;
179
    }
180
181 54
    public function parseIncludable(PropertyMetadata $propertyMetadata, Includable $includableAnnotation): void
182
    {
183 54
        $paths = $includableAnnotation->paths;
184 54
        if (null === $paths) {
185 50
            $paths = [$propertyMetadata->name];
186
        }
187 54
        $propertyMetadata->setIncludable(true);
188 54
        $propertyMetadata->setIncludablePaths($paths);
189 54
    }
190
}
191