Completed
Pull Request — master (#1790)
by Andreas
17:27 queued 13:11
created

XmlDriver::addGridFSMappings()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6.105

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 12
cts 14
cp 0.8571
rs 8.439
c 0
b 0
f 0
cc 6
eloc 13
nc 9
nop 2
crap 6.105
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Mapping\Driver;
6
7
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
8
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
9
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
10
use function array_keys;
11
use function constant;
12
use function count;
13
use function current;
14
use function explode;
15
use function in_array;
16
use function is_numeric;
17
use function iterator_to_array;
18
use function next;
19
use function preg_match;
20
use function simplexml_load_file;
21
use function strtoupper;
22
use function trim;
23
24
/**
25
 * XmlDriver is a metadata driver that enables mapping through XML files.
26
 *
27
 */
28
class XmlDriver extends FileDriver
29
{
30
    public const DEFAULT_FILE_EXTENSION = '.dcm.xml';
31
32
    private const DEFAULT_GRIDFS_MAPPINGS = [
33
        'length' => [
34
            'name' => 'length',
35
            'type' => 'int',
36
            'notSaved' => true,
37
        ],
38
        'chunk-size' => [
39
            'name' => 'chunkSize',
40
            'type' => 'int',
41
            'notSaved' => true,
42
        ],
43
        'filename' => [
44
            'name' => 'filename',
45
            'type' => 'string',
46
            'notSaved' => true,
47
        ],
48
        'upload-date' => [
49
            'name' => 'uploadDate',
50
            'type' => 'date',
51
            'notSaved' => true,
52
        ],
53
    ];
54
55
    /**
56
     * {@inheritDoc}
57
     */
58 14
    public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
59
    {
60 14
        parent::__construct($locator, $fileExtension);
61 14
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 8
    public function loadMetadataForClass($className, \Doctrine\Common\Persistence\Mapping\ClassMetadata $class)
67
    {
68
        /** @var ClassMetadata $class */
69
        /** @var \SimpleXMLElement $xmlRoot */
70 8
        $xmlRoot = $this->getElement($className);
71 8
        if (! $xmlRoot) {
72
            return;
73
        }
74
75 8
        if ($xmlRoot->getName() === 'document') {
76 7
            if (isset($xmlRoot['repository-class'])) {
77 7
                $class->setCustomRepositoryClass((string) $xmlRoot['repository-class']);
78
            }
79 3
        } elseif ($xmlRoot->getName() === 'mapped-superclass') {
80 1
            $class->setCustomRepositoryClass(
81 1
                isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null
82
            );
83 1
            $class->isMappedSuperclass = true;
84 2
        } elseif ($xmlRoot->getName() === 'embedded-document') {
85 1
            $class->isEmbeddedDocument = true;
86 2
        } elseif ($xmlRoot->getName() === 'query-result-document') {
87 1
            $class->isQueryResultDocument = true;
88 1
        } elseif ($xmlRoot->getName() === 'gridfs-file') {
89 1
            $class->isFile = true;
90
        }
91
92 8
        if (isset($xmlRoot['db'])) {
93 4
            $class->setDatabase((string) $xmlRoot['db']);
94
        }
95
96 8
        if (isset($xmlRoot['collection'])) {
97 6
            if (isset($xmlRoot['capped-collection'])) {
98
                $config = ['name' => (string) $xmlRoot['collection']];
99
                $config['capped'] = (bool) $xmlRoot['capped-collection'];
100
                if (isset($xmlRoot['capped-collection-max'])) {
101
                    $config['max'] = (int) $xmlRoot['capped-collection-max'];
102
                }
103
                if (isset($xmlRoot['capped-collection-size'])) {
104
                    $config['size'] = (int) $xmlRoot['capped-collection-size'];
105
                }
106
                $class->setCollection($config);
107
            } else {
108 6
                $class->setCollection((string) $xmlRoot['collection']);
109
            }
110
        }
111 8
        if (isset($xmlRoot['bucket-name'])) {
112
            $class->setBucketName((string) $xmlRoot['bucket-name']);
113
        }
114 8
        if (isset($xmlRoot['writeConcern'])) {
115
            $class->setWriteConcern((string) $xmlRoot['writeConcern']);
116
        }
117 8
        if (isset($xmlRoot['inheritance-type'])) {
118
            $inheritanceType = (string) $xmlRoot['inheritance-type'];
119
            $class->setInheritanceType(constant(ClassMetadata::class . '::INHERITANCE_TYPE_' . $inheritanceType));
120
        }
121 8
        if (isset($xmlRoot['change-tracking-policy'])) {
122 1
            $class->setChangeTrackingPolicy(constant(ClassMetadata::class . '::CHANGETRACKING_' . strtoupper((string) $xmlRoot['change-tracking-policy'])));
123
        }
124 8
        if (isset($xmlRoot->{'discriminator-field'})) {
125
            $discrField = $xmlRoot->{'discriminator-field'};
126
            /* XSD only allows for "name", which is consistent with association
127
             * configurations, but fall back to "fieldName" for BC.
128
             */
129
            $class->setDiscriminatorField(
130
                (string) ($discrField['name'] ?? $discrField['fieldName'])
131
            );
132
        }
133 8
        if (isset($xmlRoot->{'discriminator-map'})) {
134
            $map = [];
135
            foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) {
136
                $map[(string) $discrMapElement['value']] = (string) $discrMapElement['class'];
137
            }
138
            $class->setDiscriminatorMap($map);
139
        }
140 8
        if (isset($xmlRoot->{'default-discriminator-value'})) {
141
            $class->setDefaultDiscriminatorValue((string) $xmlRoot->{'default-discriminator-value'}['value']);
142
        }
143 8
        if (isset($xmlRoot->{'indexes'})) {
144 2
            foreach ($xmlRoot->{'indexes'}->{'index'} as $index) {
145 2
                $this->addIndex($class, $index);
146
            }
147
        }
148 8
        if (isset($xmlRoot->{'shard-key'})) {
149
            $this->setShardKey($class, $xmlRoot->{'shard-key'}[0]);
150
        }
151 8
        if (isset($xmlRoot['read-only']) && (string) $xmlRoot['read-only'] === 'true') {
152
            $class->markReadOnly();
153
        }
154 8
        if (isset($xmlRoot->{'read-preference'})) {
155
            $class->setReadPreference(...$this->transformReadPreference($xmlRoot->{'read-preference'}));
156
        }
157 8
        if (isset($xmlRoot->field)) {
158 8
            foreach ($xmlRoot->field as $field) {
159 8
                $mapping = [];
160 8
                $attributes = $field->attributes();
161 8
                foreach ($attributes as $key => $value) {
162 8
                    $mapping[$key] = (string) $value;
163 8
                    $booleanAttributes = ['id', 'reference', 'embed', 'unique', 'sparse'];
164 8
                    if (! in_array($key, $booleanAttributes)) {
165 8
                        continue;
166
                    }
167
168 8
                    $mapping[$key] = ($mapping[$key] === 'true');
169
                }
170 8
                if (isset($mapping['id']) && $mapping['id'] === true && isset($mapping['strategy'])) {
171 2
                    $mapping['options'] = [];
172 2
                    if (isset($field->{'id-generator-option'})) {
173 1
                        foreach ($field->{'id-generator-option'} as $generatorOptions) {
174 1
                            $attributesGenerator = iterator_to_array($generatorOptions->attributes());
175 1
                            if (! isset($attributesGenerator['name']) || ! isset($attributesGenerator['value'])) {
176
                                continue;
177
                            }
178
179 1
                            $mapping['options'][(string) $attributesGenerator['name']] = (string) $attributesGenerator['value'];
180
                        }
181
                    }
182
                }
183
184 8
                if (isset($attributes['not-saved'])) {
185
                    $mapping['notSaved'] = ((string) $attributes['not-saved'] === 'true');
186
                }
187
188 8
                if (isset($attributes['also-load'])) {
189
                    $mapping['alsoLoadFields'] = explode(',', $attributes['also-load']);
190 8
                } elseif (isset($attributes['version'])) {
191
                    $mapping['version'] = ((string) $attributes['version'] === 'true');
192 8
                } elseif (isset($attributes['lock'])) {
193
                    $mapping['lock'] = ((string) $attributes['lock'] === 'true');
194
                }
195
196 8
                $this->addFieldMapping($class, $mapping);
197
            }
198
        }
199
200 8
        $this->addGridFSMappings($class, $xmlRoot);
201
202 8
        if (isset($xmlRoot->{'embed-one'})) {
203 1
            foreach ($xmlRoot->{'embed-one'} as $embed) {
204 1
                $this->addEmbedMapping($class, $embed, 'one');
205
            }
206
        }
207 8
        if (isset($xmlRoot->{'embed-many'})) {
208 1
            foreach ($xmlRoot->{'embed-many'} as $embed) {
209 1
                $this->addEmbedMapping($class, $embed, 'many');
210
            }
211
        }
212 8
        if (isset($xmlRoot->{'reference-many'})) {
213 3
            foreach ($xmlRoot->{'reference-many'} as $reference) {
214 3
                $this->addReferenceMapping($class, $reference, 'many');
215
            }
216
        }
217 8
        if (isset($xmlRoot->{'reference-one'})) {
218 2
            foreach ($xmlRoot->{'reference-one'} as $reference) {
219 2
                $this->addReferenceMapping($class, $reference, 'one');
220
            }
221
        }
222 8
        if (isset($xmlRoot->{'lifecycle-callbacks'})) {
223 1
            foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) {
224 1
                $class->addLifecycleCallback((string) $lifecycleCallback['method'], constant('Doctrine\ODM\MongoDB\Events::' . (string) $lifecycleCallback['type']));
225
            }
226
        }
227 8
        if (! isset($xmlRoot->{'also-load-methods'})) {
228 8
            return;
229
        }
230
231 1
        foreach ($xmlRoot->{'also-load-methods'}->{'also-load-method'} as $alsoLoadMethod) {
232 1
            $class->registerAlsoLoadMethod((string) $alsoLoadMethod['method'], (string) $alsoLoadMethod['field']);
233
        }
234 1
    }
235
236 9
    private function addFieldMapping(ClassMetadata $class, $mapping)
237
    {
238 9
        if (isset($mapping['name'])) {
239 9
            $name = $mapping['name'];
240 1
        } elseif (isset($mapping['fieldName'])) {
241 1
            $name = $mapping['fieldName'];
242
        } else {
243
            throw new \InvalidArgumentException('Cannot infer a MongoDB name from the mapping');
244
        }
245
246 9
        $class->mapField($mapping);
247
248
        // Index this field if either "index", "unique", or "sparse" are set
249 9
        if (! (isset($mapping['index']) || isset($mapping['unique']) || isset($mapping['sparse']))) {
250 9
            return;
251
        }
252
253 1
        $keys = [$name => $mapping['order'] ?? 'asc'];
254 1
        $options = [];
255
256 1
        if (isset($mapping['background'])) {
257
            $options['background'] = (bool) $mapping['background'];
258
        }
259 1
        if (isset($mapping['drop-dups'])) {
260
            $options['dropDups'] = (bool) $mapping['drop-dups'];
261
        }
262 1
        if (isset($mapping['index-name'])) {
263
            $options['name'] = (string) $mapping['index-name'];
264
        }
265 1
        if (isset($mapping['sparse'])) {
266 1
            $options['sparse'] = (bool) $mapping['sparse'];
267
        }
268 1
        if (isset($mapping['unique'])) {
269 1
            $options['unique'] = (bool) $mapping['unique'];
270
        }
271
272 1
        $class->addIndex($keys, $options);
273 1
    }
274
275 2
    private function addEmbedMapping(ClassMetadata $class, $embed, $type)
276
    {
277 2
        $attributes = $embed->attributes();
278 2
        $defaultStrategy = $type === 'one' ? ClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY;
279
        $mapping = [
280 2
            'type'            => $type,
281
            'embedded'        => true,
282 2
            'targetDocument'  => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null,
283 2
            'collectionClass' => isset($attributes['collection-class']) ? (string) $attributes['collection-class'] : null,
284 2
            'name'            => (string) $attributes['field'],
285 2
            'strategy'        => (string) ($attributes['strategy'] ?? $defaultStrategy),
286
        ];
287 2
        if (isset($attributes['fieldName'])) {
288
            $mapping['fieldName'] = (string) $attributes['fieldName'];
289
        }
290 2
        if (isset($embed->{'discriminator-field'})) {
291
            $attr = $embed->{'discriminator-field'};
292
            $mapping['discriminatorField'] = (string) $attr['name'];
293
        }
294 2
        if (isset($embed->{'discriminator-map'})) {
295
            foreach ($embed->{'discriminator-map'}->{'discriminator-mapping'} as $discriminatorMapping) {
296
                $attr = $discriminatorMapping->attributes();
297
                $mapping['discriminatorMap'][(string) $attr['value']] = (string) $attr['class'];
298
            }
299
        }
300 2
        if (isset($embed->{'default-discriminator-value'})) {
301
            $mapping['defaultDiscriminatorValue'] = (string) $embed->{'default-discriminator-value'}['value'];
302
        }
303 2
        if (isset($attributes['not-saved'])) {
304
            $mapping['notSaved'] = ((string) $attributes['not-saved'] === 'true');
305
        }
306 2
        if (isset($attributes['also-load'])) {
307
            $mapping['alsoLoadFields'] = explode(',', $attributes['also-load']);
308
        }
309 2
        $this->addFieldMapping($class, $mapping);
310 2
    }
311
312 4
    private function addReferenceMapping(ClassMetadata $class, $reference, $type)
313
    {
314 4
        $cascade = array_keys((array) $reference->cascade);
315 4
        if (count($cascade) === 1) {
316 1
            $cascade = current($cascade) ?: next($cascade);
317
        }
318 4
        $attributes = $reference->attributes();
319 4
        $defaultStrategy = $type === 'one' ? ClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY;
320
        $mapping = [
321 4
            'cascade'          => $cascade,
322 4
            'orphanRemoval'    => isset($attributes['orphan-removal']) ? ((string) $attributes['orphan-removal'] === 'true') : false,
323 4
            'type'             => $type,
324
            'reference'        => true,
325 4
            'storeAs'          => (string) ($attributes['store-as'] ?? ClassMetadata::REFERENCE_STORE_AS_DB_REF),
326 4
            'targetDocument'   => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null,
327 4
            'collectionClass'  => isset($attributes['collection-class']) ? (string) $attributes['collection-class'] : null,
328 4
            'name'             => (string) $attributes['field'],
329 4
            'strategy'         => (string) ($attributes['strategy'] ?? $defaultStrategy),
330 4
            'inversedBy'       => isset($attributes['inversed-by']) ? (string) $attributes['inversed-by'] : null,
331 4
            'mappedBy'         => isset($attributes['mapped-by']) ? (string) $attributes['mapped-by'] : null,
332 4
            'repositoryMethod' => isset($attributes['repository-method']) ? (string) $attributes['repository-method'] : null,
333 4
            'limit'            => isset($attributes['limit']) ? (int) $attributes['limit'] : null,
334 4
            'skip'             => isset($attributes['skip']) ? (int) $attributes['skip'] : null,
335
            'prime'            => [],
336
        ];
337
338 4
        if (isset($attributes['fieldName'])) {
339
            $mapping['fieldName'] = (string) $attributes['fieldName'];
340
        }
341 4
        if (isset($reference->{'discriminator-field'})) {
342
            $attr = $reference->{'discriminator-field'};
343
            $mapping['discriminatorField'] = (string) $attr['name'];
344
        }
345 4
        if (isset($reference->{'discriminator-map'})) {
346
            foreach ($reference->{'discriminator-map'}->{'discriminator-mapping'} as $discriminatorMapping) {
347
                $attr = $discriminatorMapping->attributes();
348
                $mapping['discriminatorMap'][(string) $attr['value']] = (string) $attr['class'];
349
            }
350
        }
351 4
        if (isset($reference->{'default-discriminator-value'})) {
352
            $mapping['defaultDiscriminatorValue'] = (string) $reference->{'default-discriminator-value'}['value'];
353
        }
354 4
        if (isset($reference->{'sort'})) {
355
            foreach ($reference->{'sort'}->{'sort'} as $sort) {
356
                $attr = $sort->attributes();
357
                $mapping['sort'][(string) $attr['field']] = (string) ($attr['order'] ?? 'asc');
358
            }
359
        }
360 4
        if (isset($reference->{'criteria'})) {
361
            foreach ($reference->{'criteria'}->{'criteria'} as $criteria) {
362
                $attr = $criteria->attributes();
363
                $mapping['criteria'][(string) $attr['field']] = (string) $attr['value'];
364
            }
365
        }
366 4
        if (isset($attributes['not-saved'])) {
367
            $mapping['notSaved'] = ((string) $attributes['not-saved'] === 'true');
368
        }
369 4
        if (isset($attributes['also-load'])) {
370
            $mapping['alsoLoadFields'] = explode(',', $attributes['also-load']);
371
        }
372 4
        if (isset($reference->{'prime'})) {
373 1
            foreach ($reference->{'prime'}->{'field'} as $field) {
374 1
                $attr = $field->attributes();
375 1
                $mapping['prime'][] = (string) $attr['name'];
376
            }
377
        }
378
379 4
        $this->addFieldMapping($class, $mapping);
380 4
    }
381
382 2
    private function addIndex(ClassMetadata $class, \SimpleXmlElement $xmlIndex)
383
    {
384 2
        $attributes = $xmlIndex->attributes();
385
386 2
        $keys = [];
387
388 2
        foreach ($xmlIndex->{'key'} as $key) {
389 2
            $keys[(string) $key['name']] = (string) ($key['order'] ?? 'asc');
390
        }
391
392 2
        $options = [];
393
394 2
        if (isset($attributes['background'])) {
395
            $options['background'] = ((string) $attributes['background'] === 'true');
396
        }
397 2
        if (isset($attributes['drop-dups'])) {
398
            $options['dropDups'] = ((string) $attributes['drop-dups'] === 'true');
399
        }
400 2
        if (isset($attributes['name'])) {
401
            $options['name'] = (string) $attributes['name'];
402
        }
403 2
        if (isset($attributes['sparse'])) {
404
            $options['sparse'] = ((string) $attributes['sparse'] === 'true');
405
        }
406 2
        if (isset($attributes['unique'])) {
407
            $options['unique'] = ((string) $attributes['unique'] === 'true');
408
        }
409
410 2
        if (isset($xmlIndex->{'option'})) {
411
            foreach ($xmlIndex->{'option'} as $option) {
412
                $value = (string) $option['value'];
413
                if ($value === 'true') {
414
                    $value = true;
415
                } elseif ($value === 'false') {
416
                    $value = false;
417
                } elseif (is_numeric($value)) {
418
                    $value = preg_match('/^[-]?\d+$/', $value) ? (int) $value : (float) $value;
419
                }
420
                $options[(string) $option['name']] = $value;
421
            }
422
        }
423
424 2
        if (isset($xmlIndex->{'partial-filter-expression'})) {
425 2
            $partialFilterExpressionMapping = $xmlIndex->{'partial-filter-expression'};
426
427 2
            if (isset($partialFilterExpressionMapping->and)) {
428 2
                foreach ($partialFilterExpressionMapping->and as $and) {
429 2
                    if (! isset($and->field)) {
430 1
                        continue;
431
                    }
432
433 2
                    $partialFilterExpression = $this->getPartialFilterExpression($and->field);
434 2
                    if (! $partialFilterExpression) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $partialFilterExpression 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...
435
                        continue;
436
                    }
437
438 2
                    $options['partialFilterExpression']['$and'][] = $partialFilterExpression;
439
                }
440 1
            } elseif (isset($partialFilterExpressionMapping->field)) {
441 1
                $partialFilterExpression = $this->getPartialFilterExpression($partialFilterExpressionMapping->field);
442
443 1
                if ($partialFilterExpression) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $partialFilterExpression 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...
444 1
                    $options['partialFilterExpression'] = $partialFilterExpression;
445
                }
446
            }
447
        }
