Completed
Push — master ( 707688...6da863 )
by Mike
04:47 queued 02:08
created

Doctrine/ODM/CouchDB/Mapping/Driver/XmlDriver.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\ODM\CouchDB\Mapping\Driver;
21
22
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
23
    Doctrine\Common\Persistence\Mapping\ClassMetadata,
24
    Doctrine\ODM\CouchDB\Mapping\MappingException,
25
    Doctrine\Common\Persistence\Mapping\MappingException as DoctrineMappingException,
26
    SimpleXmlElement;
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       1.0
34
 * @author      Benjamin Eberlei <[email protected]>
35
 * @author      Jonathan H. Wage <[email protected]>
36
 * @author      Roman Borschel <[email protected]>
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 $class)
54
    {
55
        /** @var $class \Doctrine\ODM\CouchDB\Mapping\ClassMetadata */
56
        try {
57
            $xmlRoot = $this->getElement($className);
58
        } catch (DoctrineMappingException $e) {
59
            // Convert Exception type for consistency with other drivers
60
            throw new MappingException($e->getMessage(), $e->getCode(), $e);
61
        }
62
63
        if (!$xmlRoot) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $xmlRoot of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
64
            return;
65
        }
66
67
        if ($xmlRoot->getName() == 'document') {
68
            $class->setCustomRepositoryClass(
69
                isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
70
            );
71
72
            if (isset($xmlRoot['indexed']) && $xmlRoot['indexed'] == true) {
73
                $class->indexed = true;
74
            }
75
76
            if (isset($xmlRoot['inheritance-root']) && $xmlRoot['inheritance-root']) {
77
                $class->markInheritanceRoot();
78
            }
79
        } else if ($xmlRoot->getName() == "embedded-document") {
80
            $class->isEmbeddedDocument = true;
81
82
            if (isset($xmlRoot['inheritance-root']) && $xmlRoot['inheritance-root']) {
83
                $class->markInheritanceRoot();
84
            }
85
        } else if ($xmlRoot->getName() == "mapped-superclass") {
86
            $class->isMappedSuperclass = true;
87
        } else {
88
            throw MappingException::classIsNotAValidDocument($className);
89
        }
90
91
        // Evaluate <field ...> mappings
92
        if (isset($xmlRoot->field)) {
93 View Code Duplication
            foreach ($xmlRoot->field as $fieldMapping) {
94
                $class->mapField(array(
95
                    'fieldName' => (string)$fieldMapping['name'],
96
                    'jsonName'  => (isset($fieldMapping['json-name'])) ? (string)$fieldMapping['json-name'] : null,
97
                    'indexed'   => (isset($fieldMapping['index'])) ? (bool)$fieldMapping['index'] : false,
98
                    'type'      => (isset($fieldMapping['type'])) ? (string)$fieldMapping['type'] : null,
99
                    'isVersionField'   => (isset($fieldMapping['version'])) ? true : null,
100
                ));
101
            }
102
        }
103
104
        // Evaluate <id ..> mappings
105 View Code Duplication
        foreach ($xmlRoot->id as $idElement) {
106
            $class->mapField(array(
107
                'fieldName' => (string)$idElement['name'],
108
                'indexed'   => (isset($idElement['index'])) ? (bool)$idElement['index'] : false,
109
                'type'      => (isset($idElement['type'])) ? (string)$idElement['type'] : null,
110
                'id'        => true,
111
                'strategy'  => (isset($idElement['strategy'])) ? (string)$idElement['strategy'] : null,
112
            ));
113
        }
114
115
        // Evaluate <version ..> mappings
116
        foreach ($xmlRoot->version as $versionElement) {
117
            $class->mapField(array(
118
                'fieldName'      => (string)$versionElement['name'],
119
                'type'           => 'string',
120
                'isVersionField' => true,
121
                'jsonName'       => '_rev',
122
            ));
123
        }
124
125
        // Evaluate <many-to-one ..> mappings
126 View Code Duplication
        if (isset($xmlRoot->{"reference-one"})) {
127
            foreach ($xmlRoot->{"reference-one"} as $referenceOneElement) {
128
                $class->mapManyToOne(array(
129
                    'cascade'           => (isset($referenceOneElement->cascade)) ? $this->getCascadeMode($referenceOneElement->cascade) : 0,
130
                    'targetDocument'    => (string)$referenceOneElement['target-document'],
131
                    'fieldName'         => (string)$referenceOneElement['field'],
132
                    'jsonName'          => (isset($referenceOneElement['json-name'])) ? (string)$referenceOneElement['json-name'] : null,
133
                    'indexed'           => (isset($referenceOneElement['index'])) ? (bool)$referenceOneElement['index'] : false,
134
                ));
135
            }
136
        }
