Total Complexity | 96 |
Total Lines | 526 |
Duplicated Lines | 8.17 % |
Coverage | 81.04% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like XmlExporter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use XmlExporter, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class XmlExporter extends AbstractExporter |
||
30 | { |
||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $extension = '.dcm.xml'; |
||
35 | |||
36 | /** |
||
37 | * {@inheritdoc} |
||
38 | */ |
||
39 | public function exportClassMetadata(ClassMetadata $metadata) |
||
40 | { |
||
41 | 3 | $xml = new SimpleXmlElement('<?xml version="1.0" encoding="utf-8"?><doctrine-mapping ' . |
|
42 | 'xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" ' . |
||
43 | 3 | 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' . |
|
44 | 'xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd" />'); |
||
45 | |||
46 | 3 | if ($metadata->isMappedSuperclass) { |
|
47 | $root = $xml->addChild('mapped-superclass'); |
||
48 | 3 | } else { |
|
49 | $root = $xml->addChild('entity'); |
||
50 | } |
||
51 | 3 | ||
52 | if ($metadata->getCustomRepositoryClassName()) { |
||
|
|||
53 | $root->addAttribute('repository-class', $metadata->getCustomRepositoryClassName()); |
||
54 | 3 | } |
|
55 | |||
56 | $root->addAttribute('name', $metadata->getClassName()); |
||
57 | |||
58 | 3 | if ($metadata->table->getName()) { |
|
59 | $root->addAttribute('table', $metadata->table->getName()); |
||
60 | 3 | } |
|
61 | 1 | ||
62 | if ($metadata->table->getSchema()) { |
||
63 | $root->addAttribute('schema', $metadata->table->getSchema()); |
||
64 | 3 | } |
|
65 | |||
66 | if ($metadata->inheritanceType && $metadata->inheritanceType !== InheritanceType::NONE) { |
||
67 | $root->addAttribute('inheritance-type', $metadata->inheritanceType); |
||
68 | 3 | } |
|
69 | |||
70 | if ($metadata->table->getOptions()) { |
||
71 | $optionsXml = $root->addChild('options'); |
||
72 | 3 | ||
73 | 1 | $this->exportTableOptions($optionsXml, $metadata->table->getOptions()); |
|
74 | } |
||
75 | 1 | ||
76 | if ($metadata->discriminatorColumn) { |
||
77 | $discrColumn = $metadata->discriminatorColumn; |
||
78 | 3 | $discriminatorColumnXml = $root->addChild('discriminator-column'); |
|
79 | |||
80 | $discriminatorColumnXml->addAttribute('name', $discrColumn->getColumnName()); |
||
81 | $discriminatorColumnXml->addAttribute('type', $discrColumn->getTypeName()); |
||
82 | |||
83 | if (is_int($discrColumn->getLength())) { |
||
84 | $discriminatorColumnXml->addAttribute('length', (string) $discrColumn->getLength()); |
||
85 | } |
||
86 | |||
87 | if (is_int($discrColumn->getScale())) { |
||
88 | $discriminatorColumnXml->addAttribute('scale', (string) $discrColumn->getScale()); |
||
89 | } |
||
90 | |||
91 | if (is_int($discrColumn->getPrecision())) { |
||
92 | $discriminatorColumnXml->addAttribute('precision', (string) $discrColumn->getPrecision()); |
||
93 | } |
||
94 | } |
||
95 | |||
96 | if ($metadata->discriminatorMap) { |
||
97 | $discriminatorMapXml = $root->addChild('discriminator-map'); |
||
98 | 3 | ||
99 | foreach ($metadata->discriminatorMap as $value => $className) { |
||
100 | $discriminatorMappingXml = $discriminatorMapXml->addChild('discriminator-mapping'); |
||
101 | $discriminatorMappingXml->addAttribute('value', (string) $value); |
||
102 | $discriminatorMappingXml->addAttribute('class', $className); |
||
103 | } |
||
104 | } |
||
105 | |||
106 | if ($metadata->changeTrackingPolicy !== ChangeTrackingPolicy::DEFERRED_IMPLICIT) { |
||
107 | $root->addChild('change-tracking-policy', $metadata->changeTrackingPolicy); |
||
108 | 3 | } |
|
109 | |||
110 | 3 | if ($metadata->table->getIndexes()) { |
|
111 | $indexesXml = $root->addChild('indexes'); |
||
112 | |||
113 | foreach ($metadata->table->getIndexes() as $name => $index) { |
||
114 | 3 | $indexXml = $indexesXml->addChild('index'); |
|
115 | |||
116 | $indexXml->addAttribute('name', $name); |
||
117 | $indexXml->addAttribute('columns', implode(',', $index['columns'])); |
||
118 | |||
119 | if ($index['unique']) { |
||
120 | $indexXml->addAttribute('unique', 'true'); |
||
121 | } |
||
122 | |||
123 | if ($index['flags']) { |
||
124 | $indexXml->addAttribute('flags', implode(',', $index['flags'])); |
||
125 | } |
||
126 | |||
127 | View Code Duplication | if ($index['options']) { |
|
128 | 3 | $optionsXml = $indexXml->addChild('options'); |
|
129 | |||
130 | foreach ($index['options'] as $key => $value) { |
||
131 | $optionXml = $optionsXml->addChild('option', $value); |
||
132 | |||
133 | $optionXml->addAttribute('name', $key); |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | } |
||
138 | |||
139 | 3 | if ($metadata->table->getUniqueConstraints()) { |
|
140 | 3 | $uniqueConstraintsXml = $root->addChild('unique-constraints'); |
|
141 | |||
142 | 3 | foreach ($metadata->table->getUniqueConstraints() as $name => $constraint) { |
|
143 | 3 | $uniqueConstraintXml = $uniqueConstraintsXml->addChild('unique-constraint'); |
|
144 | 2 | ||
145 | $uniqueConstraintXml->addAttribute('name', $name); |
||
146 | 3 | $uniqueConstraintXml->addAttribute('columns', implode(',', $constraint['columns'])); |
|
147 | |||
148 | if ($constraint['flags']) { |
||
149 | $uniqueConstraintXml->addAttribute('flags', implode(',', $constraint['flags'])); |
||
150 | } |
||
151 | |||
152 | View Code Duplication | if ($constraint['options']) { |
|
153 | $optionsXml = $uniqueConstraintXml->addChild('options'); |
||
154 | |||
155 | foreach ($constraint['options'] as $key => $value) { |
||
156 | $optionXml = $optionsXml->addChild('option', $value); |
||
157 | |||
158 | $optionXml->addAttribute('name', $key); |
||
159 | 3 | } |
|
160 | 2 | } |
|
161 | } |
||
162 | } |
||
163 | 3 | ||
164 | 2 | $properties = iterator_to_array($metadata->getDeclaredPropertiesIterator()); |
|
165 | 2 | $id = []; |
|
166 | 2 | ||
167 | foreach ($properties as $name => $property) { |
||
168 | 2 | if ($property->isPrimaryKey()) { |
|
169 | 2 | $id[$name] = $property; |
|
170 | 2 | ||
171 | unset($properties[$name]); |
||
172 | 2 | } |
|
173 | } |
||
174 | |||
175 | if ($id) { |
||
176 | foreach ($id as $property) { |
||
177 | $idXml = $root->addChild('id'); |
||
178 | |||
179 | $idXml->addAttribute('name', $property->getName()); |
||
180 | 2 | ||
181 | 2 | if ($property instanceof AssociationMetadata) { |
|
182 | $idXml->addAttribute('association-key', 'true'); |
||
183 | 2 | ||
184 | continue; |
||
185 | 2 | } |
|
186 | |||
187 | $idXml->addAttribute('type', $property->getTypeName()); |
||
188 | $idXml->addAttribute('column', $property->getColumnName()); |
||
189 | |||
190 | 3 | if (is_int($property->getLength())) { |
|
191 | 2 | $idXml->addAttribute('length', $property->getLength()); |
|
192 | 2 | } |
|
193 | |||
194 | 2 | if ($property->hasValueGenerator()) { |
|
195 | 2 | $generatorXml = $idXml->addChild('generator'); |
|
196 | 2 | ||
197 | $generatorXml->addAttribute('strategy', $property->getValueGenerator()->getType()); |
||
198 | 2 | ||
199 | 1 | $this->exportSequenceInformation($idXml, $property); |
|
200 | } |
||
201 | } |
||
202 | 2 | } |
|
203 | 1 | ||
204 | $orderMap = [ |
||
205 | FieldMetadata::class, |
||
206 | 2 | OneToOneAssociationMetadata::class, |
|
207 | 1 | OneToManyAssociationMetadata::class, |
|
208 | ManyToOneAssociationMetadata::class, |
||
209 | ManyToManyAssociationMetadata::class, |
||
210 | 2 | ]; |
|
211 | |||
212 | |||
213 | |||
214 | 2 | uasort($properties, function($m1, $m2) use (&$orderMap) { |
|
215 | $a1 = array_search(get_class($m1), $orderMap); |
||
216 | $a2 = array_search(get_class($m2), $orderMap); |
||
217 | |||
218 | 2 | return strcmp((string) $a1, (string) $a2); |
|
219 | }); |
||
220 | |||
221 | View Code Duplication | foreach ($properties as $property) { |
|
222 | 2 | if ($property instanceof FieldMetadata) { |
|
223 | 1 | $this->exportFieldMetadata($root, $metadata, $property); |
|
224 | } else if ($property instanceof AssociationMetadata) { |
||
225 | $this->exportAssociationMetadata($root, $metadata, $property); |
||
226 | 2 | } |
|
227 | 2 | } |
|
228 | |||
229 | 2 | if (isset($metadata->lifecycleCallbacks) && count($metadata->lifecycleCallbacks)>0) { |
|
230 | 2 | $lifecycleCallbacksXml = $root->addChild('lifecycle-callbacks'); |
|
231 | |||
232 | 2 | foreach ($metadata->lifecycleCallbacks as $name => $methods) { |
|
233 | foreach ($methods as $method) { |
||
234 | $lifecycleCallbackXml = $lifecycleCallbacksXml->addChild('lifecycle-callback'); |
||
235 | |||
236 | $lifecycleCallbackXml->addAttribute('type', $name); |
||
237 | $lifecycleCallbackXml->addAttribute('method', $method); |
||
238 | } |
||
239 | 3 | } |
|
240 | 3 | } |
|
241 | 3 | ||
242 | 3 | $this->processEntityListeners($metadata, $root); |
|
243 | |||
244 | return $this->asXml($xml); |
||
245 | 3 | } |
|
246 | 1 | ||
247 | 1 | /** |
|
248 | * @param \SimpleXMLElement $root |
||
249 | 1 | * @param ClassMetadata $metadata |
|
250 | 3 | * @param FieldMetadata $property |
|
251 | */ |
||
252 | 3 | private function exportFieldMetadata( |
|
253 | 1 | \SimpleXMLElement $root, |
|
254 | 1 | ClassMetadata $metadata, |
|
255 | 1 | FieldMetadata $property |
|
256 | 1 | ) |
|
257 | 1 | { |
|
258 | 1 | $fieldXml = $root->addChild('field'); |
|
259 | 1 | ||
260 | 1 | $fieldXml->addAttribute('name', $property->getName()); |
|
261 | $fieldXml->addAttribute('type', $property->getTypeName()); |
||
262 | $fieldXml->addAttribute('column', $property->getColumnName()); |
||
263 | 1 | ||
264 | 1 | if ($property->isNullable()) { |
|
265 | $fieldXml->addAttribute('nullable', 'true'); |
||
266 | 1 | } |
|
267 | 1 | ||
268 | if ($property->isUnique()) { |
||
269 | $fieldXml->addAttribute('unique', 'true'); |
||
270 | 1 | } |
|
271 | 1 | ||
272 | if (is_int($property->getLength())) { |
||
273 | $fieldXml->addAttribute('length', (string) $property->getLength()); |
||
274 | 1 | } |
|
275 | |||
276 | if (is_int($property->getPrecision())) { |
||
277 | $fieldXml->addAttribute('precision', (string) $property->getPrecision()); |
||
278 | 1 | } |
|
279 | 1 | ||
280 | if (is_int($property->getScale())) { |
||
281 | $fieldXml->addAttribute('scale', (string) $property->getScale()); |
||
282 | 1 | } |
|
283 | 1 | ||
284 | if ($metadata->isVersioned() && $metadata->versionProperty->getName() === $property->getName()) { |
||
285 | $fieldXml->addAttribute('version', 'true'); |
||
286 | 1 | } |
|
287 | |||
288 | 1 | if ($property->getColumnDefinition()) { |
|
289 | 1 | $fieldXml->addAttribute('column-definition', $property->getColumnDefinition()); |
|
290 | 1 | } |
|
291 | |||
292 | View Code Duplication | if ($property->getOptions()) { |
|
293 | $optionsXml = $fieldXml->addChild('options'); |
||
294 | 1 | ||
295 | 1 | foreach ($property->getOptions() as $key => $value) { |
|
296 | $optionXml = $optionsXml->addChild('option', (string) $value); |
||
297 | |||
298 | 1 | $optionXml->addAttribute('name', $key); |
|
299 | 1 | } |
|
300 | } |
||
301 | 1 | } |
|
302 | 1 | ||
303 | /** |
||
304 | * @param \SimpleXMLElement $root |
||
305 | * @param ClassMetadata $metadata |
||
306 | 1 | * @param AssociationMetadata $association |
|
307 | 1 | */ |
|
308 | private function exportAssociationMetadata( |
||
309 | 1 | \SimpleXMLElement $root, |
|
310 | ClassMetadata $metadata, |
||
311 | 1 | AssociationMetadata $association |
|
312 | ) { |
||
313 | 1 | if ($association instanceof OneToOneAssociationMetadata) { |
|
314 | 1 | $associationMappingXml = $root->addChild('one-to-one'); |
|
315 | 1 | } elseif ($association instanceof OneToManyAssociationMetadata) { |
|
316 | 1 | $associationMappingXml = $root->addChild('one-to-many'); |
|
317 | } elseif ($association instanceof ManyToOneAssociationMetadata) { |
||
318 | 1 | $associationMappingXml = $root->addChild('many-to-one'); |
|
319 | 1 | } else { |
|
320 | $associationMappingXml = $root->addChild('many-to-many'); |
||
321 | } |
||
322 | |||
323 | 1 | $associationMappingXml->addAttribute('field', $association->getName()); |
|
324 | $associationMappingXml->addAttribute('target-entity', $association->getTargetEntity()); |
||
325 | 1 | $associationMappingXml->addAttribute('fetch', $association->getFetchMode()); |
|
326 | 1 | ||
327 | $this->exportCascade($associationMappingXml, $association->getCascade()); |
||
328 | 1 | ||
329 | 1 | if ($association->getMappedBy()) { |
|
330 | $associationMappingXml->addAttribute('mapped-by', $association->getMappedBy()); |
||
331 | 1 | } |
|
332 | |||
333 | if ($association->getInversedBy()) { |
||
334 | $associationMappingXml->addAttribute('inversed-by', $association->getInversedBy()); |
||
335 | 1 | } |
|
336 | 1 | ||
337 | if ($association->isOrphanRemoval()) { |
||
338 | $associationMappingXml->addAttribute('orphan-removal', 'true'); |
||
339 | 1 | } |
|
340 | |||
341 | if ($association instanceof ToManyAssociationMetadata) { |
||
342 | if ($association instanceof ManyToManyAssociationMetadata && $association->getJoinTable()) { |
||
343 | 1 | $joinTableXml = $associationMappingXml->addChild('join-table'); |
|
344 | 1 | $joinTable = $association->getJoinTable(); |
|
345 | |||
346 | $joinTableXml->addAttribute('name', $joinTable->getName()); |
||
347 | |||
348 | $this->exportJoinColumns($joinTableXml, $joinTable->getJoinColumns(), 'join-columns'); |
||
349 | 1 | $this->exportJoinColumns($joinTableXml, $joinTable->getInverseJoinColumns(), 'inverse-join-columns'); |
|
350 | 1 | } |
|
351 | |||
352 | 1 | if ($association->getIndexedBy()) { |
|
353 | 1 | $associationMappingXml->addAttribute('index-by', $association->getIndexedBy()); |
|
354 | } |
||
355 | 1 | ||
356 | 1 | if ($association->getOrderBy()) { |
|
357 | $orderByXml = $associationMappingXml->addChild('order-by'); |
||
358 | 1 | ||
359 | 1 | foreach ($association->getOrderBy() as $name => $direction) { |
|
360 | $orderByFieldXml = $orderByXml->addChild('order-by-field'); |
||
361 | |||
362 | 1 | $orderByFieldXml->addAttribute('name', $name); |
|
363 | $orderByFieldXml->addAttribute('direction', $direction); |
||
364 | } |
||
365 | } |
||
366 | 1 | } |
|
367 | 1 | ||
368 | if ($association instanceof ToOneAssociationMetadata) { |
||
369 | if ($association->getJoinColumns()) { |
||
370 | $this->exportJoinColumns($associationMappingXml, $association->getJoinColumns()); |
||
371 | } |
||
372 | 1 | } |
|
373 | 1 | } |
|
374 | |||
375 | 1 | /** |
|
376 | 1 | * @param \SimpleXMLElement $associationXml |
|
377 | * @param array $joinColumns |
||
378 | 1 | * @param string $joinColumnsName |
|
379 | 1 | */ |
|
380 | private function exportJoinColumns( |
||
381 | \SimpleXMLElement $associationXml, |
||
382 | array $joinColumns, |
||
383 | $joinColumnsName = 'join-columns' |
||
384 | 3 | ) |
|
385 | 1 | { |
|
386 | $joinColumnsXml = $associationXml->addChild($joinColumnsName); |
||
387 | 1 | ||
388 | 1 | foreach ($joinColumns as $joinColumn) { |
|
389 | 1 | /** @var JoinColumnMetadata $joinColumn */ |
|
390 | $joinColumnXml = $joinColumnsXml->addChild('join-column'); |
||
391 | 1 | ||
392 | 1 | $joinColumnXml->addAttribute('name', $joinColumn->getColumnName()); |
|
393 | $joinColumnXml->addAttribute('referenced-column-name', $joinColumn->getReferencedColumnName()); |
||
394 | |||
395 | if (! empty($joinColumn->getAliasedName())) { |
||
396 | $joinColumnXml->addAttribute('field-name', $joinColumn->getAliasedName()); |
||
397 | 3 | } |
|
398 | |||
399 | if (! empty($joinColumn->getOnDelete())) { |
||
400 | $joinColumnXml->addAttribute('on-delete', $joinColumn->getOnDelete()); |
||
401 | } |
||
402 | |||
403 | if (! empty($joinColumn->getColumnDefinition())) { |
||
404 | $joinColumnXml->addAttribute('column-definition', $joinColumn->getColumnDefinition()); |
||
405 | } |
||
406 | 1 | ||
407 | if ($joinColumn->isNullable()) { |
||
408 | 1 | $joinColumnXml->addAttribute('nullable', (string) $joinColumn->isNullable()); |
|
409 | 1 | } |
|
410 | 1 | ||
411 | 1 | if ($joinColumn->isUnique()) { |
|
412 | 1 | $joinColumnXml->addAttribute('unique', (string) $joinColumn->isUnique()); |
|
413 | } |
||
414 | 1 | ||
415 | View Code Duplication | if ($joinColumn->getOptions()) { |
|
416 | 1 | $optionsXml = $joinColumnXml->addChild('options'); |
|
417 | 1 | ||
418 | foreach ($joinColumn->getOptions() as $key => $value) { |
||
419 | $optionXml = $optionsXml->addChild('option', (string) $value); |
||
420 | 1 | ||
421 | $optionXml->addAttribute('name', $key); |
||
422 | } |
||
423 | } |
||
424 | } |
||
425 | } |
||
426 | |||
427 | /** |
||
428 | * @param \SimpleXMLElement $associationXml |
||
429 | * @param array $associationCascades |
||
430 | 2 | * |
|
431 | * @return string |
||
432 | 2 | */ |
|
433 | private function exportCascade(\SimpleXMLElement $associationXml, array $associationCascades) |
||
434 | 2 | { |
|
435 | 1 | $cascades = []; |
|
436 | |||
437 | foreach (['persist', 'remove', 'refresh'] as $type) { |
||
438 | 1 | if (in_array($type, $associationCascades)) { |
|
439 | $cascades[] = 'cascade-' . $type; |
||
440 | 1 | } |
|
441 | 1 | } |
|
442 | 1 | ||
443 | 1 | if (count($cascades) === 5) { |
|
444 | $cascades = ['cascade-all']; |
||
445 | } |
||
446 | |||
447 | if ($cascades) { |
||
448 | $cascadeXml = $associationXml->addChild('cascade'); |
||
449 | |||
450 | 3 | foreach ($cascades as $type) { |
|
451 | $cascadeXml->addChild($type); |
||
452 | 3 | } |
|
453 | } |
||
454 | 3 | } |
|
455 | 3 | ||
456 | /** |
||
457 | 3 | * Exports (nested) option elements. |
|
458 | * |
||
459 | * @param SimpleXMLElement $parentXml |
||
460 | * @param array $options |
||
461 | */ |
||
462 | private function exportTableOptions(SimpleXMLElement $parentXml, array $options) : void |
||
463 | { |
||
464 | foreach ($options as $name => $option) { |
||
465 | $isArray = is_array($option); |
||
466 | $optionXml = $isArray |
||
467 | ? $parentXml->addChild('option') |
||
468 | : $parentXml->addChild('option', (string) $option); |
||
469 | |||
470 | $optionXml->addAttribute('name', (string) $name); |
||
471 | |||
472 | if ($isArray) { |
||
473 | $this->exportTableOptions($optionXml, $option); |
||
474 | } |
||
475 | } |
||
476 | } |
||
477 | |||
478 | /** |
||
479 | * Export sequence information (if available/configured) into the current identifier XML node |
||
480 | * |
||
481 | * @param \SimpleXMLElement $identifierXmlNode |
||
482 | * @param FieldMetadata $metadata |
||
483 | * |
||
484 | * @return void |
||
485 | */ |
||
486 | private function exportSequenceInformation(\SimpleXMLElement $identifierXmlNode, FieldMetadata $metadata) |
||
487 | { |
||
488 | $sequenceDefinition = $metadata->getValueGenerator()->getDefinition(); |
||
489 | |||
490 | if (! ($metadata->getValueGenerator()->getType() === GeneratorType::SEQUENCE && $sequenceDefinition)) { |
||
491 | return; |
||
492 | } |
||
493 | |||
494 | $sequenceGeneratorXml = $identifierXmlNode->addChild('sequence-generator'); |
||
495 | |||
496 | $sequenceGeneratorXml->addAttribute('sequence-name', $sequenceDefinition['sequenceName']); |
||
497 | $sequenceGeneratorXml->addAttribute('allocation-size', (string) $sequenceDefinition['allocationSize']); |
||
498 | } |
||
499 | |||
500 | /** |
||
501 | * @param \SimpleXMLElement $simpleXml |
||
502 | * |
||
503 | * @return string $xml |
||
504 | */ |
||
505 | private function asXml(SimpleXMLElement $simpleXml) : string |
||
506 | { |
||
507 | $dom = new \DOMDocument('1.0', 'UTF-8'); |
||
508 | |||
509 | $dom->loadXML($simpleXml->asXML()); |
||
510 | $dom->formatOutput = true; |
||
511 | |||
512 | return $dom->saveXML(); |
||
513 | } |
||
514 | |||
515 | private function processEntityListeners(ClassMetadata $metadata, SimpleXMLElement $root): void |
||
516 | { |
||
517 | if (0 === \count($metadata->entityListeners)) { |
||
518 | return; |
||
519 | } |
||
520 | |||
521 | $entityListenersXml = $root->addChild('entity-listeners'); |
||
522 | $entityListenersXmlMap = []; |
||
523 | |||
524 | $this->generateEntityListenerXml($metadata, $entityListenersXmlMap, $entityListenersXml); |
||
525 | } |
||
526 | |||
527 | private function generateEntityListenerXml(ClassMetadata $metadata, array $entityListenersXmlMap, SimpleXMLElement $entityListenersXml): void |
||
528 | { |
||
529 | foreach ($metadata->entityListeners as $event => $entityListenerConfig) { |
||
530 | foreach ($entityListenerConfig as $entityListener) { |
||
531 | $entityListenerXml = $this->addClassToMapIfExists( |
||
532 | $entityListenersXmlMap, |
||
533 | $entityListener, |
||
534 | $entityListenersXml |
||
535 | ); |
||
536 | |||
537 | $entityListenerCallbackXml = $entityListenerXml->addChild('lifecycle-callback'); |
||
538 | $entityListenerCallbackXml->addAttribute('type', $event); |
||
539 | $entityListenerCallbackXml->addAttribute('method', $entityListener['method']); |
||
540 | } |
||
541 | } |
||
542 | } |
||
543 | |||
544 | private function addClassToMapIfExists(array $entityListenersXmlMap, array $entityListener, SimpleXMLElement $entityListenersXml): SimpleXMLElement |
||
555 | } |
||
556 | } |
||
557 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: