source: pro-violet-viettel/sourcecode/application/libraries/Doctrine/ORM/Mapping/Driver/XmlDriver.php @ 345

Last change on this file since 345 was 345, checked in by quyenla, 11 years ago

collaborator page

File size: 21.8 KB
Line 
1<?php
2/*
3 *  $Id$
4 *
5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 *
17 * This software consists of voluntary contributions made by many individuals
18 * and is licensed under the LGPL. For more information, see
19 * <http://www.doctrine-project.org>.
20 */
21
22namespace Doctrine\ORM\Mapping\Driver;
23
24use SimpleXMLElement,
25    Doctrine\ORM\Mapping\ClassMetadataInfo,
26    Doctrine\ORM\Mapping\MappingException;
27
28/**
29 * XmlDriver is a metadata driver that enables mapping through XML files.
30 *
31 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
32 * @link        www.doctrine-project.org
33 * @since       2.0
34 * @version     $Revision$
35 * @author              Benjamin Eberlei <kontakt@beberlei.de>
36 * @author              Guilherme Blanco <guilhermeblanco@hotmail.com>
37 * @author      Jonathan H. Wage <jonwage@gmail.com>
38 * @author      Roman Borschel <roman@code-factory.org>
39 */
40class XmlDriver extends AbstractFileDriver
41{
42    /**
43     * {@inheritdoc}
44     */
45    protected $_fileExtension = '.dcm.xml';
46
47    /**
48     * {@inheritdoc}
49     */
50    public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
51    {
52        $xmlRoot = $this->getElement($className);
53
54        if ($xmlRoot->getName() == 'entity') {
55            if (isset($xmlRoot['repository-class'])) {
56                $metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
57            }
58            if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
59                $metadata->markReadOnly();
60            }
61        } else if ($xmlRoot->getName() == 'mapped-superclass') {
62            $metadata->setCustomRepositoryClass(
63                isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
64            );
65            $metadata->isMappedSuperclass = true;
66        } else {
67            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
68        }
69
70        // Evaluate <entity...> attributes
71        $table = array();
72        if (isset($xmlRoot['table'])) {
73            $table['name'] = (string)$xmlRoot['table'];
74        }
75
76        $metadata->setPrimaryTable($table);
77
78        // Evaluate named queries
79        if (isset($xmlRoot['named-queries'])) {
80            foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) {
81                $metadata->addNamedQuery(array(
82                    'name'  => (string)$namedQueryElement['name'],
83                    'query' => (string)$namedQueryElement['query']
84                ));
85            }
86        }
87
88        /* not implemented specially anyway. use table = schema.table
89        if (isset($xmlRoot['schema'])) {
90            $metadata->table['schema'] = (string)$xmlRoot['schema'];
91        }*/
92
93        if (isset($xmlRoot['inheritance-type'])) {
94            $inheritanceType = (string)$xmlRoot['inheritance-type'];
95            $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
96
97            if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
98                // Evaluate <discriminator-column...>
99                if (isset($xmlRoot->{'discriminator-column'})) {
100                    $discrColumn = $xmlRoot->{'discriminator-column'};
101                    $metadata->setDiscriminatorColumn(array(
102                        'name' => (string)$discrColumn['name'],
103                        'type' => (string)$discrColumn['type'],
104                        'length' => (string)$discrColumn['length']
105                    ));
106                } else {
107                    $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
108                }
109
110                // Evaluate <discriminator-map...>
111                if (isset($xmlRoot->{'discriminator-map'})) {
112                    $map = array();
113                    foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} AS $discrMapElement) {
114                        $map[(string)$discrMapElement['value']] = (string)$discrMapElement['class'];
115                    }
116                    $metadata->setDiscriminatorMap($map);
117                }
118            }
119        }
120
121
122        // Evaluate <change-tracking-policy...>
123        if (isset($xmlRoot['change-tracking-policy'])) {
124            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
125                    . strtoupper((string)$xmlRoot['change-tracking-policy'])));
126        }
127
128        // Evaluate <indexes...>
129        if (isset($xmlRoot->indexes)) {
130            $metadata->table['indexes'] = array();
131            foreach ($xmlRoot->indexes->index as $index) {
132                $columns = explode(',', (string)$index['columns']);
133
134                if (isset($index['name'])) {
135                    $metadata->table['indexes'][(string)$index['name']] = array(
136                        'columns' => $columns
137                    );
138                } else {
139                    $metadata->table['indexes'][] = array(
140                        'columns' => $columns
141                    );
142                }
143            }
144        }
145
146        // Evaluate <unique-constraints..>
147        if (isset($xmlRoot->{'unique-constraints'})) {
148            $metadata->table['uniqueConstraints'] = array();
149            foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $unique) {
150                $columns = explode(',', (string)$unique['columns']);
151
152                if (isset($unique['name'])) {
153                    $metadata->table['uniqueConstraints'][(string)$unique['name']] = array(
154                        'columns' => $columns
155                    );
156                } else {
157                    $metadata->table['uniqueConstraints'][] = array(
158                        'columns' => $columns
159                    );
160                }
161            }
162        }
163
164        // Evaluate <field ...> mappings
165        if (isset($xmlRoot->field)) {
166            foreach ($xmlRoot->field as $fieldMapping) {
167                $mapping = array(
168                    'fieldName' => (string)$fieldMapping['name'],
169                );
170
171                if (isset($fieldMapping['type'])) {
172                    $mapping['type'] = (string)$fieldMapping['type'];
173                }
174
175                if (isset($fieldMapping['column'])) {
176                    $mapping['columnName'] = (string)$fieldMapping['column'];
177                }
178
179                if (isset($fieldMapping['length'])) {
180                    $mapping['length'] = (int)$fieldMapping['length'];
181                }
182
183                if (isset($fieldMapping['precision'])) {
184                    $mapping['precision'] = (int)$fieldMapping['precision'];
185                }
186
187                if (isset($fieldMapping['scale'])) {
188                    $mapping['scale'] = (int)$fieldMapping['scale'];
189                }
190
191                if (isset($fieldMapping['unique'])) {
192                    $mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true;
193                }
194
195                if (isset($fieldMapping['options'])) {
196                    $mapping['options'] = (array)$fieldMapping['options'];
197                }
198
199                if (isset($fieldMapping['nullable'])) {
200                    $mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true;
201                }
202
203                if (isset($fieldMapping['version']) && $fieldMapping['version']) {
204                    $metadata->setVersionMapping($mapping);
205                }
206
207                if (isset($fieldMapping['column-definition'])) {
208                    $mapping['columnDefinition'] = (string)$fieldMapping['column-definition'];
209                }
210
211                $metadata->mapField($mapping);
212            }
213        }
214
215        // Evaluate <id ...> mappings
216        $associationIds = array();
217        foreach ($xmlRoot->id as $idElement) {
218            if ((bool)$idElement['association-key'] == true) {
219                $associationIds[(string)$idElement['name']] = true;
220                continue;
221            }
222
223            $mapping = array(
224                'id' => true,
225                'fieldName' => (string)$idElement['name']
226            );
227
228            if (isset($idElement['type'])) {
229                $mapping['type'] = (string)$idElement['type'];
230            }
231
232            if (isset($idElement['column'])) {
233                $mapping['columnName'] = (string)$idElement['column'];
234            }
235
236            if (isset($idElement['column-definition'])) {
237                $mapping['columnDefinition'] = (string)$idElement['column-definition'];
238            }
239
240            $metadata->mapField($mapping);
241
242            if (isset($idElement->generator)) {
243                $strategy = isset($idElement->generator['strategy']) ?
244                        (string)$idElement->generator['strategy'] : 'AUTO';
245                $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
246                        . $strategy));
247            }
248
249            // Check for SequenceGenerator/TableGenerator definition
250            if (isset($idElement->{'sequence-generator'})) {
251                $seqGenerator = $idElement->{'sequence-generator'};
252                $metadata->setSequenceGeneratorDefinition(array(
253                    'sequenceName' => (string)$seqGenerator['sequence-name'],
254                    'allocationSize' => (string)$seqGenerator['allocation-size'],
255                    'initialValue' => (string)$seqGenerator['initial-value']
256                ));
257            } else if (isset($idElement->{'table-generator'})) {
258                throw MappingException::tableIdGeneratorNotImplemented($className);
259            }
260        }
261
262        // Evaluate <one-to-one ...> mappings
263        if (isset($xmlRoot->{'one-to-one'})) {
264            foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
265                $mapping = array(
266                    'fieldName' => (string)$oneToOneElement['field'],
267                    'targetEntity' => (string)$oneToOneElement['target-entity']
268                );
269
270                if (isset($associationIds[$mapping['fieldName']])) {
271                    $mapping['id'] = true;
272                }
273
274                if (isset($oneToOneElement['fetch'])) {
275                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToOneElement['fetch']);
276                }
277
278                if (isset($oneToOneElement['mapped-by'])) {
279                    $mapping['mappedBy'] = (string)$oneToOneElement['mapped-by'];
280                } else {
281                    if (isset($oneToOneElement['inversed-by'])) {
282                        $mapping['inversedBy'] = (string)$oneToOneElement['inversed-by'];
283                    }
284                    $joinColumns = array();
285
286                    if (isset($oneToOneElement->{'join-column'})) {
287                        $joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement->{'join-column'});
288                    } else if (isset($oneToOneElement->{'join-columns'})) {
289                        foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
290                            $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
291                        }
292                    }
293
294                    $mapping['joinColumns'] = $joinColumns;
295                }
296
297                if (isset($oneToOneElement->cascade)) {
298                    $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade);
299                }
300
301                if (isset($oneToOneElement['orphan-removal'])) {
302                    $mapping['orphanRemoval'] = (bool)$oneToOneElement['orphan-removal'];
303                }
304
305                $metadata->mapOneToOne($mapping);
306            }
307        }
308
309        // Evaluate <one-to-many ...> mappings
310        if (isset($xmlRoot->{'one-to-many'})) {
311            foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
312                $mapping = array(
313                    'fieldName' => (string)$oneToManyElement['field'],
314                    'targetEntity' => (string)$oneToManyElement['target-entity'],
315                    'mappedBy' => (string)$oneToManyElement['mapped-by']
316                );
317
318                if (isset($oneToManyElement['fetch'])) {
319                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToManyElement['fetch']);
320                }
321
322                if (isset($oneToManyElement->cascade)) {
323                    $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
324                }
325
326                if (isset($oneToManyElement['orphan-removal'])) {
327                    $mapping['orphanRemoval'] = (bool)$oneToManyElement['orphan-removal'];
328                }
329
330                if (isset($oneToManyElement->{'order-by'})) {
331                    $orderBy = array();
332                    foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} AS $orderByField) {
333                        $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
334                    }
335                    $mapping['orderBy'] = $orderBy;
336                }
337
338                if (isset($oneToManyElement['index-by'])) {
339                    $mapping['indexBy'] = (string)$oneToManyElement['index-by'];
340                } else if (isset($oneToManyElement->{'index-by'})) {
341                    throw new \InvalidArgumentException("<index-by /> is not a valid tag");
342                }
343
344                $metadata->mapOneToMany($mapping);
345            }
346        }
347
348        // Evaluate <many-to-one ...> mappings
349        if (isset($xmlRoot->{'many-to-one'})) {
350            foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
351                $mapping = array(
352                    'fieldName' => (string)$manyToOneElement['field'],
353                    'targetEntity' => (string)$manyToOneElement['target-entity']
354                );
355
356                if (isset($associationIds[$mapping['fieldName']])) {
357                    $mapping['id'] = true;
358                }
359
360                if (isset($manyToOneElement['fetch'])) {
361                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToOneElement['fetch']);
362                }
363
364                if (isset($manyToOneElement['inversed-by'])) {
365                    $mapping['inversedBy'] = (string)$manyToOneElement['inversed-by'];
366                }
367
368                $joinColumns = array();
369
370                if (isset($manyToOneElement->{'join-column'})) {
371                    $joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'});
372                } else if (isset($manyToOneElement->{'join-columns'})) {
373                    foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
374                        $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
375                    }
376                }
377
378                $mapping['joinColumns'] = $joinColumns;
379
380                if (isset($manyToOneElement->cascade)) {
381                    $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade);
382                }
383
384                $metadata->mapManyToOne($mapping);
385            }
386        }
387
388        // Evaluate <many-to-many ...> mappings
389        if (isset($xmlRoot->{'many-to-many'})) {
390            foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
391                $mapping = array(
392                    'fieldName' => (string)$manyToManyElement['field'],
393                    'targetEntity' => (string)$manyToManyElement['target-entity']
394                );
395
396                if (isset($manyToManyElement['fetch'])) {
397                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToManyElement['fetch']);
398                }
399
400                if (isset($manyToManyElement['orphan-removal'])) {
401                    $mapping['orphanRemoval'] = (bool)$manyToManyElement['orphan-removal'];
402                }
403
404                if (isset($manyToManyElement['mapped-by'])) {
405                    $mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
406                } else if (isset($manyToManyElement->{'join-table'})) {
407                    if (isset($manyToManyElement['inversed-by'])) {
408                        $mapping['inversedBy'] = (string)$manyToManyElement['inversed-by'];
409                    }
410
411                    $joinTableElement = $manyToManyElement->{'join-table'};
412                    $joinTable = array(
413                        'name' => (string)$joinTableElement['name']
414                    );
415
416                    if (isset($joinTableElement['schema'])) {
417                        $joinTable['schema'] = (string)$joinTableElement['schema'];
418                    }
419
420                    foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
421                        $joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
422                    }
423
424                    foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
425                        $joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
426                    }
427
428                    $mapping['joinTable'] = $joinTable;
429                }
430
431                if (isset($manyToManyElement->cascade)) {
432                    $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade);
433                }
434
435                if (isset($manyToManyElement->{'order-by'})) {
436                    $orderBy = array();
437                    foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} AS $orderByField) {
438                        $orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
439                    }
440                    $mapping['orderBy'] = $orderBy;
441                }
442
443                if (isset($manyToManyElement['index-by'])) {
444                    $mapping['indexBy'] = (string)$manyToManyElement['index-by'];
445                } else if (isset($manyToManyElement->{'index-by'})) {
446                    throw new \InvalidArgumentException("<index-by /> is not a valid tag");
447                }
448
449                $metadata->mapManyToMany($mapping);
450            }
451        }
452
453        // Evaluate <lifecycle-callbacks...>
454        if (isset($xmlRoot->{'lifecycle-callbacks'})) {
455            foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) {
456                $metadata->addLifecycleCallback((string)$lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string)$lifecycleCallback['type']));
457            }
458        }
459    }
460
461    /**
462     * Constructs a joinColumn mapping array based on the information
463     * found in the given SimpleXMLElement.
464     *
465     * @param $joinColumnElement The XML element.
466     * @return array The mapping array.
467     */
468    private function _getJoinColumnMapping(SimpleXMLElement $joinColumnElement)
469    {
470        $joinColumn = array(
471            'name' => (string)$joinColumnElement['name'],
472            'referencedColumnName' => (string)$joinColumnElement['referenced-column-name']
473        );
474
475        if (isset($joinColumnElement['unique'])) {
476            $joinColumn['unique'] = ((string)$joinColumnElement['unique'] == "false") ? false : true;
477        }
478
479        if (isset($joinColumnElement['nullable'])) {
480            $joinColumn['nullable'] = ((string)$joinColumnElement['nullable'] == "false") ? false : true;
481        }
482
483        if (isset($joinColumnElement['on-delete'])) {
484            $joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
485        }
486
487        if (isset($joinColumnElement['column-definition'])) {
488            $joinColumn['columnDefinition'] = (string)$joinColumnElement['column-definition'];
489        }
490
491        return $joinColumn;
492    }
493
494    /**
495     * Gathers a list of cascade options found in the given cascade element.
496     *
497     * @param $cascadeElement The cascade element.
498     * @return array The list of cascade options.
499     */
500    private function _getCascadeMappings($cascadeElement)
501    {
502        $cascades = array();
503        foreach ($cascadeElement->children() as $action) {
504            // According to the JPA specifications, XML uses "cascade-persist"
505            // instead of "persist". Here, both variations
506            // are supported because both YAML and Annotation use "persist"
507            // and we want to make sure that this driver doesn't need to know
508            // anything about the supported cascading actions
509            $cascades[] = str_replace('cascade-', '', $action->getName());
510        }
511        return $cascades;
512    }
513
514    /**
515     * {@inheritdoc}
516     */
517    protected function _loadMappingFile($file)
518    {
519        $result = array();
520        $xmlElement = simplexml_load_file($file);
521
522        if (isset($xmlElement->entity)) {
523            foreach ($xmlElement->entity as $entityElement) {
524                $entityName = (string)$entityElement['name'];
525                $result[$entityName] = $entityElement;
526            }
527        } else if (isset($xmlElement->{'mapped-superclass'})) {
528            foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) {
529                $className = (string)$mappedSuperClass['name'];
530                $result[$className] = $mappedSuperClass;
531            }
532        }
533
534        return $result;
535    }
536}
Note: See TracBrowser for help on using the repository browser.