composer package updates
[openemr.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Mapping / Driver / XmlDriver.php
blob7a6d4b135c7dfcc8aeb78d9ae0de69088464a383
1 <?php
2 /*
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\ORM\Mapping\Driver;
22 use SimpleXMLElement;
23 use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
24 use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
25 use Doctrine\Common\Persistence\Mapping\ClassMetadata;
26 use Doctrine\ORM\Mapping\MappingException;
28 /**
29 * XmlDriver is a metadata driver that enables mapping through XML files.
31 * @license http://www.opensource.org/licenses/mit-license.php MIT
32 * @link www.doctrine-project.org
33 * @since 2.0
34 * @author Benjamin Eberlei <kontakt@beberlei.de>
35 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
36 * @author Jonathan H. Wage <jonwage@gmail.com>
37 * @author Roman Borschel <roman@code-factory.org>
39 class XmlDriver extends FileDriver
41 const DEFAULT_FILE_EXTENSION = '.dcm.xml';
43 /**
44 * {@inheritDoc}
46 public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
48 parent::__construct($locator, $fileExtension);
51 /**
52 * {@inheritDoc}
54 public function loadMetadataForClass($className, ClassMetadata $metadata)
56 /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
57 /* @var $xmlRoot SimpleXMLElement */
58 $xmlRoot = $this->getElement($className);
60 if ($xmlRoot->getName() == 'entity') {
61 if (isset($xmlRoot['repository-class'])) {
62 $metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
64 if (isset($xmlRoot['read-only']) && $this->evaluateBoolean($xmlRoot['read-only'])) {
65 $metadata->markReadOnly();
67 } else if ($xmlRoot->getName() == 'mapped-superclass') {
68 $metadata->setCustomRepositoryClass(
69 isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
71 $metadata->isMappedSuperclass = true;
72 } else if ($xmlRoot->getName() == 'embeddable') {
73 $metadata->isEmbeddedClass = true;
74 } else {
75 throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
78 // Evaluate <entity...> attributes
79 $primaryTable = array();
81 if (isset($xmlRoot['table'])) {
82 $primaryTable['name'] = (string) $xmlRoot['table'];
85 if (isset($xmlRoot['schema'])) {
86 $primaryTable['schema'] = (string) $xmlRoot['schema'];
89 $metadata->setPrimaryTable($primaryTable);
91 // Evaluate second level cache
92 if (isset($xmlRoot->cache)) {
93 $metadata->enableCache($this->cacheToArray($xmlRoot->cache));
96 // Evaluate named queries
97 if (isset($xmlRoot->{'named-queries'})) {
98 foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) {
99 $metadata->addNamedQuery(array(
100 'name' => (string)$namedQueryElement['name'],
101 'query' => (string)$namedQueryElement['query']
106 // Evaluate native named queries
107 if (isset($xmlRoot->{'named-native-queries'})) {
108 foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) {
109 $metadata->addNamedNativeQuery(array(
110 'name' => isset($nativeQueryElement['name']) ? (string)$nativeQueryElement['name'] : null,
111 'query' => isset($nativeQueryElement->query) ? (string)$nativeQueryElement->query : null,
112 'resultClass' => isset($nativeQueryElement['result-class']) ? (string)$nativeQueryElement['result-class'] : null,
113 'resultSetMapping' => isset($nativeQueryElement['result-set-mapping']) ? (string)$nativeQueryElement['result-set-mapping'] : null,
118 // Evaluate sql result set mapping
119 if (isset($xmlRoot->{'sql-result-set-mappings'})) {
120 foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) {
121 $entities = array();
122 $columns = array();
123 foreach ($rsmElement as $entityElement) {
124 //<entity-result/>
125 if (isset($entityElement['entity-class'])) {
126 $entityResult = array(
127 'fields' => array(),
128 'entityClass' => (string)$entityElement['entity-class'],
129 'discriminatorColumn' => isset($entityElement['discriminator-column']) ? (string)$entityElement['discriminator-column'] : null,
132 foreach ($entityElement as $fieldElement) {
133 $entityResult['fields'][] = array(
134 'name' => isset($fieldElement['name']) ? (string)$fieldElement['name'] : null,
135 'column' => isset($fieldElement['column']) ? (string)$fieldElement['column'] : null,
139 $entities[] = $entityResult;
142 //<column-result/>
143 if (isset($entityElement['name'])) {
144 $columns[] = array(
145 'name' => (string)$entityElement['name'],
150 $metadata->addSqlResultSetMapping(array(
151 'name' => (string)$rsmElement['name'],
152 'entities' => $entities,
153 'columns' => $columns
158 if (isset($xmlRoot['inheritance-type'])) {
159 $inheritanceType = (string)$xmlRoot['inheritance-type'];
160 $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
162 if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
163 // Evaluate <discriminator-column...>
164 if (isset($xmlRoot->{'discriminator-column'})) {
165 $discrColumn = $xmlRoot->{'discriminator-column'};
166 $metadata->setDiscriminatorColumn(array(
167 'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null,
168 'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : null,
169 'length' => isset($discrColumn['length']) ? (string)$discrColumn['length'] : null,
170 'columnDefinition' => isset($discrColumn['column-definition']) ? (string)$discrColumn['column-definition'] : null
172 } else {
173 $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
176 // Evaluate <discriminator-map...>
177 if (isset($xmlRoot->{'discriminator-map'})) {
178 $map = array();
179 foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) {
180 $map[(string)$discrMapElement['value']] = (string)$discrMapElement['class'];
182 $metadata->setDiscriminatorMap($map);
188 // Evaluate <change-tracking-policy...>
189 if (isset($xmlRoot['change-tracking-policy'])) {
190 $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
191 . strtoupper((string)$xmlRoot['change-tracking-policy'])));
194 // Evaluate <indexes...>
195 if (isset($xmlRoot->indexes)) {
196 $metadata->table['indexes'] = array();
197 foreach ($xmlRoot->indexes->index as $indexXml) {
198 $index = array('columns' => explode(',', (string) $indexXml['columns']));
200 if (isset($indexXml['flags'])) {
201 $index['flags'] = explode(',', (string) $indexXml['flags']);
204 if (isset($indexXml->options)) {
205 $index['options'] = $this->_parseOptions($indexXml->options->children());
208 if (isset($indexXml['name'])) {
209 $metadata->table['indexes'][(string) $indexXml['name']] = $index;
210 } else {
211 $metadata->table['indexes'][] = $index;
216 // Evaluate <unique-constraints..>
217 if (isset($xmlRoot->{'unique-constraints'})) {
218 $metadata->table['uniqueConstraints'] = array();
219 foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $uniqueXml) {
220 $unique = array('columns' => explode(',', (string) $uniqueXml['columns']));
223 if (isset($uniqueXml->options)) {
224 $unique['options'] = $this->_parseOptions($uniqueXml->options->children());
227 if (isset($uniqueXml['name'])) {
228 $metadata->table['uniqueConstraints'][(string)$uniqueXml['name']] = $unique;
229 } else {
230 $metadata->table['uniqueConstraints'][] = $unique;
235 if (isset($xmlRoot->options)) {
236 $metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children());
239 // The mapping assignment is done in 2 times as a bug might occurs on some php/xml lib versions
240 // The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception
241 $mappings = array();
242 // Evaluate <field ...> mappings
243 if (isset($xmlRoot->field)) {
244 foreach ($xmlRoot->field as $fieldMapping) {
245 $mapping = $this->columnToArray($fieldMapping);
247 if (isset($mapping['version'])) {
248 $metadata->setVersionMapping($mapping);
249 unset($mapping['version']);
252 $metadata->mapField($mapping);
256 if (isset($xmlRoot->embedded)) {
257 foreach ($xmlRoot->embedded as $embeddedMapping) {
258 $columnPrefix = isset($embeddedMapping['column-prefix'])
259 ? (string) $embeddedMapping['column-prefix']
260 : null;
262 $useColumnPrefix = isset($embeddedMapping['use-column-prefix'])
263 ? $this->evaluateBoolean($embeddedMapping['use-column-prefix'])
264 : true;
266 $mapping = array(
267 'fieldName' => (string) $embeddedMapping['name'],
268 'class' => (string) $embeddedMapping['class'],
269 'columnPrefix' => $useColumnPrefix ? $columnPrefix : false
272 $metadata->mapEmbedded($mapping);
276 foreach ($mappings as $mapping) {
277 if (isset($mapping['version'])) {
278 $metadata->setVersionMapping($mapping);
281 $metadata->mapField($mapping);
284 // Evaluate <id ...> mappings
285 $associationIds = array();
286 foreach ($xmlRoot->id as $idElement) {
287 if (isset($idElement['association-key']) && $this->evaluateBoolean($idElement['association-key'])) {
288 $associationIds[(string)$idElement['name']] = true;
289 continue;
292 $mapping = array(
293 'id' => true,
294 'fieldName' => (string)$idElement['name']
297 if (isset($idElement['type'])) {
298 $mapping['type'] = (string)$idElement['type'];
301 if (isset($idElement['length'])) {
302 $mapping['length'] = (string)$idElement['length'];
305 if (isset($idElement['column'])) {
306 $mapping['columnName'] = (string)$idElement['column'];
309 if (isset($idElement['column-definition'])) {
310 $mapping['columnDefinition'] = (string)$idElement['column-definition'];
313 if (isset($idElement->options)) {
314 $mapping['options'] = $this->_parseOptions($idElement->options->children());
317 $metadata->mapField($mapping);
319 if (isset($idElement->generator)) {
320 $strategy = isset($idElement->generator['strategy']) ?
321 (string)$idElement->generator['strategy'] : 'AUTO';
322 $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
323 . $strategy));
326 // Check for SequenceGenerator/TableGenerator definition
327 if (isset($idElement->{'sequence-generator'})) {
328 $seqGenerator = $idElement->{'sequence-generator'};
329 $metadata->setSequenceGeneratorDefinition(array(
330 'sequenceName' => (string)$seqGenerator['sequence-name'],
331 'allocationSize' => (string)$seqGenerator['allocation-size'],
332 'initialValue' => (string)$seqGenerator['initial-value']
334 } else if (isset($idElement->{'custom-id-generator'})) {
335 $customGenerator = $idElement->{'custom-id-generator'};
336 $metadata->setCustomGeneratorDefinition(array(
337 'class' => (string) $customGenerator['class']
339 } else if (isset($idElement->{'table-generator'})) {
340 throw MappingException::tableIdGeneratorNotImplemented($className);
344 // Evaluate <one-to-one ...> mappings
345 if (isset($xmlRoot->{'one-to-one'})) {
346 foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
347 $mapping = array(
348 'fieldName' => (string)$oneToOneElement['field'],
349 'targetEntity' => (string)$oneToOneElement['target-entity']
352 if (isset($associationIds[$mapping['fieldName']])) {
353 $mapping['id'] = true;
356 if (isset($oneToOneElement['fetch'])) {
357 $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToOneElement['fetch']);
360 if (isset($oneToOneElement['mapped-by'])) {
361 $mapping['mappedBy'] = (string)$oneToOneElement['mapped-by'];
362 } else {
363 if (isset($oneToOneElement['inversed-by'])) {
364 $mapping['inversedBy'] = (string)$oneToOneElement['inversed-by'];
366 $joinColumns = array();
368 if (isset($oneToOneElement->{'join-column'})) {
369 $joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'});
370 } else if (isset($oneToOneElement->{'join-columns'})) {
371 foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
372 $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
376 $mapping['joinColumns'] = $joinColumns;
379 if (isset($oneToOneElement->cascade)) {
380 $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade);
383 if (isset($oneToOneElement['orphan-removal'])) {
384 $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToOneElement['orphan-removal']);
387 $metadata->mapOneToOne($mapping);
389 // Evaluate second level cache
390 if (isset($oneToOneElement->cache)) {
391 $metadata->enableAssociationCache($mapping['fieldName'], $this->cacheToArray($oneToOneElement->cache));
396 // Evaluate <one-to-many ...> mappings
397 if (isset($xmlRoot->{'one-to-many'})) {
398 foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
399 $mapping = array(
400 'fieldName' => (string)$oneToManyElement['field'],
401 'targetEntity' => (string)$oneToManyElement['target-entity'],
402 'mappedBy' => (string)$oneToManyElement['mapped-by']
405 if (isset($oneToManyElement['fetch'])) {
406 $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToManyElement['fetch']);
409 if (isset($oneToManyElement->cascade)) {
410 $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
413 if (isset($oneToManyElement['orphan-removal'])) {
414 $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToManyElement['orphan-removal']);
417 if (isset($oneToManyElement->{'order-by'})) {
418 $orderBy = array();
419 foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
420 $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
422 $mapping['orderBy'] = $orderBy;
425 if (isset($oneToManyElement['index-by'])) {
426 $mapping['indexBy'] = (string)$oneToManyElement['index-by'];
427 } else if (isset($oneToManyElement->{'index-by'})) {
428 throw new \InvalidArgumentException("<index-by /> is not a valid tag");
431 $metadata->mapOneToMany($mapping);
433 // Evaluate second level cache
434 if (isset($oneToManyElement->cache)) {
435 $metadata->enableAssociationCache($mapping['fieldName'], $this->cacheToArray($oneToManyElement->cache));
440 // Evaluate <many-to-one ...> mappings
441 if (isset($xmlRoot->{'many-to-one'})) {
442 foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
443 $mapping = array(
444 'fieldName' => (string)$manyToOneElement['field'],
445 'targetEntity' => (string)$manyToOneElement['target-entity']
448 if (isset($associationIds[$mapping['fieldName']])) {
449 $mapping['id'] = true;
452 if (isset($manyToOneElement['fetch'])) {
453 $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToOneElement['fetch']);
456 if (isset($manyToOneElement['inversed-by'])) {
457 $mapping['inversedBy'] = (string)$manyToOneElement['inversed-by'];
460 $joinColumns = array();
462 if (isset($manyToOneElement->{'join-column'})) {
463 $joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'});
464 } else if (isset($manyToOneElement->{'join-columns'})) {
465 foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
466 $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
470 $mapping['joinColumns'] = $joinColumns;
472 if (isset($manyToOneElement->cascade)) {
473 $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade);
476 $metadata->mapManyToOne($mapping);
478 // Evaluate second level cache
479 if (isset($manyToOneElement->cache)) {
480 $metadata->enableAssociationCache($mapping['fieldName'], $this->cacheToArray($manyToOneElement->cache));
485 // Evaluate <many-to-many ...> mappings
486 if (isset($xmlRoot->{'many-to-many'})) {
487 foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
488 $mapping = array(
489 'fieldName' => (string)$manyToManyElement['field'],
490 'targetEntity' => (string)$manyToManyElement['target-entity']
493 if (isset($manyToManyElement['fetch'])) {
494 $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToManyElement['fetch']);
497 if (isset($manyToManyElement['orphan-removal'])) {
498 $mapping['orphanRemoval'] = $this->evaluateBoolean($manyToManyElement['orphan-removal']);
501 if (isset($manyToManyElement['mapped-by'])) {
502 $mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
503 } else if (isset($manyToManyElement->{'join-table'})) {
504 if (isset($manyToManyElement['inversed-by'])) {
505 $mapping['inversedBy'] = (string)$manyToManyElement['inversed-by'];
508 $joinTableElement = $manyToManyElement->{'join-table'};
509 $joinTable = array(
510 'name' => (string)$joinTableElement['name']
513 if (isset($joinTableElement['schema'])) {
514 $joinTable['schema'] = (string)$joinTableElement['schema'];
517 foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
518 $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
521 foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
522 $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
525 $mapping['joinTable'] = $joinTable;
528 if (isset($manyToManyElement->cascade)) {
529 $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade);
532 if (isset($manyToManyElement->{'order-by'})) {
533 $orderBy = array();
534 foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
535 $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
537 $mapping['orderBy'] = $orderBy;
540 if (isset($manyToManyElement['index-by'])) {
541 $mapping['indexBy'] = (string)$manyToManyElement['index-by'];
542 } else if (isset($manyToManyElement->{'index-by'})) {
543 throw new \InvalidArgumentException("<index-by /> is not a valid tag");
546 $metadata->mapManyToMany($mapping);
548 // Evaluate second level cache
549 if (isset($manyToManyElement->cache)) {
550 $metadata->enableAssociationCache($mapping['fieldName'], $this->cacheToArray($manyToManyElement->cache));
555 // Evaluate association-overrides
556 if (isset($xmlRoot->{'attribute-overrides'})) {
557 foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) {
558 $fieldName = (string) $overrideElement['name'];
559 foreach ($overrideElement->field as $field) {
560 $mapping = $this->columnToArray($field);
561 $mapping['fieldName'] = $fieldName;
562 $metadata->setAttributeOverride($fieldName, $mapping);
567 // Evaluate association-overrides
568 if (isset($xmlRoot->{'association-overrides'})) {
569 foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) {
570 $fieldName = (string) $overrideElement['name'];
571 $override = array();
573 // Check for join-columns
574 if (isset($overrideElement->{'join-columns'})) {
575 $joinColumns = array();
576 foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
577 $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
579 $override['joinColumns'] = $joinColumns;
582 // Check for join-table
583 if ($overrideElement->{'join-table'}) {
584 $joinTable = null;
585 $joinTableElement = $overrideElement->{'join-table'};
587 $joinTable = array(
588 'name' => (string) $joinTableElement['name'],
589 'schema' => (string) $joinTableElement['schema']
592 if (isset($joinTableElement->{'join-columns'})) {
593 foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
594 $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
598 if (isset($joinTableElement->{'inverse-join-columns'})) {
599 foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
600 $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
604 $override['joinTable'] = $joinTable;
607 $metadata->setAssociationOverride($fieldName, $override);
611 // Evaluate <lifecycle-callbacks...>
612 if (isset($xmlRoot->{'lifecycle-callbacks'})) {
613 foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) {
614 $metadata->addLifecycleCallback((string)$lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string)$lifecycleCallback['type']));
618 // Evaluate entity listener
619 if (isset($xmlRoot->{'entity-listeners'})) {
620 foreach ($xmlRoot->{'entity-listeners'}->{'entity-listener'} as $listenerElement) {
621 $className = (string) $listenerElement['class'];
622 // Evaluate the listener using naming convention.
623 if($listenerElement->count() === 0) {
624 EntityListenerBuilder::bindEntityListener($metadata, $className);
626 continue;
629 foreach ($listenerElement as $callbackElement) {
630 $eventName = (string) $callbackElement['type'];
631 $methodName = (string) $callbackElement['method'];
633 $metadata->addEntityListener($eventName, $className, $methodName);
640 * Parses (nested) option elements.
642 * @param SimpleXMLElement $options The XML element.
644 * @return array The options array.
646 private function _parseOptions(SimpleXMLElement $options)
648 $array = array();
650 /* @var $option SimpleXMLElement */
651 foreach ($options as $option) {
652 if ($option->count()) {
653 $value = $this->_parseOptions($option->children());
654 } else {
655 $value = (string) $option;
658 $attr = $option->attributes();
660 if (isset($attr->name)) {
661 $array[(string) $attr->name] = $value;
662 } else {
663 $array[] = $value;
667 return $array;
671 * Constructs a joinColumn mapping array based on the information
672 * found in the given SimpleXMLElement.
674 * @param SimpleXMLElement $joinColumnElement The XML element.
676 * @return array The mapping array.
678 private function joinColumnToArray(SimpleXMLElement $joinColumnElement)
680 $joinColumn = array(
681 'name' => (string)$joinColumnElement['name'],
682 'referencedColumnName' => (string)$joinColumnElement['referenced-column-name']
685 if (isset($joinColumnElement['unique'])) {
686 $joinColumn['unique'] = $this->evaluateBoolean($joinColumnElement['unique']);
689 if (isset($joinColumnElement['nullable'])) {
690 $joinColumn['nullable'] = $this->evaluateBoolean($joinColumnElement['nullable']);
693 if (isset($joinColumnElement['on-delete'])) {
694 $joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
697 if (isset($joinColumnElement['column-definition'])) {
698 $joinColumn['columnDefinition'] = (string)$joinColumnElement['column-definition'];
701 return $joinColumn;
705 * Parses the given field as array.
707 * @param SimpleXMLElement $fieldMapping
709 * @return array
711 private function columnToArray(SimpleXMLElement $fieldMapping)
713 $mapping = array(
714 'fieldName' => (string) $fieldMapping['name'],
717 if (isset($fieldMapping['type'])) {
718 $mapping['type'] = (string) $fieldMapping['type'];
721 if (isset($fieldMapping['column'])) {
722 $mapping['columnName'] = (string) $fieldMapping['column'];
725 if (isset($fieldMapping['length'])) {
726 $mapping['length'] = (int) $fieldMapping['length'];
729 if (isset($fieldMapping['precision'])) {
730 $mapping['precision'] = (int) $fieldMapping['precision'];
733 if (isset($fieldMapping['scale'])) {
734 $mapping['scale'] = (int) $fieldMapping['scale'];
737 if (isset($fieldMapping['unique'])) {
738 $mapping['unique'] = $this->evaluateBoolean($fieldMapping['unique']);
741 if (isset($fieldMapping['nullable'])) {
742 $mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']);
745 if (isset($fieldMapping['version']) && $fieldMapping['version']) {
746 $mapping['version'] = $this->evaluateBoolean($fieldMapping['version']);
749 if (isset($fieldMapping['column-definition'])) {
750 $mapping['columnDefinition'] = (string) $fieldMapping['column-definition'];
753 if (isset($fieldMapping->options)) {
754 $mapping['options'] = $this->_parseOptions($fieldMapping->options->children());
757 return $mapping;
761 * Parse / Normalize the cache configuration
763 * @param SimpleXMLElement $cacheMapping
765 * @return array
767 private function cacheToArray(SimpleXMLElement $cacheMapping)
769 $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null;
770 $usage = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null;
772 if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) {
773 throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage));
776 if ($usage) {
777 $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage);
780 return array(
781 'usage' => $usage,
782 'region' => $region,
787 * Gathers a list of cascade options found in the given cascade element.
789 * @param SimpleXMLElement $cascadeElement The cascade element.
791 * @return array The list of cascade options.
793 private function _getCascadeMappings(SimpleXMLElement $cascadeElement)
795 $cascades = array();
796 /* @var $action SimpleXmlElement */
797 foreach ($cascadeElement->children() as $action) {
798 // According to the JPA specifications, XML uses "cascade-persist"
799 // instead of "persist". Here, both variations
800 // are supported because both YAML and Annotation use "persist"
801 // and we want to make sure that this driver doesn't need to know
802 // anything about the supported cascading actions
803 $cascades[] = str_replace('cascade-', '', $action->getName());
805 return $cascades;
809 * {@inheritDoc}
811 protected function loadMappingFile($file)
813 $result = array();
814 // Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577
815 $xmlElement = simplexml_load_string(file_get_contents($file));
817 if (isset($xmlElement->entity)) {
818 foreach ($xmlElement->entity as $entityElement) {
819 $entityName = (string)$entityElement['name'];
820 $result[$entityName] = $entityElement;
822 } else if (isset($xmlElement->{'mapped-superclass'})) {
823 foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) {
824 $className = (string)$mappedSuperClass['name'];
825 $result[$className] = $mappedSuperClass;
827 } else if (isset($xmlElement->embeddable)) {
828 foreach ($xmlElement->embeddable as $embeddableElement) {
829 $embeddableName = (string) $embeddableElement['name'];
830 $result[$embeddableName] = $embeddableElement;
834 return $result;
838 * @param mixed $element
840 * @return bool
842 protected function evaluateBoolean($element)
844 $flag = (string)$element;
846 return ($flag == "true" || $flag == "1");