Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Mapping / Driver / XmlDriver.php
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.
14  *
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>.
18  */
19
20 namespace Doctrine\ORM\Mapping\Driver;
21
22 use SimpleXMLElement,
23     Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
24     Doctrine\Common\Persistence\Mapping\ClassMetadata,
25     Doctrine\ORM\Mapping\MappingException;
26
27 /**
28  * XmlDriver is a metadata driver that enables mapping through XML files.
29  *
30  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
31  * @link        www.doctrine-project.org
32  * @since       2.0
33  * @author              Benjamin Eberlei <kontakt@beberlei.de>
34  * @author              Guilherme Blanco <guilhermeblanco@hotmail.com>
35  * @author      Jonathan H. Wage <jonwage@gmail.com>
36  * @author      Roman Borschel <roman@code-factory.org>
37  */
38 class XmlDriver extends FileDriver
39 {
40     const DEFAULT_FILE_EXTENSION = '.dcm.xml';
41
42     /**
43      * {@inheritDoc}
44      */
45     public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
46     {
47         parent::__construct($locator, $fileExtension);
48     }
49
50     /**
51      * {@inheritDoc}
52      */
53     public function loadMetadataForClass($className, ClassMetadata $metadata)
54     {
55         /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
56         /* @var $xmlRoot SimpleXMLElement */
57         $xmlRoot = $this->getElement($className);
58
59         if ($xmlRoot->getName() == 'entity') {
60             if (isset($xmlRoot['repository-class'])) {
61                 $metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
62             }
63             if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
64                 $metadata->markReadOnly();
65             }
66         } else if ($xmlRoot->getName() == 'mapped-superclass') {
67             $metadata->setCustomRepositoryClass(
68                 isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
69             );
70             $metadata->isMappedSuperclass = true;
71         } else {
72             throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
73         }
74
75         // Evaluate <entity...> attributes
76         $table = array();
77         if (isset($xmlRoot['table'])) {
78             $table['name'] = (string)$xmlRoot['table'];
79         }
80
81         $metadata->setPrimaryTable($table);
82
83         // Evaluate named queries
84         if (isset($xmlRoot->{'named-queries'})) {
85             foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) {
86                 $metadata->addNamedQuery(array(
87                     'name'  => (string)$namedQueryElement['name'],
88                     'query' => (string)$namedQueryElement['query']
89                 ));
90             }
91         }
92
93         // Evaluate native named queries
94         if (isset($xmlRoot->{'named-native-queries'})) {
95             foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) {
96                 $metadata->addNamedNativeQuery(array(
97                     'name'              => isset($nativeQueryElement['name']) ? (string)$nativeQueryElement['name'] : null,
98                     'query'             => isset($nativeQueryElement->query) ? (string)$nativeQueryElement->query : null,
99                     'resultClass'       => isset($nativeQueryElement['result-class']) ? (string)$nativeQueryElement['result-class'] : null,
100                     'resultSetMapping'  => isset($nativeQueryElement['result-set-mapping']) ? (string)$nativeQueryElement['result-set-mapping'] : null,
101                 ));
102             }
103         }
104
105         // Evaluate sql result set mapping
106         if (isset($xmlRoot->{'sql-result-set-mappings'})) {
107             foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) {
108                 $entities   = array();
109                 $columns    = array();
110                 foreach ($rsmElement as $entityElement) {
111                     //<entity-result/>
112                     if (isset($entityElement['entity-class'])) {
113                         $entityResult = array(
114                             'fields'                => array(),
115                             'entityClass'           => (string)$entityElement['entity-class'],
116                             'discriminatorColumn'   => isset($entityElement['discriminator-column']) ? (string)$entityElement['discriminator-column'] : null,
117                         );
118
119                         foreach ($entityElement as $fieldElement) {
120                             $entityResult['fields'][] = array(
121                                 'name'      => isset($fieldElement['name']) ? (string)$fieldElement['name'] : null,
122                                 'column'    => isset($fieldElement['column']) ? (string)$fieldElement['column'] : null,
123                             );
124                         }
125
126                         $entities[] = $entityResult;
127                     }
128
129                     //<column-result/>
130                     if (isset($entityElement['name'])) {
131                         $columns[] = array(
132                             'name' => (string)$entityElement['name'],
133                         );
134                     }
135                 }
136
137                 $metadata->addSqlResultSetMapping(array(
138                     'name'          => (string)$rsmElement['name'],
139                     'entities'      => $entities,
140                     'columns'       => $columns
141                 ));
142             }
143         }
144
145         /* not implemented specially anyway. use table = schema.table
146         if (isset($xmlRoot['schema'])) {
147             $metadata->table['schema'] = (string)$xmlRoot['schema'];
148         }*/
149
150         if (isset($xmlRoot['inheritance-type'])) {
151             $inheritanceType = (string)$xmlRoot['inheritance-type'];
152             $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
153
154             if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
155                 // Evaluate <discriminator-column...>
156                 if (isset($xmlRoot->{'discriminator-column'})) {
157                     $discrColumn = $xmlRoot->{'discriminator-column'};
158                     $metadata->setDiscriminatorColumn(array(
159                         'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null,
160                         'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : null,
161                         'length' => isset($discrColumn['length']) ? (string)$discrColumn['length'] : null,
162                         'columnDefinition' => isset($discrColumn['column-definition']) ? (string)$discrColumn['column-definition'] : null
163                     ));
164                 } else {
165                     $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
166                 }
167
168                 // Evaluate <discriminator-map...>
169                 if (isset($xmlRoot->{'discriminator-map'})) {
170                     $map = array();
171                     foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) {
172                         $map[(string)$discrMapElement['value']] = (string)$discrMapElement['class'];
173                     }
174                     $metadata->setDiscriminatorMap($map);
175                 }
176             }
177         }
178
179
180         // Evaluate <change-tracking-policy...>
181         if (isset($xmlRoot['change-tracking-policy'])) {
182             $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
183                     . strtoupper((string)$xmlRoot['change-tracking-policy'])));
184         }
185
186         // Evaluate <indexes...>
187         if (isset($xmlRoot->indexes)) {
188             $metadata->table['indexes'] = array();
189             foreach ($xmlRoot->indexes->index as $index) {
190                 $columns = explode(',', (string)$index['columns']);
191
192                 if (isset($index['name'])) {
193                     $metadata->table['indexes'][(string)$index['name']] = array(
194                         'columns' => $columns
195                     );
196                 } else {
197                     $metadata->table['indexes'][] = array(
198                         'columns' => $columns
199                     );
200                 }
201             }
202         }
203
204         // Evaluate <unique-constraints..>
205         if (isset($xmlRoot->{'unique-constraints'})) {
206             $metadata->table['uniqueConstraints'] = array();
207             foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $unique) {
208                 $columns = explode(',', (string)$unique['columns']);
209
210                 if (isset($unique['name'])) {
211                     $metadata->table['uniqueConstraints'][(string)$unique['name']] = array(
212                         'columns' => $columns
213                     );
214                 } else {
215                     $metadata->table['uniqueConstraints'][] = array(
216                         'columns' => $columns
217                     );
218                 }
219             }
220         }
221
222         if (isset($xmlRoot->options)) {
223             $metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children());
224         }
225
226         // The mapping assignement is done in 2 times as a bug might occurs on some php/xml lib versions
227         // The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception
228         $mappings = array();
229         // Evaluate <field ...> mappings
230         if (isset($xmlRoot->field)) {
231             foreach ($xmlRoot->field as $fieldMapping) {
232                 $mapping = $this->columnToArray($fieldMapping);
233                 $metadata->mapField($mapping);
234             }
235         }
236
237         foreach ($mappings as $mapping) {
238              $metadata->mapField($mapping);
239         }
240
241         // Evaluate <id ...> mappings
242         $associationIds = array();
243         foreach ($xmlRoot->id as $idElement) {
244             if ((bool)$idElement['association-key'] == true) {
245                 $associationIds[(string)$idElement['name']] = true;
246                 continue;
247             }
248
249             $mapping = array(
250                 'id' => true,
251                 'fieldName' => (string)$idElement['name']
252             );
253
254             if (isset($idElement['type'])) {
255                 $mapping['type'] = (string)$idElement['type'];
256             }
257
258             if (isset($idElement['length'])) {
259                 $mapping['length'] = (string)$idElement['length'];
260             }
261
262             if (isset($idElement['column'])) {
263                 $mapping['columnName'] = (string)$idElement['column'];
264             }
265
266             if (isset($idElement['column-definition'])) {
267                 $mapping['columnDefinition'] = (string)$idElement['column-definition'];
268             }
269
270             $metadata->mapField($mapping);
271
272             if (isset($idElement->generator)) {
273                 $strategy = isset($idElement->generator['strategy']) ?
274                         (string)$idElement->generator['strategy'] : 'AUTO';
275                 $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
276                         . $strategy));
277             }
278
279             // Check for SequenceGenerator/TableGenerator definition
280             if (isset($idElement->{'sequence-generator'})) {
281                 $seqGenerator = $idElement->{'sequence-generator'};
282                 $metadata->setSequenceGeneratorDefinition(array(
283                     'sequenceName' => (string)$seqGenerator['sequence-name'],
284                     'allocationSize' => (string)$seqGenerator['allocation-size'],
285                     'initialValue' => (string)$seqGenerator['initial-value']
286                 ));
287             } else if (isset($idElement->{'custom-id-generator'})) {
288                 $customGenerator = $idElement->{'custom-id-generator'};
289                 $metadata->setCustomGeneratorDefinition(array(
290                     'class' => (string) $customGenerator['class']
291                 ));
292             } else if (isset($idElement->{'table-generator'})) {
293                 throw MappingException::tableIdGeneratorNotImplemented($className);
294             }
295         }
296
297         // Evaluate <one-to-one ...> mappings
298         if (isset($xmlRoot->{'one-to-one'})) {
299             foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
300                 $mapping = array(
301                     'fieldName' => (string)$oneToOneElement['field'],
302                     'targetEntity' => (string)$oneToOneElement['target-entity']
303                 );
304
305                 if (isset($associationIds[$mapping['fieldName']])) {
306                     $mapping['id'] = true;
307                 }
308
309                 if (isset($oneToOneElement['fetch'])) {
310                     $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToOneElement['fetch']);
311                 }
312
313                 if (isset($oneToOneElement['mapped-by'])) {
314                     $mapping['mappedBy'] = (string)$oneToOneElement['mapped-by'];
315                 } else {
316                     if (isset($oneToOneElement['inversed-by'])) {
317                         $mapping['inversedBy'] = (string)$oneToOneElement['inversed-by'];
318                     }
319                     $joinColumns = array();
320
321                     if (isset($oneToOneElement->{'join-column'})) {
322                         $joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'});
323                     } else if (isset($oneToOneElement->{'join-columns'})) {
324                         foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
325                             $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
326                         }
327                     }
328
329                     $mapping['joinColumns'] = $joinColumns;
330                 }
331
332                 if (isset($oneToOneElement->cascade)) {
333                     $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade);
334                 }
335
336                 if (isset($oneToOneElement['orphan-removal'])) {
337                     $mapping['orphanRemoval'] = (bool)$oneToOneElement['orphan-removal'];
338                 }
339
340                 $metadata->mapOneToOne($mapping);
341             }
342         }
343
344         // Evaluate <one-to-many ...> mappings
345         if (isset($xmlRoot->{'one-to-many'})) {
346             foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
347                 $mapping = array(
348                     'fieldName' => (string)$oneToManyElement['field'],
349                     'targetEntity' => (string)$oneToManyElement['target-entity'],
350                     'mappedBy' => (string)$oneToManyElement['mapped-by']
351                 );
352
353                 if (isset($oneToManyElement['fetch'])) {
354                     $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToManyElement['fetch']);
355                 }
356
357                 if (isset($oneToManyElement->cascade)) {
358                     $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
359                 }
360
361                 if (isset($oneToManyElement['orphan-removal'])) {
362                     $mapping['orphanRemoval'] = (bool)$oneToManyElement['orphan-removal'];
363                 }
364
365                 if (isset($oneToManyElement->{'order-by'})) {
366                     $orderBy = array();
367                     foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
368                         $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
369                     }
370                     $mapping['orderBy'] = $orderBy;
371                 }
372
373                 if (isset($oneToManyElement['index-by'])) {
374                     $mapping['indexBy'] = (string)$oneToManyElement['index-by'];
375                 } else if (isset($oneToManyElement->{'index-by'})) {
376                     throw new \InvalidArgumentException("<index-by /> is not a valid tag");
377                 }
378
379                 $metadata->mapOneToMany($mapping);
380             }
381         }
382
383         // Evaluate <many-to-one ...> mappings
384         if (isset($xmlRoot->{'many-to-one'})) {
385             foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
386                 $mapping = array(
387                     'fieldName' => (string)$manyToOneElement['field'],
388                     'targetEntity' => (string)$manyToOneElement['target-entity']
389                 );
390
391                 if (isset($associationIds[$mapping['fieldName']])) {
392                     $mapping['id'] = true;
393                 }
394
395                 if (isset($manyToOneElement['fetch'])) {
396                     $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToOneElement['fetch']);
397                 }
398
399                 if (isset($manyToOneElement['inversed-by'])) {
400                     $mapping['inversedBy'] = (string)$manyToOneElement['inversed-by'];
401                 }
402
403                 $joinColumns = array();
404
405                 if (isset($manyToOneElement->{'join-column'})) {
406                     $joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'});
407                 } else if (isset($manyToOneElement->{'join-columns'})) {
408                     foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
409                         $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
410                     }
411                 }
412
413                 $mapping['joinColumns'] = $joinColumns;
414
415                 if (isset($manyToOneElement->cascade)) {
416                     $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade);
417                 }
418
419                 $metadata->mapManyToOne($mapping);
420             }
421         }
422
423         // Evaluate <many-to-many ...> mappings
424         if (isset($xmlRoot->{'many-to-many'})) {
425             foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
426                 $mapping = array(
427                     'fieldName' => (string)$manyToManyElement['field'],
428                     'targetEntity' => (string)$manyToManyElement['target-entity']
429                 );
430
431                 if (isset($manyToManyElement['fetch'])) {
432                     $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToManyElement['fetch']);
433                 }
434
435                 if (isset($manyToManyElement['orphan-removal'])) {
436                     $mapping['orphanRemoval'] = (bool)$manyToManyElement['orphan-removal'];
437                 }
438
439                 if (isset($manyToManyElement['mapped-by'])) {
440                     $mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
441                 } else if (isset($manyToManyElement->{'join-table'})) {
442                     if (isset($manyToManyElement['inversed-by'])) {
443                         $mapping['inversedBy'] = (string)$manyToManyElement['inversed-by'];
444                     }
445
446                     $joinTableElement = $manyToManyElement->{'join-table'};
447                     $joinTable = array(
448                         'name' => (string)$joinTableElement['name']
449                     );
450
451                     if (isset($joinTableElement['schema'])) {
452                         $joinTable['schema'] = (string)$joinTableElement['schema'];
453                     }
454
455                     foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
456                         $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
457                     }
458
459                     foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
460                         $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
461                     }
462
463                     $mapping['joinTable'] = $joinTable;
464                 }
465
466                 if (isset($manyToManyElement->cascade)) {
467                     $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade);
468                 }
469
470                 if (isset($manyToManyElement->{'order-by'})) {
471                     $orderBy = array();
472                     foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
473                         $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
474                     }
475                     $mapping['orderBy'] = $orderBy;
476                 }
477
478                 if (isset($manyToManyElement['index-by'])) {
479                     $mapping['indexBy'] = (string)$manyToManyElement['index-by'];
480                 } else if (isset($manyToManyElement->{'index-by'})) {
481                     throw new \InvalidArgumentException("<index-by /> is not a valid tag");
482                 }
483
484                 $metadata->mapManyToMany($mapping);
485             }
486         }
487
488         // Evaluate association-overrides
489         if (isset($xmlRoot->{'attribute-overrides'})) {
490             foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) {
491                 $fieldName = (string) $overrideElement['name'];
492                 foreach ($overrideElement->field as $field) {
493                     $mapping = $this->columnToArray($field);
494                     $mapping['fieldName'] = $fieldName;
495                     $metadata->setAttributeOverride($fieldName, $mapping);
496                 }
497             }
498         }
499
500         // Evaluate association-overrides
501         if (isset($xmlRoot->{'association-overrides'})) {
502             foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) {
503                 $fieldName  = (string) $overrideElement['name'];
504                 $override   = array();
505
506                 // Check for join-columns
507                 if (isset($overrideElement->{'join-columns'})) {
508                     $joinColumns = array();
509                     foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
510                         $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
511                     }
512                     $override['joinColumns'] = $joinColumns;
513                 }
514
515                 // Check for join-table
516                 if ($overrideElement->{'join-table'}) {
517                     $joinTable          = null;
518                     $joinTableElement   = $overrideElement->{'join-table'};
519
520                     $joinTable = array(
521                         'name'      => (string) $joinTableElement['name'],
522                         'schema'    => (string) $joinTableElement['schema']
523                     );
524
525                     if (isset($joinTableElement->{'join-columns'})) {
526                         foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
527                             $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
528                         }
529                     }
530
531                     if (isset($joinTableElement->{'inverse-join-columns'})) {
532                         foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
533                             $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
534                         }
535                     }
536
537                     $override['joinTable'] = $joinTable;
538                 }
539
540                 $metadata->setAssociationOverride($fieldName, $override);
541             }
542         }
543
544         // Evaluate <lifecycle-callbacks...>
545         if (isset($xmlRoot->{'lifecycle-callbacks'})) {
546             foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) {
547                 $metadata->addLifecycleCallback((string)$lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string)$lifecycleCallback['type']));
548             }
549         }
550     }
551
552     /**
553      * Parses (nested) option elements.
554      *
555      * @param SimpleXMLElement $options the XML element.
556      * @return array The options array.
557      */
558     private function _parseOptions(SimpleXMLElement $options)
559     {
560         $array = array();
561
562         /* @var $option SimpleXMLElement */
563         foreach ($options as $option) {
564             if ($option->count()) {
565                 $value = $this->_parseOptions($option->children());
566             } else {
567                 $value = (string) $option;
568             }
569
570             $attr = $option->attributes();
571
572             if (isset($attr->name)) {
573                 $array[(string) $attr->name] = $value;
574             } else {
575                 $array[] = $value;
576             }
577         }
578
579         return $array;
580     }
581
582     /**
583      * Constructs a joinColumn mapping array based on the information
584      * found in the given SimpleXMLElement.
585      *
586      * @param SimpleXMLElement $joinColumnElement the XML element.
587      * @return array The mapping array.
588      */
589     private function joinColumnToArray(SimpleXMLElement $joinColumnElement)
590     {
591         $joinColumn = array(
592             'name' => (string)$joinColumnElement['name'],
593             'referencedColumnName' => (string)$joinColumnElement['referenced-column-name']
594         );
595
596         if (isset($joinColumnElement['unique'])) {
597             $joinColumn['unique'] = ((string)$joinColumnElement['unique'] == "false") ? false : true;
598         }
599
600         if (isset($joinColumnElement['nullable'])) {
601             $joinColumn['nullable'] = ((string)$joinColumnElement['nullable'] == "false") ? false : true;
602         }
603
604         if (isset($joinColumnElement['on-delete'])) {
605             $joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
606         }
607
608         if (isset($joinColumnElement['column-definition'])) {
609             $joinColumn['columnDefinition'] = (string)$joinColumnElement['column-definition'];
610         }
611
612         return $joinColumn;
613     }
614
615      /**
616      * Parse the given field as array
617      *
618      * @param   SimpleXMLElement   $fieldMapping
619      * @return  array
620      */
621     private function columnToArray(SimpleXMLElement $fieldMapping)
622     {
623         $mapping = array(
624             'fieldName' => (string) $fieldMapping['name'],
625         );
626
627         if (isset($fieldMapping['type'])) {
628             $mapping['type'] = (string) $fieldMapping['type'];
629         }
630
631         if (isset($fieldMapping['column'])) {
632             $mapping['columnName'] = (string) $fieldMapping['column'];
633         }
634
635         if (isset($fieldMapping['length'])) {
636             $mapping['length'] = (int) $fieldMapping['length'];
637         }
638
639         if (isset($fieldMapping['precision'])) {
640             $mapping['precision'] = (int) $fieldMapping['precision'];
641         }
642
643         if (isset($fieldMapping['scale'])) {
644             $mapping['scale'] = (int) $fieldMapping['scale'];
645         }
646
647         if (isset($fieldMapping['unique'])) {
648             $mapping['unique'] = ((string) $fieldMapping['unique'] == "false") ? false : true;
649         }
650
651         if (isset($fieldMapping['nullable'])) {
652             $mapping['nullable'] = ((string) $fieldMapping['nullable'] == "false") ? false : true;
653         }
654
655         if (isset($fieldMapping['version']) && $fieldMapping['version']) {
656             $mapping['version'] = $fieldMapping['version'];
657         }
658
659         if (isset($fieldMapping['column-definition'])) {
660             $mapping['columnDefinition'] = (string) $fieldMapping['column-definition'];
661         }
662
663         if (isset($fieldMapping->options)) {
664             $mapping['options'] = $this->_parseOptions($fieldMapping->options->children());
665         }
666
667         return $mapping;
668     }
669
670     /**
671      * Gathers a list of cascade options found in the given cascade element.
672      *
673      * @param SimpleXMLElement $cascadeElement the cascade element.
674      * @return array The list of cascade options.
675      */
676     private function _getCascadeMappings($cascadeElement)
677     {
678         $cascades = array();
679         /* @var $action SimpleXmlElement */
680         foreach ($cascadeElement->children() as $action) {
681             // According to the JPA specifications, XML uses "cascade-persist"
682             // instead of "persist". Here, both variations
683             // are supported because both YAML and Annotation use "persist"
684             // and we want to make sure that this driver doesn't need to know
685             // anything about the supported cascading actions
686             $cascades[] = str_replace('cascade-', '', $action->getName());
687         }
688         return $cascades;
689     }
690
691     /**
692      * {@inheritDoc}
693      */
694     protected function loadMappingFile($file)
695     {
696         $result = array();
697         $xmlElement = simplexml_load_file($file);
698
699         if (isset($xmlElement->entity)) {
700             foreach ($xmlElement->entity as $entityElement) {
701                 $entityName = (string)$entityElement['name'];
702                 $result[$entityName] = $entityElement;
703             }
704         } else if (isset($xmlElement->{'mapped-superclass'})) {
705             foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) {
706                 $className = (string)$mappedSuperClass['name'];
707                 $result[$className] = $mappedSuperClass;
708             }
709         }
710
711         return $result;
712     }
713 }