Passed
Push — master ( 685595...680e76 )
by Julien
01:32
created

AnnotationDriver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
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
            if ($metadata = $this->getClassMetadataForClassname($class)) {
104 1
                $mapping[] = $metadata;
105
            }
106
        }
107
108 1
        return $mapping;
109
    }
110
111
    /**
112
     * loadClassname
113
     *
114
     * @param string $classname
115
     *
116
     * @return ClassMetadata[]
117
     */
118
    public function loadClassname($classname)
119
    {
120 1
        $metadata = $this->getClassMetadataForClassname($classname);
121
122 1
        return $metadata ? [$metadata] : [];
123
    }
124
125
    /**
126
     * getClassMetadataForClassname
127
     *
128
     * @param string $classname
129
     *
130
     * @return ClassMetadata|null
131
     */
132
    private function getClassMetadataForClassname($classname)
133
    {
134 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

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