Completed
Push — master ( faed70...56c59d )
by Philip
13:07
created

AnnotationDriver   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 73.17%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 8
dl 0
loc 171
ccs 60
cts 82
cp 0.7317
rs 10
c 0
b 0
f 0

4 Methods

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