137
138
        // Evaluate <many-to-one ..> mappings
139 View Code Duplication
        if (isset($xmlRoot->{"reference-many"})) {
140
            foreach ($xmlRoot->{"reference-many"} as $referenceManyElement) {
141
                $class->mapManyToMany(array(
142
                    'cascade'           => (isset($referenceManyElement->cascade)) ? $this->getCascadeMode($referenceManyElement->cascade) : 0,
143
                    'targetDocument'    => (string)$referenceManyElement['target-document'],
144
                    'fieldName'         => (string)$referenceManyElement['field'],
145
                    'jsonName'          => (isset($referenceManyElement['json-name'])) ? (string)$referenceManyElement['json-name'] : null,
146
                    'mappedBy'          => (isset($referenceManyElement['mapped-by'])) ? (string)$referenceManyElement['mapped-by'] : null,
147
                ));
148
            }
149
        }
150
151
        // Evaluate <attachments ..> mapping
152
        if (isset($xmlRoot->{"attachments"})) {
153
            $class->mapAttachments((string)$xmlRoot->{"attachments"}[0]['field']);
154
        }
155
156
        // Evaluate <embed-one />
157 View Code Duplication
        if (isset($xmlRoot->{'embed-one'})) {
158
            foreach ($xmlRoot->{'embed-one'} AS $embedOneElement) {
159
                $class->mapEmbedded(array(
160
                    'targetDocument'    => (string)$embedOneElement['target-document'],
161
                    'fieldName'         => (string)$embedOneElement['field'],
162
                    'jsonName'          => (isset($embedOneElement['json-name'])) ? (string)$embedOneElement['json-name'] : null,
163
                    'embedded'          => 'one',
164
                ));
165
            }
166
        }
167
168
        // Evaluate <embed-many />
169 View Code Duplication
        if (isset($xmlRoot->{'embed-many'})) {
170
            foreach ($xmlRoot->{'embed-many'} AS $embedManyElement) {
171
                $class->mapEmbedded(array(
172
                    'targetDocument'    => (string)$embedManyElement['target-document'],
173
                    'fieldName'         => (string)$embedManyElement['field'],
174
                    'jsonName'          => (isset($embedManyElement['json-name'])) ? (string)$embedManyElement['json-name'] : null,
175
                    'embedded'          => 'many',
176
                ));
177
            }
178
        }
179
    }
180
181
    protected function loadMappingFile($file)
182
    {
183
        $result = array();
184
        $entity = libxml_disable_entity_loader(true);
185
        $xmlElement = simplexml_load_string(file_get_contents($file));
186
        libxml_disable_entity_loader($entity);
187
188
        foreach (array('document', 'embedded-document', 'mapped-superclass') as $type) {
189
            if (isset($xmlElement->$type)) {
190
                foreach ($xmlElement->$type as $documentElement) {
191
                    $documentName = (string) $documentElement['name'];
192
                    $result[$documentName] = $documentElement;
193
                }
194
            }
195
        }
196
197
        return $result;
198
    }
199
200
    /**
201
     * Gathers a list of cascade options found in the given cascade element.
202
     *
203
     * @param $cascadeElement cascade element.
204
     * @return integer a bitmask of cascade options.
205
     */
206
    private function getCascadeMode(SimpleXMLElement $cascadeElement)
207
    {
208
        $cascade = 0;
209
        foreach ($cascadeElement->children() as $action) {
210
            // According to the JPA specifications, XML uses "cascade-persist"
211
            // instead of "persist". Here, both variations
212
            // are supported because both YAML and Annotation use "persist"
213
            // and we want to make sure that this driver doesn't need to know
214
            // anything about the supported cascading actions
215
            $cascadeMode = str_replace('cascade-', '', $action->getName());
216
            $constantName = 'Doctrine\ODM\CouchDB\Mapping\ClassMetadata::CASCADE_' . strtoupper($cascadeMode);
217
            if (!defined($constantName)) {
218
                throw new MappingException("Cascade mode '$cascadeMode' not supported.");
219
            }
220
            $cascade |= constant($constantName);
221
        }
222
223
        return $cascade;
224
    }
225
}
226