This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the ONGR package. |
||
5 | * |
||
6 | * (c) NFQ Technologies UAB <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace ONGR\ElasticsearchBundle\Mapping; |
||
13 | |||
14 | use Doctrine\Common\Annotations\AnnotationRegistry; |
||
15 | use Doctrine\Common\Annotations\Reader; |
||
16 | use Doctrine\Common\Cache\Cache; |
||
17 | use ONGR\ElasticsearchBundle\Annotation\AbstractAnnotation; |
||
18 | use ONGR\ElasticsearchBundle\Annotation\Embedded; |
||
19 | use ONGR\ElasticsearchBundle\Annotation\Id; |
||
20 | use ONGR\ElasticsearchBundle\Annotation\Index; |
||
21 | use ONGR\ElasticsearchBundle\Annotation\NestedType; |
||
22 | use ONGR\ElasticsearchBundle\Annotation\ObjectType; |
||
23 | use ONGR\ElasticsearchBundle\Annotation\PropertiesAwareInterface; |
||
24 | use ONGR\ElasticsearchBundle\Annotation\Property; |
||
25 | use ONGR\ElasticsearchBundle\DependencyInjection\Configuration; |
||
26 | |||
27 | /** |
||
28 | * Document parser used for reading document annotations. |
||
29 | */ |
||
30 | class DocumentParser |
||
31 | { |
||
32 | const OBJ_CACHED_FIELDS = 'ongr.obj_fields'; |
||
33 | const EMBEDDED_CACHED_FIELDS = 'ongr.embedded_fields'; |
||
34 | const ARRAY_CACHED_FIELDS = 'ongr.array_fields'; |
||
35 | |||
36 | private $reader; |
||
37 | private $properties = []; |
||
38 | private $analysisConfig = []; |
||
39 | private $cache; |
||
40 | |||
41 | public function __construct(Reader $reader, Cache $cache, array $analysisConfig = []) |
||
42 | { |
||
43 | $this->reader = $reader; |
||
44 | $this->cache = $cache; |
||
45 | $this->analysisConfig = $analysisConfig; |
||
46 | |||
47 | #Fix for annotations loader until doctrine/annotations 2.0 will be released with the full autoload support. |
||
48 | AnnotationRegistry::registerLoader('class_exists'); |
||
0 ignored issues
–
show
|
|||
49 | } |
||
50 | |||
51 | public function getIndexAliasName(\ReflectionClass $class): string |
||
52 | { |
||
53 | /** @var Index $document */ |
||
54 | $document = $this->reader->getClassAnnotation($class, Index::class); |
||
55 | |||
56 | return $document->alias ?? Caser::snake($class->getShortName()); |
||
57 | } |
||
58 | |||
59 | public function isDefaultIndex(\ReflectionClass $class): bool |
||
60 | { |
||
61 | /** @var Index $document */ |
||
62 | $document = $this->reader->getClassAnnotation($class, Index::class); |
||
63 | |||
64 | return $document->default; |
||
65 | } |
||
66 | |||
67 | public function getIndexAnnotation(\ReflectionClass $class) |
||
68 | { |
||
69 | /** @var Index $document */ |
||
70 | $document = $this->reader->getClassAnnotation($class, Index::class); |
||
71 | |||
72 | return $document; |
||
73 | } |
||
74 | |||
75 | public function getIndexMetadata(\ReflectionClass $class): array |
||
76 | { |
||
77 | if ($class->isTrait()) { |
||
78 | return []; |
||
79 | } |
||
80 | |||
81 | /** @var Index $document */ |
||
82 | $document = $this->reader->getClassAnnotation($class, Index::class); |
||
83 | |||
84 | if ($document === null) { |
||
85 | return []; |
||
86 | } |
||
87 | |||
88 | $settings = $document->getSettings(); |
||
89 | $settings['analysis'] = $this->getAnalysisConfig($class); |
||
90 | |||
91 | return array_filter(array_map('array_filter', [ |
||
92 | 'settings' => $settings, |
||
93 | 'mappings' => [ |
||
94 | 'properties' => array_filter($this->getClassMetadata($class)) |
||
95 | ] |
||
96 | ])); |
||
97 | } |
||
98 | |||
99 | private function getClassMetadata(\ReflectionClass $class): array |
||
100 | { |
||
101 | $mapping = []; |
||
102 | $objFields = null; |
||
103 | $arrayFields = null; |
||
104 | $embeddedFields = null; |
||
105 | |||
106 | /** @var \ReflectionProperty $property */ |
||
107 | foreach ($this->getDocumentPropertiesReflection($class) as $name => $property) { |
||
108 | $annotations = $this->reader->getPropertyAnnotations($property); |
||
109 | |||
110 | /** @var AbstractAnnotation $annotation */ |
||
111 | foreach ($annotations as $annotation) { |
||
112 | if (!$annotation instanceof PropertiesAwareInterface) { |
||
113 | continue; |
||
114 | } |
||
115 | |||
116 | $fieldMapping = $annotation->getSettings(); |
||
117 | |||
118 | if ($annotation instanceof Property) { |
||
119 | $fieldMapping['type'] = $annotation->type; |
||
120 | if ($annotation->fields) { |
||
121 | $fieldMapping['fields'] = $annotation->fields; |
||
122 | } |
||
123 | $fieldMapping['analyzer'] = $annotation->analyzer; |
||
124 | $fieldMapping['search_analyzer'] = $annotation->searchAnalyzer; |
||
125 | $fieldMapping['search_quote_analyzer'] = $annotation->searchQuoteAnalyzer; |
||
126 | } |
||
127 | |||
128 | if ($annotation instanceof Embedded) { |
||
129 | $embeddedClass = new \ReflectionClass($annotation->class); |
||
130 | $fieldMapping['type'] = $this->getObjectMappingType($embeddedClass); |
||
131 | $fieldMapping['properties'] = $this->getClassMetadata($embeddedClass); |
||
132 | $embeddedFields[$name] = $annotation->class; |
||
133 | } |
||
134 | |||
135 | $mapping[$annotation->getName() ?? Caser::snake($name)] = array_filter($fieldMapping); |
||
136 | $objFields[$name] = $annotation->getName() ?? Caser::snake($name); |
||
137 | $arrayFields[$annotation->getName() ?? Caser::snake($name)] = $name; |
||
138 | } |
||
139 | } |
||
140 | |||
141 | //Embeded fields are option compared to the array or object mapping. |
||
142 | if ($embeddedFields) { |
||
143 | $cacheItem = $this->cache->fetch(self::EMBEDDED_CACHED_FIELDS) ?? []; |
||
144 | $cacheItem[$class->getName()] = $embeddedFields; |
||
145 | $t = $this->cache->save(self::EMBEDDED_CACHED_FIELDS, $cacheItem); |
||
0 ignored issues
–
show
$t is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
146 | } |
||
147 | |||
148 | $cacheItem = $this->cache->fetch(self::ARRAY_CACHED_FIELDS) ?? []; |
||
149 | $cacheItem[$class->getName()] = $arrayFields; |
||
150 | $this->cache->save(self::ARRAY_CACHED_FIELDS, $cacheItem); |
||
151 | |||
152 | $cacheItem = $this->cache->fetch(self::OBJ_CACHED_FIELDS) ?? []; |
||
153 | $cacheItem[$class->getName()] = $objFields; |
||
154 | $this->cache->save(self::OBJ_CACHED_FIELDS, $cacheItem); |
||
155 | |||
156 | return $mapping; |
||
157 | } |
||
158 | |||
159 | public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = false): array |
||
160 | { |
||
161 | if ($class->isTrait() || (!$this->reader->getClassAnnotation($class, Index::class) && !$subClass)) { |
||
162 | return []; |
||
163 | } |
||
164 | |||
165 | $metadata = []; |
||
166 | |||
167 | /** @var \ReflectionProperty $property */ |
||
168 | foreach ($this->getDocumentPropertiesReflection($class) as $name => $property) { |
||
169 | /** @var AbstractAnnotation $annotation */ |
||
170 | foreach ($this->reader->getPropertyAnnotations($property) as $annotation) { |
||
171 | if (!$annotation instanceof PropertiesAwareInterface) { |
||
172 | continue; |
||
173 | } |
||
174 | |||
175 | $propertyMetadata = [ |
||
176 | 'identifier' => false, |
||
177 | 'class' => null, |
||
178 | 'embeded' => false, |
||
179 | 'type' => null, |
||
180 | 'public' => $property->isPublic(), |
||
181 | 'getter' => null, |
||
182 | 'setter' => null, |
||
183 | 'sub_properties' => [] |
||
184 | ]; |
||
185 | |||
186 | $name = $property->getName(); |
||
187 | $propertyMetadata['name'] = $name; |
||
188 | |||
189 | if (!$propertyMetadata['public']) { |
||
190 | $propertyMetadata['getter'] = $this->guessGetter($class, $name); |
||
191 | } |
||
192 | |||
193 | if ($annotation instanceof Id) { |
||
194 | $propertyMetadata['identifier'] = true; |
||
195 | } else { |
||
196 | if (!$propertyMetadata['public']) { |
||
197 | $propertyMetadata['setter'] = $this->guessSetter($class, $name); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | if ($annotation instanceof Property) { |
||
202 | // we need the type (and possibly settings?) in Converter::denormalize() |
||
203 | $propertyMetadata['type'] = $annotation->type; |
||
204 | $propertyMetadata['settings'] = $annotation->settings; |
||
205 | } |
||
206 | |||
207 | if ($annotation instanceof Embedded) { |
||
208 | $propertyMetadata['embeded'] = true; |
||
209 | $propertyMetadata['class'] = $annotation->class; |
||
210 | $propertyMetadata['sub_properties'] = $this->getPropertyMetadata( |
||
211 | new \ReflectionClass($annotation->class), |
||
212 | true |
||
213 | ); |
||
214 | } |
||
215 | |||
216 | $metadata[$annotation->getName() ?? Caser::snake($name)] = $propertyMetadata; |
||
217 | } |
||
218 | } |
||
219 | |||
220 | return $metadata; |
||
221 | } |
||
222 | |||
223 | public function getAnalysisConfig(\ReflectionClass $class): array |
||
224 | { |
||
225 | $config = []; |
||
226 | $mapping = $this->getClassMetadata($class); |
||
227 | |||
228 | //Think how to remove these array merge |
||
229 | $analyzers = $this->getListFromArrayByKey('analyzer', $mapping); |
||
230 | $analyzers = array_merge($analyzers, $this->getListFromArrayByKey('search_analyzer', $mapping)); |
||
231 | $analyzers = array_merge($analyzers, $this->getListFromArrayByKey('search_quote_analyzer', $mapping)); |
||
232 | |||
233 | View Code Duplication | foreach ($analyzers as $analyzer) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
234 | if (isset($this->analysisConfig['analyzer'][$analyzer])) { |
||
235 | $config['analyzer'][$analyzer] = $this->analysisConfig['analyzer'][$analyzer]; |
||
236 | } |
||
237 | } |
||
238 | |||
239 | $normalizers = $this->getListFromArrayByKey('normalizer', $mapping); |
||
240 | View Code Duplication | foreach ($normalizers as $normalizer) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
241 | if (isset($this->analysisConfig['normalizer'][$normalizer])) { |
||
242 | $config['normalizer'][$normalizer] = $this->analysisConfig['normalizer'][$normalizer]; |
||
243 | } |
||
244 | } |
||
245 | |||
246 | foreach (['tokenizer', 'filter', 'char_filter'] as $type) { |
||
247 | $list = $this->getListFromArrayByKey($type, $config); |
||
248 | |||
249 | foreach ($list as $listItem) { |
||
250 | if (isset($this->analysisConfig[$type][$listItem])) { |
||
251 | $config[$type][$listItem] = $this->analysisConfig[$type][$listItem]; |
||
252 | } |
||
253 | } |
||
254 | } |
||
255 | |||
256 | return $config; |
||
257 | } |
||
258 | |||
259 | protected function guessGetter(\ReflectionClass $class, $name): string |
||
260 | { |
||
261 | if ($class->hasMethod($name)) { |
||
262 | return $name; |
||
263 | } |
||
264 | |||
265 | if ($class->hasMethod('get' . ucfirst($name))) { |
||
266 | return 'get' . ucfirst($name); |
||
267 | } |
||
268 | |||
269 | if ($class->hasMethod('is' . ucfirst($name))) { |
||
270 | return 'is' . ucfirst($name); |
||
271 | } |
||
272 | |||
273 | // if there are underscores in the name convert them to CamelCase |
||
274 | if (strpos($name, '_')) { |
||
275 | $name = Caser::camel($name); |
||
276 | if ($class->hasMethod('get' . ucfirst($name))) { |
||
277 | return 'get' . $name; |
||
278 | } |
||
279 | if ($class->hasMethod('is' . ucfirst($name))) { |
||
280 | return 'is' . $name; |
||
281 | } |
||
282 | } |
||
283 | |||
284 | throw new \Exception("Could not determine a getter for `$name` of class `{$class->getNamespaceName()}`"); |
||
285 | } |
||
286 | |||
287 | protected function guessSetter(\ReflectionClass $class, $name): string |
||
288 | { |
||
289 | if ($class->hasMethod('set' . ucfirst($name))) { |
||
290 | return 'set' . ucfirst($name); |
||
291 | } |
||
292 | |||
293 | // if there are underscores in the name convert them to CamelCase |
||
294 | if (strpos($name, '_')) { |
||
295 | $name = Caser::camel($name); |
||
296 | if ($class->hasMethod('set' . ucfirst($name))) { |
||
297 | return 'set' . $name; |
||
298 | } |
||
299 | } |
||
300 | |||
301 | throw new \Exception("Could not determine a setter for `$name` of class `{$class->getNamespaceName()}`"); |
||
302 | } |
||
303 | |||
304 | private function getListFromArrayByKey(string $searchKey, array $array): array |
||
305 | { |
||
306 | $list = []; |
||
307 | |||
308 | foreach (new \RecursiveIteratorIterator( |
||
309 | new \RecursiveArrayIterator($array), |
||
310 | \RecursiveIteratorIterator::SELF_FIRST |
||
311 | ) as $key => $value) { |
||
312 | if ($key === $searchKey) { |
||
313 | if (is_array($value)) { |
||
314 | $list = array_merge($list, $value); |
||
315 | } else { |
||
316 | $list[] = $value; |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | |||
321 | return array_unique($list); |
||
322 | } |
||
323 | |||
324 | private function getObjectMappingType(\ReflectionClass $class): string |
||
325 | { |
||
326 | switch (true) { |
||
327 | case $this->reader->getClassAnnotation($class, ObjectType::class): |
||
328 | $type = ObjectType::TYPE; |
||
329 | break; |
||
330 | case $this->reader->getClassAnnotation($class, NestedType::class): |
||
331 | $type = NestedType::TYPE; |
||
332 | break; |
||
333 | default: |
||
334 | throw new \LogicException( |
||
335 | sprintf( |
||
336 | '%s must be used @ObjectType or @NestedType as embeddable object.', |
||
337 | $class->getName() |
||
338 | ) |
||
339 | ); |
||
340 | } |
||
341 | |||
342 | return $type; |
||
343 | } |
||
344 | |||
345 | private function getDocumentPropertiesReflection(\ReflectionClass $class): array |
||
346 | { |
||
347 | if (in_array($class->getName(), $this->properties)) { |
||
348 | return $this->properties[$class->getName()]; |
||
349 | } |
||
350 | |||
351 | $properties = []; |
||
352 | |||
353 | foreach ($class->getProperties() as $property) { |
||
354 | if (!in_array($property->getName(), $properties)) { |
||
355 | $properties[$property->getName()] = $property; |
||
356 | } |
||
357 | } |
||
358 | |||
359 | $parentReflection = $class->getParentClass(); |
||
360 | if ($parentReflection !== false) { |
||
361 | $properties = array_merge( |
||
362 | $properties, |
||
363 | array_diff_key($this->getDocumentPropertiesReflection($parentReflection), $properties) |
||
364 | ); |
||
365 | } |
||
366 | |||
367 | $this->properties[$class->getName()] = $properties; |
||
368 | |||
369 | return $properties; |
||
370 | } |
||
371 | } |
||
372 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.