1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Mapado\RestClientSdk\Mapping\Driver; |
6
|
|
|
|
7
|
|
|
use Doctrine\Common\Annotations\AnnotationReader; |
8
|
|
|
use Doctrine\Common\Annotations\AnnotationRegistry; |
9
|
|
|
use Doctrine\Common\Annotations\FileCacheReader; |
10
|
|
|
use Doctrine\Common\Annotations\Reader; |
11
|
|
|
use Mapado\RestClientSdk\Exception\MappingException; |
12
|
|
|
use Mapado\RestClientSdk\Mapping\Annotations; |
13
|
|
|
use Mapado\RestClientSdk\Mapping\Attribute; |
14
|
|
|
use Mapado\RestClientSdk\Mapping\ClassMetadata; |
15
|
|
|
use Mapado\RestClientSdk\Mapping\Relation; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class AnnotationDriver |
19
|
|
|
* |
20
|
|
|
* @author Julien Deniau <[email protected]> |
21
|
|
|
*/ |
22
|
|
|
class AnnotationDriver |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @var string |
26
|
|
|
*/ |
27
|
|
|
private $cachePath; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var bool |
31
|
|
|
*/ |
32
|
|
|
private $debug; |
33
|
|
|
|
34
|
|
|
public function __construct(string $cachePath, bool $debug = false) |
35
|
|
|
{ |
36
|
1 |
|
$this->cachePath = $cachePath; |
37
|
1 |
|
$this->debug = $debug; |
38
|
|
|
|
39
|
1 |
|
AnnotationRegistry::registerFile( |
|
|
|
|
40
|
1 |
|
__DIR__ . '/../Annotations/AllAnnotations.php' |
41
|
|
|
); |
42
|
1 |
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @return array<ClassMetadata> |
46
|
|
|
* |
47
|
|
|
* @throws MappingException |
48
|
|
|
*/ |
49
|
|
|
public function loadDirectory(string $path): array |
50
|
|
|
{ |
51
|
1 |
|
if (!is_dir($path)) { |
52
|
|
|
throw new MappingException($path . ' is not a valid directory'); |
53
|
|
|
} |
54
|
|
|
|
55
|
1 |
|
$iterator = new \RegexIterator( |
56
|
1 |
|
new \RecursiveIteratorIterator( |
57
|
1 |
|
new \RecursiveDirectoryIterator( |
58
|
1 |
|
$path, |
59
|
1 |
|
\FilesystemIterator::SKIP_DOTS |
60
|
|
|
), |
61
|
1 |
|
\RecursiveIteratorIterator::LEAVES_ONLY |
62
|
|
|
), |
63
|
1 |
|
'/^.+\.php$/i', |
64
|
1 |
|
\RecursiveRegexIterator::GET_MATCH |
65
|
|
|
); |
66
|
|
|
|
67
|
1 |
|
$classes = []; |
68
|
1 |
|
$includedFiles = []; |
69
|
|
|
|
70
|
1 |
|
foreach ($iterator as $file) { |
71
|
1 |
|
$sourceFile = $file[0]; |
72
|
1 |
|
if (!preg_match('(^phar:)i', $sourceFile)) { |
73
|
1 |
|
$sourceFile = realpath($sourceFile); |
74
|
|
|
} |
75
|
|
|
|
76
|
1 |
|
require_once $sourceFile; |
77
|
1 |
|
$includedFiles[] = $sourceFile; |
78
|
|
|
} |
79
|
|
|
|
80
|
1 |
|
$declared = get_declared_classes(); |
81
|
1 |
|
foreach ($declared as $className) { |
82
|
1 |
|
$rc = new \ReflectionClass($className); |
83
|
1 |
|
$sourceFile = $rc->getFileName(); |
84
|
1 |
|
if (in_array($sourceFile, $includedFiles)) { |
85
|
1 |
|
$classes[] = $className; |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
1 |
|
$mapping = []; |
90
|
1 |
|
foreach ($classes as $class) { |
91
|
1 |
|
$metadata = $this->getClassMetadataForClassname($class); |
92
|
1 |
|
if ($metadata) { |
93
|
1 |
|
$mapping[] = $metadata; |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
97
|
1 |
|
return $mapping; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @param class-string $classname |
|
|
|
|
102
|
|
|
* |
103
|
|
|
* @return array<ClassMetadata> |
104
|
|
|
*/ |
105
|
|
|
public function loadClassname(string $classname): array |
106
|
|
|
{ |
107
|
1 |
|
$metadata = $this->getClassMetadataForClassname($classname); |
108
|
|
|
|
109
|
1 |
|
return $metadata ? [$metadata] : []; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @param class-string $classname |
|
|
|
|
114
|
|
|
* |
115
|
|
|
* @throws \ReflectionException |
116
|
|
|
*/ |
117
|
|
|
private function getClassMetadataForClassname( |
118
|
|
|
string $classname |
119
|
|
|
): ?ClassMetadata { |
120
|
1 |
|
$reader = new FileCacheReader( |
|
|
|
|
121
|
1 |
|
new AnnotationReader(), |
122
|
1 |
|
$this->cachePath, |
123
|
1 |
|
$this->debug |
124
|
|
|
); |
125
|
|
|
|
126
|
1 |
|
$reflClass = new \ReflectionClass($classname); |
127
|
|
|
/** @var Annotations\Entity|null */ |
128
|
1 |
|
$classAnnotation = $reader->getClassAnnotation( |
129
|
1 |
|
$reflClass, |
130
|
1 |
|
Annotations\Entity::class |
131
|
|
|
); |
132
|
|
|
|
133
|
1 |
|
if (!$classAnnotation) { |
134
|
1 |
|
return null; |
135
|
|
|
} |
136
|
|
|
|
137
|
1 |
|
$attributeList = []; |
138
|
1 |
|
$relationList = []; |
139
|
1 |
|
foreach ($reflClass->getProperties() as $property) { |
140
|
|
|
// manage attributes |
141
|
|
|
/** @var Annotations\Attribute|null */ |
142
|
1 |
|
$propertyAnnotation = $this->getPropertyAnnotation( |
143
|
1 |
|
$reader, |
144
|
|
|
$property, |
145
|
1 |
|
'Attribute' |
146
|
|
|
); |
147
|
|
|
|
148
|
1 |
|
if ($propertyAnnotation) { |
149
|
1 |
|
$isId = $this->getPropertyAnnotation($reader, $property, 'Id'); |
150
|
|
|
|
151
|
1 |
|
$attributeList[] = new Attribute( |
152
|
1 |
|
$propertyAnnotation->name, |
153
|
1 |
|
$property->getName(), |
154
|
1 |
|
$propertyAnnotation->type, |
155
|
1 |
|
(bool) $isId |
156
|
|
|
); |
157
|
|
|
} else { |
158
|
|
|
// manage relations |
159
|
|
|
/** @var Annotations\OneToMany|null */ |
160
|
1 |
|
$relation = $this->getPropertyAnnotation( |
161
|
1 |
|
$reader, |
162
|
|
|
$property, |
163
|
1 |
|
'OneToMany' |
164
|
|
|
); |
165
|
1 |
|
if (!$relation) { |
166
|
|
|
/** @var Annotations\ManyToOne|null */ |
167
|
1 |
|
$relation = $this->getPropertyAnnotation( |
168
|
1 |
|
$reader, |
169
|
|
|
$property, |
170
|
1 |
|
'ManyToOne' |
171
|
|
|
); |
172
|
|
|
} |
173
|
|
|
|
174
|
1 |
|
if ($relation) { |
175
|
1 |
|
$attributeList[] = new Attribute( |
176
|
1 |
|
$relation->name, |
177
|
1 |
|
$property->getName() |
178
|
|
|
); |
179
|
|
|
|
180
|
1 |
|
$targetEntity = $relation->targetEntity; |
181
|
1 |
|
if (false === mb_strpos($targetEntity, '/')) { |
182
|
|
|
$targetEntity = |
183
|
1 |
|
mb_substr( |
184
|
1 |
|
$classname, |
185
|
1 |
|
0, |
186
|
1 |
|
mb_strrpos($classname, '\\') + 1 |
187
|
1 |
|
) . $targetEntity; |
188
|
|
|
} |
189
|
|
|
|
190
|
1 |
|
$relationList[] = new Relation( |
191
|
1 |
|
$relation->name, |
192
|
1 |
|
$relation->type, |
193
|
|
|
$targetEntity |
194
|
|
|
); |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
} |
198
|
|
|
|
199
|
1 |
|
$classMetadata = new ClassMetadata( |
200
|
1 |
|
$classAnnotation->key, |
201
|
|
|
$classname, |
202
|
1 |
|
$classAnnotation->repository |
203
|
|
|
); |
204
|
1 |
|
$classMetadata->setAttributeList($attributeList); |
205
|
1 |
|
$classMetadata->setRelationList($relationList); |
206
|
|
|
|
207
|
1 |
|
return $classMetadata; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @return object|null the Annotation or NULL, if the requested annotation does not exist |
212
|
|
|
*/ |
213
|
|
|
private function getPropertyAnnotation( |
214
|
|
|
Reader $reader, |
215
|
|
|
\ReflectionProperty $property, |
216
|
|
|
string $classname |
217
|
|
|
): ?object { |
218
|
|
|
/** @var class-string $classname */ |
219
|
|
|
$classname = |
220
|
1 |
|
'Mapado\\RestClientSdk\\Mapping\\Annotations\\' . $classname; |
221
|
|
|
|
222
|
1 |
|
return $reader->getPropertyAnnotation($property, $classname); |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
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.