448
449 2
        $class->addIndex($keys, $options);
450 2
    }
451
452 2
    private function getPartialFilterExpression(\SimpleXMLElement $fields)
453
    {
454 2
        $partialFilterExpression = [];
455 2
        foreach ($fields as $field) {
456 2
            $operator = (string) $field['operator'] ?: null;
457
458 2
            if (! isset($field['value'])) {
459 1
                if (! isset($field->field)) {
460
                    continue;
461
                }
462
463 1
                $nestedExpression = $this->getPartialFilterExpression($field->field);
464 1
                if (! $nestedExpression) {
465
                    continue;
466
                }
467
468 1
                $value = $nestedExpression;
469
            } else {
470 2
                $value = trim((string) $field['value']);
471
            }
472
473 2
            if ($value === 'true') {
474
                $value = true;
475 2
            } elseif ($value === 'false') {
476
                $value = false;
477 2
            } elseif (is_numeric($value)) {
478 1
                $value = preg_match('/^[-]?\d+$/', $value) ? (int) $value : (float) $value;
479
            }
480
481 2
            $partialFilterExpression[(string) $field['name']] = $operator ? ['$' . $operator => $value] : $value;
482
        }
483
484 2
        return $partialFilterExpression;
485
    }
486
487 1
    private function setShardKey(ClassMetadata $class, \SimpleXmlElement $xmlShardkey)
