Completed
Push — standalone ( e42fd2...f309de )
by Philip
10:13
created

AnnotationDriver::methodToPropertyName()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6.7441

Importance

Changes 0
Metric Value
dl 0
loc 17
c 0
b 0
f 0
ccs 4
cts 9
cp 0.4444
rs 9.2
cc 4
eloc 9
nc 4
nop 1
crap 6.7441
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
    private $reader;
19
20
    /**
21
     * @var DriverInterface
22
     */
23
    private $doctrineDriver;
24
25 62
    public function __construct(Reader $reader, DriverInterface $doctrineDriver)
26
    {
27 62
        $this->reader = $reader;
28 62
        $this->doctrineDriver = $doctrineDriver;
29 62
    }
30
31
    /**
32
     * {@inheritdoc}
33
     */
34 56
    public function loadMetadataForClass(\ReflectionClass $class)
35
    {
36
        /** @var ClassMetadata $ddrRestClassMetadata */
37 56
        $ddrRestClassMetadata = $this->doctrineDriver->loadMetadataForClass($class);
38 56
        if (null === $ddrRestClassMetadata) {
39
            $ddrRestClassMetadata = new ClassMetadata($class->getName());
40
        }
41
42
        /** @var RootResource $restResourceAnnotation */
43 56
        $restResourceAnnotation = $this->reader->getClassAnnotation($class, RootResource::class);
44 56
        if (null !== $restResourceAnnotation) {
45
46 54
            $ddrRestClassMetadata->setRestResource(true);
47
48 54
            if (null !== $restResourceAnnotation->namePrefix) {
49
                $ddrRestClassMetadata->setNamePrefix($restResourceAnnotation->namePrefix);
50
            }
51
52 54
            if (null !== $restResourceAnnotation->pathPrefix) {
53 34
                $ddrRestClassMetadata->setPathPrefix($restResourceAnnotation->pathPrefix);
54
            }
55
56 54
            if (null !== $restResourceAnnotation->service) {
57
                $ddrRestClassMetadata->setService($restResourceAnnotation->service);
58
            }
59
60 54
            if (null !== $restResourceAnnotation->controller) {
61
                $ddrRestClassMetadata->setController($restResourceAnnotation->controller);
62
            }
63
64 54
            $ddrRestClassMetadata->idField = $restResourceAnnotation->idField;
65
66 54
            if (null !== $restResourceAnnotation->methods) {
67 54
                $methods = [];
68 54
                $methodAnnotations = $restResourceAnnotation->methods;
69 54
                foreach ($methodAnnotations as $methodAnnotation) {
70 54
                    $methods[$methodAnnotation->name] = $methodAnnotation;
71
                }
72 54
                $ddrRestClassMetadata->setMethods($methods);
73
            }
74
75 54
            if (null !== $restResourceAnnotation->methods) {
76 54
                $ddrRestClassMetadata->setMethods($restResourceAnnotation->methods);
0 ignored issues
show
Documentation introduced by
$restResourceAnnotation->methods is of type array<integer,object<Don...ata\Annotation\Method>>, but the function expects a array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
77
            }
78
        }
79
80 56
        foreach ($class->getProperties() as $reflectionProperty) {
81
82 56
            $propertyMetadata = $ddrRestClassMetadata->getPropertyMetadata($reflectionProperty->getName());
83 56
            if (null === $propertyMetadata) {
84 40
                $propertyMetadata = new PropertyMetadata($class->getName(), $reflectionProperty->getName());
85
            }
86
87 56
            $puttableAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, Puttable::class);
88 56
            if (null !== $puttableAnnotation) {
89 34
                $propertyMetadata->setPuttable(true);
90
            }
91
92 56
            $postableAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, Postable::class);
93 56
            if (null !== $postableAnnotation) {
94 34
                $propertyMetadata->setPostable(true);
95
            }
96
97 56
            $includableAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, Includable::class);
98 56
            if (null !== $includableAnnotation) {
99 54
                $this->parseIncludable($propertyMetadata, $includableAnnotation);
100
            }
101
102 56
            $excludedAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, Excluded::class);
103 56
            if (null !== $excludedAnnotation) {
104 54
                $propertyMetadata->setExcluded(true);
105
            }
106
107
            /** @var SubResource $subResourceAnnotation */
108 56
            $subResourceAnnotation = $this->reader->getPropertyAnnotation($reflectionProperty, SubResource::class);
109 56
            if (null !== $subResourceAnnotation) {
110
111 52
                $propertyMetadata->setSubResource(true);
112
113 52
                if (null !== $subResourceAnnotation->path) {
114
                    $propertyMetadata->setSubResourcePath($subResourceAnnotation->path);
115
                }
116
117 52
                if (null !== $subResourceAnnotation->methods) {
118 52
                    $methods = [];
119 52
                    $methodAnnotations = $subResourceAnnotation->methods;
120 52
                    foreach ($methodAnnotations as $methodAnnotation) {
121 52
                        $methods[$methodAnnotation->name] = $methodAnnotation;
122
                    }
123 52
                    $propertyMetadata->setMethods($methods);
124
                }
125
            }
126
127 56
            $ddrRestClassMetadata->addPropertyMetadata($propertyMetadata);
128
        }
129
130 56
        foreach ($class->getMethods() as $reflectionMethod) {
131 56
            $virtualAnnotation = $this->reader->getMethodAnnotation($reflectionMethod, Virtual::class);
132 56
            if (null !== $virtualAnnotation) {
133
134 22
                $name = $this->methodToPropertyName($reflectionMethod);
135
136 22
                $propertyMetadata = $ddrRestClassMetadata->getPropertyMetadata($name);
137 22
                if (null === $propertyMetadata) {
138 22
                    $propertyMetadata = new PropertyMetadata($class->getName(), $name);
139
                }
140 22
                $propertyMetadata->setVirtual(true);
141
142
                /** @var Includable|null $includableAnnotation */
143 22
                if (null !== $includableAnnotation = $this->reader->getMethodAnnotation(
144
                        $reflectionMethod,
145 22
                        Includable::class
146
                    )
147
                ) {
148 22
                    $this->parseIncludable($propertyMetadata, $includableAnnotation);
149
                }
150
151 56
                $ddrRestClassMetadata->addPropertyMetadata($propertyMetadata);
152
            }
153
        }
154
155 56
        return $ddrRestClassMetadata;
156
    }
157
158 22
    private function methodToPropertyName(\ReflectionMethod $reflectionMethod): string
159
    {
160 22
        $name = $reflectionMethod->getName();
1 ignored issue
show
Bug introduced by
Consider using $reflectionMethod->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
161 22
        if (0 === strpos($name, 'get')) {
162 22
            return lcfirst(substr($name, 3));
163
        }
164
165
        if (0 === strpos($name, 'is')) {
166
            return lcfirst(substr($name, 2));
167
        }
168
169
        if (0 === strpos($name, 'has')) {
170
            return lcfirst(substr($name, 3));
171
        }
172
173
        return $name;
174
    }
175
176 54
    public function parseIncludable(PropertyMetadata $propertyMetadata, Includable $includableAnnotation): void
177
    {
178 54
        $paths = $includableAnnotation->paths;
179 54
        if (null === $paths) {
180 52
            $paths = [$propertyMetadata->name];
181
        }
182 54
        $propertyMetadata->setIncludable(true);
183 54
        $propertyMetadata->setIncludablePaths($paths);
0 ignored issues
show
Documentation introduced by
$paths is of type array<integer,string>, but the function expects a null|array<integer,object<string>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
184 54
    }
185
}
186