Completed
Push — master ( cc21f4...3eeaf5 )
by Julien
06:41 queued 03:06
created

AnnotationDriver::getPropertyAnnotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 8
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Mapado\RestClientSdk\Mapping\Driver;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Annotations\AnnotationRegistry;
7
use Doctrine\Common\Annotations\FileCacheReader;
8
use Doctrine\Common\Annotations\Reader;
9
use Mapado\RestClientSdk\Exception\MappingException;
10
use Mapado\RestClientSdk\Mapping\Annotations;
11
use Mapado\RestClientSdk\Mapping\Attribute;
12
use Mapado\RestClientSdk\Mapping\ClassMetadata;
13
use Mapado\RestClientSdk\Mapping\Relation;
14
15
/**
16
 * Class AnnotationDriver
17
 *
18
 * @author Julien Deniau <[email protected]>
19
 */
20
class AnnotationDriver
21
{
22
    /**
23
     * cachePath
24
     *
25
     * @var string
26
     */
27
    private $cachePath;
28
29
    /**
30
     * debug
31
     *
32
     * @var bool
33
     */
34
    private $debug;
35
36
    /**
37
     * Constructor.
38
     *
39
     * @param string $cachePath
40
     * @param bool   $debug
41
     */
42
    public function __construct($cachePath, $debug = false)
43
    {
44 1
        $this->cachePath = $cachePath;
45 1
        $this->debug = $debug;
46
47 1
        AnnotationRegistry::registerFile(
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...egistry::registerFile() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

47
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerFile(

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
48 1
            __DIR__ . '/../Annotations/AllAnnotations.php'
49
        );
50 1
    }
51
52
    /**
53
     * loadDirectory
54
     *
55
     * @param string $path
56
     *
57
     * @return ClassMetadata[]
58
     *
59
     * @throws MappingException
60
     */
61
    public function loadDirectory($path)
62
    {
63 1
        if (!is_dir($path)) {
64
            throw new MappingException($path . ' is not a valid directory');
65
        }
66
67 1
        $iterator = new \RegexIterator(
68 1
            new \RecursiveIteratorIterator(
69 1
                new \RecursiveDirectoryIterator(
70 1
                    $path,
71 1
                    \FilesystemIterator::SKIP_DOTS
72
                ),
73 1
                \RecursiveIteratorIterator::LEAVES_ONLY
74
            ),
75 1
            '/^.+\.php$/i',
76 1
            \RecursiveRegexIterator::GET_MATCH
77
        );
78
79 1
        $classes = [];
80 1
        $includedFiles = [];
81
82 1
        foreach ($iterator as $file) {
83 1
            $sourceFile = $file[0];
84 1
            if (!preg_match('(^phar:)i', $sourceFile)) {
85 1
                $sourceFile = realpath($sourceFile);
86
            }
87
88 1
            require_once $sourceFile;
89 1
            $includedFiles[] = $sourceFile;
90
        }
91
92 1
        $declared = get_declared_classes();
93 1
        foreach ($declared as $className) {
94 1
            $rc = new \ReflectionClass($className);
95 1
            $sourceFile = $rc->getFileName();
96 1
            if (in_array($sourceFile, $includedFiles)) {
97 1
                $classes[] = $className;
98
            }
99
        }
100
101 1
        $mapping = [];
102 1
        foreach ($classes as $class) {
103 1
            $metadata = $this->getClassMetadataForClassname($class);
104 1
            if ($metadata) {
105 1
                $mapping[] = $metadata;
106
            }
107
        }
108
109 1
        return $mapping;
110
    }
111
112
    /**
113
     * loadClassname
114
     *
115
     * @param string $classname
116
     *
117
     * @return ClassMetadata[]
118
     */
119
    public function loadClassname($classname)
120
    {
121 1
        $metadata = $this->getClassMetadataForClassname($classname);
122
123 1
        return $metadata ? [$metadata] : [];
124
    }
125
126
    /**
127
     * getClassMetadataForClassname
128
     *
129
     * @param string $classname
130
     *
131
     * @return ClassMetadata|null
132
     */
133
    private function getClassMetadataForClassname($classname)
134
    {
135 1
        $reader = new FileCacheReader(
0 ignored issues
show
Deprecated Code introduced by
The class Doctrine\Common\Annotations\FileCacheReader has been deprecated: the FileCacheReader is deprecated and will be removed in version 2.0.0 of doctrine/annotations. Please use the {@see \Doctrine\Common\Annotations\CachedReader} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

135
        $reader = /** @scrutinizer ignore-deprecated */ new FileCacheReader(
Loading history...
136 1
            new AnnotationReader(),
137 1
            $this->cachePath,
138 1
            $this->debug
139
        );
140
141 1
        $reflClass = new \ReflectionClass($classname);
142
        /** @var Annotations\Entity|null */
143 1
        $classAnnotation = $reader->getClassAnnotation(
144 1
            $reflClass,
145 1
            Annotations\Entity::class
146
        );
147
148 1
        if (!$classAnnotation) {
149 1
            return null;
150
        }
151
152 1
        $attributeList = [];
153 1
        $relationList = [];
154 1
        foreach ($reflClass->getProperties() as $property) {
155
            // manage attributes
156
            /** @var Annotations\Attribute|null */
157 1
            $propertyAnnotation = $this->getPropertyAnnotation(
158 1
                $reader,
159 1
                $property,
160 1
                'Attribute'
161
            );
162
163 1
            if ($propertyAnnotation) {
164 1
                $isId = $this->getPropertyAnnotation($reader, $property, 'Id');
165
166 1
                $attributeList[] = new Attribute(
167 1
                    $propertyAnnotation->name,
168 1
                    $property->getName(),
169 1
                    $propertyAnnotation->type,
170 1
                    (bool) $isId
171
                );
172
            } else {
173
                // manage relations
174
                /** @var Annotations\OneToMany|null */
175 1
                $relation = $this->getPropertyAnnotation(
176 1
                    $reader,
177 1
                    $property,
178 1
                    'OneToMany'
179
                );
180 1
                if (!$relation) {
181
                    /** @var Annotations\ManyToOne|null */
182 1
                    $relation = $this->getPropertyAnnotation(
183 1
                        $reader,
184 1
                        $property,
185 1
                        'ManyToOne'
186
                    );
187
                }
188
189 1
                if ($relation) {
190 1
                    $attributeList[] = new Attribute(
191 1
                        $relation->name,
192 1
                        $property->getName()
193
                    );
194
195 1
                    $targetEntity = $relation->targetEntity;
196 1
                    if (false === strpos($targetEntity, '/')) {
197
                        $targetEntity =
198 1
                            substr(
199 1
                                $classname,
200 1
                                0,
201 1
                                strrpos($classname, '\\') + 1
202
                            ) .
203 1
                            $targetEntity;
204
                    }
205
206 1
                    $relationList[] = new Relation(
207 1
                        $relation->name,
208 1
                        $relation->type,
209 1
                        $targetEntity
210
                    );
211
                }
212
            }
213
        }
214
215 1
        $classMetadata = new ClassMetadata(
216 1
            $classAnnotation->key,
217 1
            $classname,
218 1
            $classAnnotation->repository
219
        );
220 1
        $classMetadata->setAttributeList($attributeList);
221 1
        $classMetadata->setRelationList($relationList);
222
223 1
        return $classMetadata;
224
    }
225
226
    /**
227
     * getPropertyAnnotation
228
     *
229
     * @param Reader              $reader
230
     * @param \ReflectionProperty $property
231
     * @param string              $classname
232
     *
233
     * @return object|null
234
     */
235
    private function getPropertyAnnotation(
236
        Reader $reader,
237
        \ReflectionProperty $property,
238
        $classname
239
    ) {
240 1
        return $reader->getPropertyAnnotation(
241 1
            $property,
242 1
            'Mapado\\RestClientSdk\\Mapping\\Annotations\\' . $classname
243
        );
244
    }
245
}
246