488
    {
489 1
        $attributes = $xmlShardkey->attributes();
490
491 1
        $keys = [];
492 1
        $options = [];
493 1
        foreach ($xmlShardkey->{'key'} as $key) {
494 1
            $keys[(string) $key['name']] = (string) ($key['order'] ?? 'asc');
495
        }
496
497 1
        if (isset($attributes['unique'])) {
498 1
            $options['unique'] = ((string) $attributes['unique'] === 'true');
499
        }
500
501 1
        if (isset($attributes['numInitialChunks'])) {
502 1
            $options['numInitialChunks'] = (int) $attributes['numInitialChunks'];
503
        }
504
505 1
        if (isset($xmlShardkey->{'option'})) {
506
            foreach ($xmlShardkey->{'option'} as $option) {
507
                $value = (string) $option['value'];
508
                if ($value === 'true') {
509
                    $value = true;
510
                } elseif ($value === 'false') {
511
                    $value = false;
512
                } elseif (is_numeric($value)) {
513
                    $value = preg_match('/^[-]?\d+$/', $value) ? (int) $value : (float) $value;
514
                }
515
                $options[(string) $option['name']] = $value;
516
            }
517
        }
518
519 1
        $class->setShardKey($keys, $options);
520 1
    }
521
522
    /**
523
     * Parses <read-preference> to a format suitable for the underlying driver.
524
     *
525
     * list($readPreference, $tags) = $this->transformReadPreference($xml->{read-preference});
526
     *
527
     * @param \SimpleXMLElement $xmlReadPreference
528
     * @return array
529
     */
530
    private function transformReadPreference($xmlReadPreference)
531
    {
532
        $tags = null;
533
        if (isset($xmlReadPreference->{'tag-set'})) {
534
            $tags = [];
535
            foreach ($xmlReadPreference->{'tag-set'} as $tagSet) {
536
                $set = [];
537
                foreach ($tagSet->tag as $tag) {
538
                    $set[(string) $tag['name']] = (string) $tag['value'];
539
                }
540
                $tags[] = $set;
541
            }
542
        }
543
        return [(string) $xmlReadPreference['mode'], $tags];
544
    }
545
546
    /**
547
     * {@inheritDoc}
548
     */
549 8
    protected function loadMappingFile($file)
550
    {
551 8
        $result = [];
552 8
        $xmlElement = simplexml_load_file($file);
553
554 8
        foreach (['document', 'embedded-document', 'mapped-superclass', 'query-result-document', 'gridfs-file'] as $type) {
555 8
            if (! isset($xmlElement->$type)) {
556 8
                continue;
557
            }
558
559 8
            foreach ($xmlElement->$type as $documentElement) {
560 8
                $documentName = (string) $documentElement['name'];
561 8
                $result[$documentName] = $documentElement;
562
            }
563
        }
564
565 8
        return $result;
566
    }
567
568 8
    private function addGridFSMappings(ClassMetadata $class, \SimpleXMLElement $xmlRoot): void
569
    {
570 8
        if (! $class->isFile) {
571 7
            return;
572
        }
573
574 1
        foreach (self::DEFAULT_GRIDFS_MAPPINGS as $name => $mapping) {
575 1
            if (! isset($xmlRoot->{$name})) {
576
                continue;
577
            }
578
579 1
            if (isset($xmlRoot->{$name}->attributes()['fieldName'])) {
580 1
                $mapping['fieldName'] = (string) $xmlRoot->{$name}->attributes()['fieldName'];
581
            }
582
583 1
            $this->addFieldMapping($class, $mapping);
584
        }
585
586 1
        if (! isset($xmlRoot->metadata)) {
587
            return;
588
        }
589
590 1
        $xmlRoot->metadata->addAttribute('field', 'metadata');
591 1
        $this->addEmbedMapping($class, $xmlRoot->metadata, 'one');
592 1
    }
593
}
594