Completed
Pull Request — master (#1385)
by Andreas
08:02
created

ClassMetadataInfo::getFieldMapping()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 2
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\MongoDB\Mapping;
21
22
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
23
use Doctrine\ODM\MongoDB\LockException;
24
use Doctrine\ODM\MongoDB\Proxy\Proxy;
25
use Doctrine\ODM\MongoDB\Types\Type;
26
use InvalidArgumentException;
27
28
/**
29
 * A <tt>ClassMetadata</tt> instance holds all the object-document mapping metadata
30
 * of a document and it's references.
31
 *
32
 * Once populated, ClassMetadata instances are usually cached in a serialized form.
33
 *
34
 * <b>IMPORTANT NOTE:</b>
35
 *
36
 * The fields of this class are only public for 2 reasons:
37
 * 1) To allow fast READ access.
38
 * 2) To drastically reduce the size of a serialized instance (private/protected members
39
 *    get the whole class name, namespace inclusive, prepended to every property in
40
 *    the serialized representation).
41
 *
42
 * @since       1.0
43
 */
44
class ClassMetadataInfo implements \Doctrine\Common\Persistence\Mapping\ClassMetadata
45
{
46
    /* The Id generator types. */
47
    /**
48
     * AUTO means Doctrine will automatically create a new \MongoId instance for us.
49
     */
50
    const GENERATOR_TYPE_AUTO = 1;
51
52
    /**
53
     * INCREMENT means a separate collection is used for maintaining and incrementing id generation.
54
     * Offers full portability.
55
     */
56
    const GENERATOR_TYPE_INCREMENT = 2;
57
58
    /**
59
     * UUID means Doctrine will generate a uuid for us.
60
     */
61
    const GENERATOR_TYPE_UUID = 3;
62
63
    /**
64
     * ALNUM means Doctrine will generate Alpha-numeric string identifiers, using the INCREMENT
65
     * generator to ensure identifier uniqueness
66
     */
67
    const GENERATOR_TYPE_ALNUM = 4;
68
69
    /**
70
     * CUSTOM means Doctrine expect a class parameter. It will then try to initiate that class
71
     * and pass other options to the generator. It will throw an Exception if the class
72
     * does not exist or if an option was passed for that there is not setter in the new
73
     * generator class.
74
     *
75
     * The class  will have to be a subtype of AbstractIdGenerator.
76
     */
77
    const GENERATOR_TYPE_CUSTOM = 5;
78
79
    /**
80
     * NONE means Doctrine will not generate any id for us and you are responsible for manually
81
     * assigning an id.
82
     */
83
    const GENERATOR_TYPE_NONE = 6;
84
85
    /**
86
     * Default discriminator field name.
87
     *
88
     * This is used for associations value for associations where a that do not define a "targetDocument" or
89
     * "discriminatorField" option in their mapping.
90
     */
91
    const DEFAULT_DISCRIMINATOR_FIELD = '_doctrine_class_name';
92
93
    const REFERENCE_ONE = 1;
94
    const REFERENCE_MANY = 2;
95
    const EMBED_ONE = 3;
96
    const EMBED_MANY = 4;
97
    const MANY = 'many';
98
    const ONE = 'one';
99
100
    /* The inheritance mapping types */
101
    /**
102
     * NONE means the class does not participate in an inheritance hierarchy
103
     * and therefore does not need an inheritance mapping type.
104
     */
105
    const INHERITANCE_TYPE_NONE = 1;
106
107
    /**
108
     * SINGLE_COLLECTION means the class will be persisted according to the rules of
109
     * <tt>Single Collection Inheritance</tt>.
110
     */
111
    const INHERITANCE_TYPE_SINGLE_COLLECTION = 2;
112
113
    /**
114
     * COLLECTION_PER_CLASS means the class will be persisted according to the rules
115
     * of <tt>Concrete Collection Inheritance</tt>.
116
     */
117
    const INHERITANCE_TYPE_COLLECTION_PER_CLASS = 3;
118
119
    /**
120
     * DEFERRED_IMPLICIT means that changes of entities are calculated at commit-time
121
     * by doing a property-by-property comparison with the original data. This will
122
     * be done for all entities that are in MANAGED state at commit-time.
123
     *
124
     * This is the default change tracking policy.
125
     */
126
    const CHANGETRACKING_DEFERRED_IMPLICIT = 1;
127
128
    /**
129
     * DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time
130
     * by doing a property-by-property comparison with the original data. This will
131
     * be done only for entities that were explicitly saved (through persist() or a cascade).
132
     */
133
    const CHANGETRACKING_DEFERRED_EXPLICIT = 2;
134
135
    /**
136
     * NOTIFY means that Doctrine relies on the entities sending out notifications
137
     * when their properties change. Such entity classes must implement
138
     * the <tt>NotifyPropertyChanged</tt> interface.
139
     */
140
    const CHANGETRACKING_NOTIFY = 3;
141
142
    /**
143
     * SET means that fields will be written to the database using a $set operator
144
     */
145
    const STORAGE_STRATEGY_SET = 'set';
146
147
    /**
148
     * INCREMENT means that fields will be written to the database by calculating
149
     * the difference and using the $inc operator
150
     */
151
    const STORAGE_STRATEGY_INCREMENT = 'increment';
152
153
    const STORAGE_STRATEGY_PUSH_ALL = 'pushAll';
154
    const STORAGE_STRATEGY_ADD_TO_SET = 'addToSet';
155
    const STORAGE_STRATEGY_ATOMIC_SET = 'atomicSet';
156
    const STORAGE_STRATEGY_ATOMIC_SET_ARRAY = 'atomicSetArray';
157
    const STORAGE_STRATEGY_SET_ARRAY = 'setArray';
158
159
    /**
160
     * READ-ONLY: The name of the mongo database the document is mapped to.
161
     */
162
    public $db;
163
164
    /**
165
     * READ-ONLY: The name of the mongo collection the document is mapped to.
166
     */
167
    public $collection;
168
169
    /**
170
     * READ-ONLY: If the collection should be a fixed size.
171
     */
172
    public $collectionCapped;
173
174
    /**
175
     * READ-ONLY: If the collection is fixed size, its size in bytes.
176
     */
177
    public $collectionSize;
178
179
    /**
180
     * READ-ONLY: If the collection is fixed size, the maximum number of elements to store in the collection.
181
     */
182
    public $collectionMax;
183
184
    /**
185
     * READ-ONLY: The field name of the document identifier.
186
     */
187
    public $identifier;
188
189
    /**
190
     * READ-ONLY: The field that stores a file reference and indicates the
191
     * document is a file and should be stored on the MongoGridFS.
192
     */
193
    public $file;
194
195
    /**
196
     * READ-ONLY: The field that stores the calculated distance when performing geo spatial
197
     * queries.
198
     */
199
    public $distance;
200
201
    /**
202
     * READ-ONLY: Whether or not reads for this class are okay to read from a slave.
203
     */
204
    public $slaveOkay;
205
206
    /**
207
     * READ-ONLY: The array of indexes for the document collection.
208
     */
209
    public $indexes = array();
210
211
    /**
212
     * READ-ONLY: Keys and options describing shard key. Only for sharded collections.
213
     */
214
    public $shardKey;
215
216
    /**
217
     * READ-ONLY: Whether or not queries on this document should require indexes.
218
     */
219
    public $requireIndexes = false;
220
221
    /**
222
     * READ-ONLY: The name of the document class.
223
     */
224
    public $name;
225
226
    /**
227
     * READ-ONLY: The namespace the document class is contained in.
228
     *
229
     * @var string
230
     * @todo Not really needed. Usage could be localized.
231
     */
232
    public $namespace;
233
234
    /**
235
     * READ-ONLY: The name of the document class that is at the root of the mapped document inheritance
236
     * hierarchy. If the document is not part of a mapped inheritance hierarchy this is the same
237
     * as {@link $documentName}.
238
     *
239
     * @var string
240
     */
241
    public $rootDocumentName;
242
243
    /**
244
     * The name of the custom repository class used for the document class.
245
     * (Optional).
246
     *
247
     * @var string
248
     */
249
    public $customRepositoryClassName;
250
251
    /**
252
     * READ-ONLY: The names of the parent classes (ancestors).
253
     *
254
     * @var array
255
     */
256
    public $parentClasses = array();
257
258
    /**
259
     * READ-ONLY: The names of all subclasses (descendants).
260
     *
261
     * @var array
262
     */
263
    public $subClasses = array();
264
265
    /**
266
     * The ReflectionProperty instances of the mapped class.
267
     *
268
     * @var \ReflectionProperty[]
269
     */
270
    public $reflFields = array();
271
272
    /**
273
     * READ-ONLY: The inheritance mapping type used by the class.
274
     *
275
     * @var integer
276
     */
277
    public $inheritanceType = self::INHERITANCE_TYPE_NONE;
278
279
    /**
280
     * READ-ONLY: The Id generator type used by the class.
281
     *
282
     * @var string
283
     */
284
    public $generatorType = self::GENERATOR_TYPE_AUTO;
285
286
    /**
287
     * READ-ONLY: The Id generator options.
288
     *
289
     * @var array
290
     */
291
    public $generatorOptions = array();
292
293
    /**
294
     * READ-ONLY: The ID generator used for generating IDs for this class.
295
     *
296
     * @var \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator
297
     */
298
    public $idGenerator;
299
300
    /**
301
     * READ-ONLY: The field mappings of the class.
302
     * Keys are field names and values are mapping definitions.
303
     *
304
     * The mapping definition array has the following values:
305
     *
306
     * - <b>fieldName</b> (string)
307
     * The name of the field in the Document.
308
     *
309
     * - <b>id</b> (boolean, optional)
310
     * Marks the field as the primary key of the document. Multiple fields of an
311
     * document can have the id attribute, forming a composite key.
312
     *
313
     * @var array
314
     */
315
    public $fieldMappings = array();
316
317
    /**
318
     * READ-ONLY: The association mappings of the class.
319
     * Keys are field names and values are mapping definitions.
320
     *
321
     * @var array
322
     */
323
    public $associationMappings = array();
324
325
    /**
326
     * READ-ONLY: Array of fields to also load with a given method.
327
     *
328
     * @var array
329
     */
330
    public $alsoLoadMethods = array();
331
332
    /**
333
     * READ-ONLY: The registered lifecycle callbacks for documents of this class.
334
     *
335
     * @var array
336
     */
337
    public $lifecycleCallbacks = array();
338
339
    /**
340
     * READ-ONLY: The discriminator value of this class.
341
     *
342
     * <b>This does only apply to the JOINED and SINGLE_COLLECTION inheritance mapping strategies
343
     * where a discriminator field is used.</b>
344
     *
345
     * @var mixed
346
     * @see discriminatorField
347
     */
348
    public $discriminatorValue;
349
350
    /**
351
     * READ-ONLY: The discriminator map of all mapped classes in the hierarchy.
352
     *
353
     * <b>This does only apply to the SINGLE_COLLECTION inheritance mapping strategy
354
     * where a discriminator field is used.</b>
355
     *
356
     * @var mixed
357
     * @see discriminatorField
358
     */
359
    public $discriminatorMap = array();
360
361
    /**
362
     * READ-ONLY: The definition of the discriminator field used in SINGLE_COLLECTION
363
     * inheritance mapping.
364
     *
365
     * @var string
366
     */
367
    public $discriminatorField;
368
369
    /**
370
     * READ-ONLY: The default value for discriminatorField in case it's not set in the document
371
     *
372
     * @var string
373
     * @see discriminatorField
374
     */
375
    public $defaultDiscriminatorValue;
376
377
    /**
378
     * READ-ONLY: Whether this class describes the mapping of a mapped superclass.
379
     *
380
     * @var boolean
381
     */
382
    public $isMappedSuperclass = false;
383
384
    /**
385
     * READ-ONLY: Whether this class describes the mapping of a embedded document.
386
     *
387
     * @var boolean
388
     */
389
    public $isEmbeddedDocument = false;
390
391
    /**
392
     * READ-ONLY: The policy used for change-tracking on entities of this class.
393
     *
394
     * @var integer
395
     */
396
    public $changeTrackingPolicy = self::CHANGETRACKING_DEFERRED_IMPLICIT;
397
398
    /**
399
     * READ-ONLY: A flag for whether or not instances of this class are to be versioned
400
     * with optimistic locking.
401
     *
402
     * @var boolean $isVersioned
403
     */
404
    public $isVersioned;
405
406
    /**
407
     * READ-ONLY: The name of the field which is used for versioning in optimistic locking (if any).
408
     *
409
     * @var mixed $versionField
410
     */
411
    public $versionField;
412
413
    /**
414
     * READ-ONLY: A flag for whether or not instances of this class are to allow pessimistic
415
     * locking.
416
     *
417
     * @var boolean $isLockable
418
     */
419
    public $isLockable;
420
421
    /**
422
     * READ-ONLY: The name of the field which is used for locking a document.
423
     *
424
     * @var mixed $lockField
425
     */
426
    public $lockField;
427
428
    /**
429
     * The ReflectionClass instance of the mapped class.
430
     *
431
     * @var \ReflectionClass
432
     */
433
    public $reflClass;
434
435
    /**
436
     * Initializes a new ClassMetadata instance that will hold the object-document mapping
437
     * metadata of the class with the given name.
438
     *
439
     * @param string $documentName The name of the document class the new instance is used for.
440
     */
441 902
    public function __construct($documentName)
442
    {
443 902
        $this->name = $documentName;
444 902
        $this->rootDocumentName = $documentName;
445 902
    }
446
447
    /**
448
     * {@inheritDoc}
449
     */
450 842
    public function getReflectionClass()
451
    {
452 842
        if ( ! $this->reflClass) {
453 2
            $this->reflClass = new \ReflectionClass($this->name);
454
        }
455
456 842
        return $this->reflClass;
457
    }
458
459
    /**
460
     * {@inheritDoc}
461
     */
462 300
    public function isIdentifier($fieldName)
463
    {
464 300
        return $this->identifier === $fieldName;
465
    }
466
467
    /**
468
     * INTERNAL:
469
     * Sets the mapped identifier field of this class.
470
     *
471
     * @param string $identifier
472
     */
473 347
    public function setIdentifier($identifier)
474
    {
475 347
        $this->identifier = $identifier;
476 347
    }
477
478
    /**
479
     * {@inheritDoc}
480
     *
481
     * Since MongoDB only allows exactly one identifier field
482
     * this will always return an array with only one value
483
     */
484 26
    public function getIdentifier()
485
    {
486 26
        return array($this->identifier);
487
    }
488
489
    /**
490
     * {@inheritDoc}
491
     *
492
     * Since MongoDB only allows exactly one identifier field
493
     * this will always return an array with only one value
494
     */
495 92
    public function getIdentifierFieldNames()
496
    {
497 92
        return array($this->identifier);
498
    }
499
500
    /**
501
     * {@inheritDoc}
502
     */
503 518
    public function hasField($fieldName)
504
    {
505 518
        return isset($this->fieldMappings[$fieldName]);
506
    }
507
508
    /**
509
     * Sets the inheritance type used by the class and it's subclasses.
510
     *
511
     * @param integer $type
512
     */
513 358
    public function setInheritanceType($type)
514
    {
515 358
        $this->inheritanceType = $type;
516 358
    }
517
518
    /**
519
     * Checks whether a mapped field is inherited from an entity superclass.
520
     *
521
     * @param  string $fieldName
522
     *
523
     * @return boolean TRUE if the field is inherited, FALSE otherwise.
524
     */
525 842
    public function isInheritedField($fieldName)
526
    {
527 842
        return isset($this->fieldMappings[$fieldName]['inherited']);
528
    }
529
530
    /**
531
     * Registers a custom repository class for the document class.
532
     *
533
     * @param string $repositoryClassName The class name of the custom repository.
534
     */
535 298 View Code Duplication
    public function setCustomRepositoryClass($repositoryClassName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
536
    {
537 298
        if ($this->isEmbeddedDocument) {
538
            return;
539
        }
540
541 298
        if ($repositoryClassName && strpos($repositoryClassName, '\\') === false && strlen($this->namespace)) {
542 3
            $repositoryClassName = $this->namespace . '\\' . $repositoryClassName;
543
        }
544
545 298
        $this->customRepositoryClassName = $repositoryClassName;
546 298
    }
547
548
    /**
549
     * Dispatches the lifecycle event of the given document by invoking all
550
     * registered callbacks.
551
     *
552
     * @param string $event     Lifecycle event
553
     * @param object $document  Document on which the event occurred
554
     * @param array  $arguments Arguments to pass to all callbacks
555
     * @throws \InvalidArgumentException if document class is not this class or
556
     *                                   a Proxy of this class
557
     */
558 601
    public function invokeLifecycleCallbacks($event, $document, array $arguments = null)
559
    {
560 601
        if ( ! $document instanceof $this->name) {
561 1
            throw new \InvalidArgumentException(sprintf('Expected document class "%s"; found: "%s"', $this->name, get_class($document)));
562
        }
563
564 600
        if (empty($this->lifecycleCallbacks[$event])) {
565 587
            return;
566
        }
567
568 183
        foreach ($this->lifecycleCallbacks[$event] as $callback) {
569 183
            if ($arguments !== null) {
570 182
                call_user_func_array(array($document, $callback), $arguments);
571
            } else {
572 183
                $document->$callback();
573
            }
574
        }
575 183
    }
576
577
    /**
578
     * Checks whether the class has callbacks registered for a lifecycle event.
579
     *
580
     * @param string $event Lifecycle event
581
     *
582
     * @return boolean
583
     */
584
    public function hasLifecycleCallbacks($event)
585
    {
586
        return ! empty($this->lifecycleCallbacks[$event]);
587
    }
588
589
    /**
590
     * Gets the registered lifecycle callbacks for an event.
591
     *
592
     * @param string $event
593
     * @return array
594
     */
595
    public function getLifecycleCallbacks($event)
596
    {
597
        return isset($this->lifecycleCallbacks[$event]) ? $this->lifecycleCallbacks[$event] : array();
598
    }
599
600
    /**
601
     * Adds a lifecycle callback for documents of this class.
602
     *
603
     * If the callback is already registered, this is a NOOP.
604
     *
605
     * @param string $callback
606
     * @param string $event
607
     */
608 279
    public function addLifecycleCallback($callback, $event)
609
    {
610 279
        if (isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) {
611 1
            return;
612
        }
613
614 279
        $this->lifecycleCallbacks[$event][] = $callback;
615 279
    }
616
617
    /**
618
     * Sets the lifecycle callbacks for documents of this class.
619
     *
620
     * Any previously registered callbacks are overwritten.
621
     *
622
     * @param array $callbacks
623
     */
624 346
    public function setLifecycleCallbacks(array $callbacks)
625
    {
626 346
        $this->lifecycleCallbacks = $callbacks;
627 346
    }
628
629
    /**
630
     * Registers a method for loading document data before field hydration.
631
     *
632
     * Note: A method may be registered multiple times for different fields.
633
     * it will be invoked only once for the first field found.
634
     *
635
     * @param string       $method Method name
636
     * @param array|string $fields Database field name(s)
637
     */
638 15
    public function registerAlsoLoadMethod($method, $fields)
639
    {
640 15
        $this->alsoLoadMethods[$method] = is_array($fields) ? $fields : array($fields);
641 15
    }
642
643
    /**
644
     * Sets the AlsoLoad methods for documents of this class.
645
     *
646
     * Any previously registered methods are overwritten.
647
     *
648
     * @param array $methods
649
     */
650 346
    public function setAlsoLoadMethods(array $methods)
651
    {
652 346
        $this->alsoLoadMethods = $methods;
653 346
    }
654
655
    /**
656
     * Sets the discriminator field.
657
     *
658
     * The field name is the the unmapped database field. Discriminator values
659
     * are only used to discern the hydration class and are not mapped to class
660
     * properties.
661
     *
662
     * @param string $discriminatorField
663
     *
664
     * @throws MappingException If the discriminator field conflicts with the
665
     *                          "name" attribute of a mapped field.
666
     */
667 367
    public function setDiscriminatorField($discriminatorField)
668
    {
669 367
        if ($discriminatorField === null) {
670 307
            $this->discriminatorField = null;
671
672 307
            return;
673
        }
674
675
        // Handle array argument with name/fieldName keys for BC
676 70
        if (is_array($discriminatorField)) {
677
            if (isset($discriminatorField['name'])) {
678
                $discriminatorField = $discriminatorField['name'];
679
            } elseif (isset($discriminatorField['fieldName'])) {
680
                $discriminatorField = $discriminatorField['fieldName'];
681
            }
682
        }
683
684 70
        foreach ($this->fieldMappings as $fieldMapping) {
685 4
            if ($discriminatorField == $fieldMapping['name']) {
686 4
                throw MappingException::discriminatorFieldConflict($this->name, $discriminatorField);
687
            }
688
        }
689
690 69
        $this->discriminatorField = $discriminatorField;
691 69
    }
692
693
    /**
694
     * Sets the discriminator values used by this class.
695
     * Used for JOINED and SINGLE_TABLE inheritance mapping strategies.
696
     *
697
     * @param array $map
698
     *
699
     * @throws MappingException
700
     */
701 363
    public function setDiscriminatorMap(array $map)
702
    {
703 363
        foreach ($map as $value => $className) {
704 119
            if (strpos($className, '\\') === false && strlen($this->namespace)) {
705 87
                $className = $this->namespace . '\\' . $className;
706
            }
707 119
            $this->discriminatorMap[$value] = $className;
708 119
            if ($this->name == $className) {
709 111
                $this->discriminatorValue = $value;
710
            } else {
711 111
                if ( ! class_exists($className)) {
712
                    throw MappingException::invalidClassInDiscriminatorMap($className, $this->name);
713
                }
714 111
                if (is_subclass_of($className, $this->name)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $this->name can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
715 119
                    $this->subClasses[] = $className;
716
                }
717
            }
718
        }
719 363
    }
720
721
    /**
722
     * Sets the default discriminator value to be used for this class
723
     * Used for JOINED and SINGLE_TABLE inheritance mapping strategies if the document has no discriminator value
724
     *
725
     * @param string $defaultDiscriminatorValue
726
     *
727
     * @throws MappingException
728
     */
729 352
    public function setDefaultDiscriminatorValue($defaultDiscriminatorValue)
730
    {
731 352
        if ($defaultDiscriminatorValue === null) {
732 346
            $this->defaultDiscriminatorValue = null;
733
734 346
            return;
735
        }
736
737 8
        if (!array_key_exists($defaultDiscriminatorValue, $this->discriminatorMap)) {
738
            throw MappingException::invalidDiscriminatorValue($defaultDiscriminatorValue, $this->name);
739
        }
740
741 8
        $this->defaultDiscriminatorValue = $defaultDiscriminatorValue;
742 8
    }
743
744
    /**
745
     * Sets the discriminator value for this class.
746
     * Used for JOINED/SINGLE_TABLE inheritance and multiple document types in a single
747
     * collection.
748
     *
749
     * @param string $value
750
     */
751
    public function setDiscriminatorValue($value)
752
    {
753
        $this->discriminatorMap[$value] = $this->name;
754
        $this->discriminatorValue = $value;
755
    }
756
757
    /**
758
     * Sets the slaveOkay option applied to collections for this class.
759
     *
760
     * @param boolean|null $slaveOkay
761
     */
762 3
    public function setSlaveOkay($slaveOkay)
763
    {
764 3
        $this->slaveOkay = $slaveOkay === null ? null : (boolean) $slaveOkay;
765 3
    }
766
767
    /**
768
     * Add a index for this Document.
769
     *
770
     * @param array $keys Array of keys for the index.
771
     * @param array $options Array of options for the index.
772
     */
773 225
    public function addIndex($keys, array $options = array())
774
    {
775 225
        $this->indexes[] = array(
776 View Code Duplication
            'keys' => array_map(function($value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
777 225
                if ($value == 1 || $value == -1) {
778 10
                    return (int) $value;
779
                }
780 217
                if (is_string($value)) {
781 217
                    $lower = strtolower($value);
782 217
                    if ($lower === 'asc') {
783 210
                        return 1;
784 10
                    } elseif ($lower === 'desc') {
785 3
                        return -1;
786
                    }
787
                }
788 7
                return $value;
789 225
            }, $keys),
790 225
            'options' => $options
791
        );
792 225
    }
793
794
    /**
795
     * Set whether or not queries on this document should require indexes.
796
     *
797
     * @param bool $requireIndexes
798
     */
799 832
    public function setRequireIndexes($requireIndexes)
800
    {
801 832
        $this->requireIndexes = $requireIndexes;
802 832
    }
803
804
    /**
805
     * Returns the array of indexes for this Document.
806
     *
807
     * @return array $indexes The array of indexes.
808
     */
809 47
    public function getIndexes()
810
    {
811 47
        return $this->indexes;
812
    }
813
814
    /**
815
     * Checks whether this document has indexes or not.
816
     *
817
     * @return boolean
818
     */
819
    public function hasIndexes()
820
    {
821
        return $this->indexes ? true : false;
822
    }
823
824
    /**
825
     * Set shard key for this Document.
826
     *
827
     * @param array $keys Array of document keys.
828
     * @param array $options Array of sharding options.
829
     *
830
     * @throws MappingException
831
     */
832 18
    public function setShardKey(array $keys, array $options = array())
833
    {
834 18
        if ($this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_COLLECTION && !is_null($this->shardKey)) {
835 2
            throw MappingException::shardKeyInSingleCollInheritanceSubclass($this->getName());
836
        }
837
838 18
        if ($this->isEmbeddedDocument) {
839 1
            throw MappingException::embeddedDocumentCantHaveShardKey($this->getName());
840
        }
841
842 17
        foreach ($keys as $field) {
843 17
            if ($this->getTypeOfField($field) == 'increment') {
844 17
                throw MappingException::noIncrementFieldsAllowedInShardKey($this->getName());
845
            }
846
        }
847
848 16
        $this->shardKey = array(
849 View Code Duplication
            'keys' => array_map(function($value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
850 16
                if ($value == 1 || $value == -1) {
851 5
                    return (int) $value;
852
                }
853 15
                if (is_string($value)) {
854 15
                    $lower = strtolower($value);
855 15
                    if ($lower === 'asc') {
856 15
                        return 1;
857 1
                    } elseif ($lower === 'desc') {
858
                        return -1;
859
                    }
860
                }
861 1
                return $value;
862 16
            }, $keys),
863 16
            'options' => $options
864
        );
865 16
    }
866
867
    /**
868
     * @return array
869
     */
870 13
    public function getShardKey()
871
    {
872 13
        return $this->shardKey;
873
    }
874
875
    /**
876
     * Checks whether this document has shard key or not.
877
     *
878
     * @return bool
879
     */
880 549
    public function isSharded()
881
    {
882 549
        return $this->shardKey ? true : false;
883
    }
884
885
    /**
886
     * Sets the change tracking policy used by this class.
887
     *
888
     * @param integer $policy
889
     */
890 351
    public function setChangeTrackingPolicy($policy)
891
    {
892 351
        $this->changeTrackingPolicy = $policy;
893 351
    }
894
895
    /**
896
     * Whether the change tracking policy of this class is "deferred explicit".
897
     *
898
     * @return boolean
899
     */
900 62
    public function isChangeTrackingDeferredExplicit()
901
    {
902 62
        return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_EXPLICIT;
903
    }
904
905
    /**
906
     * Whether the change tracking policy of this class is "deferred implicit".
907
     *
908
     * @return boolean
909
     */
910 576
    public function isChangeTrackingDeferredImplicit()
911
    {
912 576
        return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_IMPLICIT;
913
    }
914
915
    /**
916
     * Whether the change tracking policy of this class is "notify".
917
     *
918
     * @return boolean
919
     */
920 333
    public function isChangeTrackingNotify()
921
    {
922 333
        return $this->changeTrackingPolicy == self::CHANGETRACKING_NOTIFY;
923
    }
924
925
    /**
926
     * Gets the ReflectionProperties of the mapped class.
927
     *
928
     * @return array An array of ReflectionProperty instances.
929
     */
930 92
    public function getReflectionProperties()
931
    {
932 92
        return $this->reflFields;
933
    }
934
935
    /**
936
     * Gets a ReflectionProperty for a specific field of the mapped class.
937
     *
938
     * @param string $name
939
     *
940
     * @return \ReflectionProperty
941
     */
942
    public function getReflectionProperty($name)
943
    {
944
        return $this->reflFields[$name];
945
    }
946
947
    /**
948
     * {@inheritDoc}
949
     */
950 842
    public function getName()
951
    {
952 842
        return $this->name;
953
    }
954
955
    /**
956
     * The namespace this Document class belongs to.
957
     *
958
     * @return string $namespace The namespace name.
959
     */
960
    public function getNamespace()
961
    {
962
        return $this->namespace;
963
    }
964
965
    /**
966
     * Returns the database this Document is mapped to.
967
     *
968
     * @return string $db The database name.
969
     */
970 763
    public function getDatabase()
971
    {
972 763
        return $this->db;
973
    }
974
975
    /**
976
     * Set the database this Document is mapped to.
977
     *
978
     * @param string $db The database name
979
     */
980 100
    public function setDatabase($db)
981
    {
982 100
        $this->db = $db;
983 100
    }
984
985
    /**
986
     * Get the collection this Document is mapped to.
987
     *
988
     * @return string $collection The collection name.
989
     */
990 767
    public function getCollection()
991
    {
992 767
        return $this->collection;
993
    }
994
995
    /**
996
     * Sets the collection this Document is mapped to.
997
     *
998
     * @param array|string $name
999
     *
1000
     * @throws \InvalidArgumentException
1001
     */
1002 872
    public function setCollection($name)
1003
    {
1004 872
        if (is_array($name)) {
1005
            if ( ! isset($name['name'])) {
1006
                throw new \InvalidArgumentException('A name key is required when passing an array to setCollection()');
1007
            }
1008
            $this->collectionCapped = isset($name['capped']) ? $name['capped'] : false;
1009
            $this->collectionSize = isset($name['size']) ? $name['size'] : 0;
1010
            $this->collectionMax = isset($name['max']) ? $name['max'] : 0;
1011
            $this->collection = $name['name'];
1012
        } else {
1013 872
            $this->collection = $name;
1014
        }
1015 872
    }
1016
1017
    /**
1018
     * Get whether or not the documents collection is capped.
1019
     *
1020
     * @return boolean
1021
     */
1022 2
    public function getCollectionCapped()
1023
    {
1024 2
        return $this->collectionCapped;
1025
    }
1026
1027
    /**
1028
     * Set whether or not the documents collection is capped.
1029
     *
1030
     * @param boolean $bool
1031
     */
1032 1
    public function setCollectionCapped($bool)
1033
    {
1034 1
        $this->collectionCapped = $bool;
1035 1
    }
1036
1037
    /**
1038
     * Get the collection size
1039
     *
1040
     * @return integer
1041
     */
1042 2
    public function getCollectionSize()
1043
    {
1044 2
        return $this->collectionSize;
1045
    }
1046
1047
    /**
1048
     * Set the collection size.
1049
     *
1050
     * @param integer $size
1051
     */
1052 1
    public function setCollectionSize($size)
1053
    {
1054 1
        $this->collectionSize = $size;
1055 1
    }
1056
1057
    /**
1058
     * Get the collection max.
1059
     *
1060
     * @return integer
1061
     */
1062 2
    public function getCollectionMax()
1063
    {
1064 2
        return $this->collectionMax;
1065
    }
1066
1067
    /**
1068
     * Set the collection max.
1069
     *
1070
     * @param integer $max
1071
     */
1072 1
    public function setCollectionMax($max)
1073
    {
1074 1
        $this->collectionMax = $max;
1075 1
    }
1076
1077
    /**
1078
     * Returns TRUE if this Document is mapped to a collection FALSE otherwise.
1079
     *
1080
     * @return boolean
1081
     */
1082
    public function isMappedToCollection()
1083
    {
1084
        return $this->collection ? true : false;
1085
    }
1086
1087
    /**
1088
     * Returns TRUE if this Document is a file to be stored on the MongoGridFS FALSE otherwise.
1089
     *
1090
     * @return boolean
1091
     */
1092 706
    public function isFile()
1093
    {
1094 706
        return $this->file ? true : false;
1095
    }
1096
1097
    /**
1098
     * Returns the file field name.
1099
     *
1100
     * @return string $file The file field name.
1101
     */
1102 346
    public function getFile()
1103
    {
1104 346
        return $this->file;
1105
    }
1106
1107
    /**
1108
     * Set the field name that stores the grid file.
1109
     *
1110
     * @param string $file
1111
     */
1112 347
    public function setFile($file)
1113
    {
1114 347
        $this->file = $file;
1115 347
    }
1116
1117
    /**
1118
     * Returns the distance field name.
1119
     *
1120
     * @return string $distance The distance field name.
1121
     */
1122
    public function getDistance()
1123
    {
1124
        return $this->distance;
1125
    }
1126
1127
    /**
1128
     * Set the field name that stores the distance.
1129
     *
1130
     * @param string $distance
1131
     */
1132 1
    public function setDistance($distance)
1133
    {
1134 1
        $this->distance = $distance;
1135 1
    }
1136
1137
    /**
1138
     * Map a field.
1139
     *
1140
     * @param array $mapping The mapping information.
1141
     *
1142
     * @return array
1143
     *
1144
     * @throws MappingException
1145
     */
1146 878
    public function mapField(array $mapping)
1147
    {
1148 878
        if ( ! isset($mapping['fieldName']) && isset($mapping['name'])) {
1149 8
            $mapping['fieldName'] = $mapping['name'];
1150
        }
1151 878
        if ( ! isset($mapping['fieldName'])) {
1152
            throw MappingException::missingFieldName($this->name);
1153
        }
1154 878
        if ( ! isset($mapping['name'])) {
1155 870
            $mapping['name'] = $mapping['fieldName'];
1156
        }
1157 878
        if ($this->identifier === $mapping['name'] && empty($mapping['id'])) {
1158 1
            throw MappingException::mustNotChangeIdentifierFieldsType($this->name, $mapping['name']);
1159
        }
1160 877
        if (isset($this->fieldMappings[$mapping['fieldName']])) {
1161
            //throw MappingException::duplicateFieldMapping($this->name, $mapping['fieldName']);
1162
        }
1163 877
        if ($this->discriminatorField !== null && $this->discriminatorField == $mapping['name']) {
1164 1
            throw MappingException::discriminatorFieldConflict($this->name, $this->discriminatorField);
1165
        }
1166 876 View Code Duplication
        if (isset($mapping['targetDocument']) && strpos($mapping['targetDocument'], '\\') === false && strlen($this->namespace)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1167 554
            $mapping['targetDocument'] = $this->namespace . '\\' . $mapping['targetDocument'];
1168
        }
1169 876
        if (isset($mapping['collectionClass'])) {
1170 60 View Code Duplication
            if (strpos($mapping['collectionClass'], '\\') === false && strlen($this->namespace)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1171 59
                $mapping['collectionClass'] = $this->namespace . '\\' . $mapping['collectionClass'];
1172
            }
1173 60
            $mapping['collectionClass'] = ltrim($mapping['collectionClass'], '\\');
1174
        }
1175 876
        if ( ! empty($mapping['collectionClass'])) {
1176 60
            $rColl = new \ReflectionClass($mapping['collectionClass']);
1177 60
            if ( ! $rColl->implementsInterface('Doctrine\\Common\\Collections\\Collection')) {
1178 1
                throw MappingException::collectionClassDoesNotImplementCommonInterface($this->name, $mapping['fieldName'], $mapping['collectionClass']);
1179
            }
1180
        }
1181
1182 875
        if (isset($mapping['discriminatorMap'])) {
1183 58
            foreach ($mapping['discriminatorMap'] as $key => $class) {
1184 58 View Code Duplication
                if (strpos($class, '\\') === false && strlen($this->namespace)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1185 58
                    $mapping['discriminatorMap'][$key] = $this->namespace . '\\' . $class;
1186
                }
1187
            }
1188
        }
1189
1190 875
        if (isset($mapping['cascade']) && isset($mapping['embedded'])) {
1191 1
            throw MappingException::cascadeOnEmbeddedNotAllowed($this->name, $mapping['fieldName']);
1192
        }
1193
1194 874
        $cascades = isset($mapping['cascade']) ? array_map('strtolower', (array) $mapping['cascade']) : array();
1195
1196 874
        if (in_array('all', $cascades) || isset($mapping['embedded'])) {
1197 579
            $cascades = array('remove', 'persist', 'refresh', 'merge', 'detach');
1198
        }
1199
1200 874
        if (isset($mapping['embedded'])) {
1201 544
            unset($mapping['cascade']);
1202 871
        } elseif (isset($mapping['cascade'])) {
1203 378
            $mapping['cascade'] = $cascades;
1204
        }
1205
1206 874
        $mapping['isCascadeRemove'] = in_array('remove', $cascades);
1207 874
        $mapping['isCascadePersist'] = in_array('persist', $cascades);
1208 874
        $mapping['isCascadeRefresh'] = in_array('refresh', $cascades);
1209 874
        $mapping['isCascadeMerge'] = in_array('merge', $cascades);
1210 874
        $mapping['isCascadeDetach'] = in_array('detach', $cascades);
1211
1212 874
        if (isset($mapping['type']) && $mapping['type'] === 'file') {
1213 64
            $mapping['file'] = true;
1214
        }
1215 874
        if (isset($mapping['type']) && $mapping['type'] === 'increment') {
1216 2
            $mapping['strategy'] = self::STORAGE_STRATEGY_INCREMENT;
1217
        }
1218 874 View Code Duplication
        if (isset($mapping['file']) && $mapping['file'] === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1219 64
            $this->file = $mapping['fieldName'];
1220 64
            $mapping['name'] = 'file';
1221
        }
1222 874 View Code Duplication
        if (isset($mapping['distance']) && $mapping['distance'] === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1223 7
            $this->distance = $mapping['fieldName'];
1224
        }
1225 874
        if (isset($mapping['id']) && $mapping['id'] === true) {
1226 853
            $mapping['name'] = '_id';
1227 853
            $this->identifier = $mapping['fieldName'];
1228 853 View Code Duplication
            if (isset($mapping['strategy'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1229 838
                $this->generatorType = constant(ClassMetadata::class . '::GENERATOR_TYPE_' . strtoupper($mapping['strategy']));
1230
            }
1231 853
            $this->generatorOptions = isset($mapping['options']) ? $mapping['options'] : array();
1232 853
            switch ($this->generatorType) {
1233 853
                case self::GENERATOR_TYPE_AUTO:
1234 786
                    $mapping['type'] = 'id';
1235 786
                    break;
1236
                default:
1237 155
                    if ( ! empty($this->generatorOptions['type'])) {
1238 52
                        $mapping['type'] = $this->generatorOptions['type'];
1239 103
                    } elseif (empty($mapping['type'])) {
1240 80
                        $mapping['type'] = $this->generatorType === self::GENERATOR_TYPE_INCREMENT ? 'int_id' : 'custom_id';
1241
                    }
1242
            }
1243 853
            unset($this->generatorOptions['type']);
1244
        }
1245
1246 874
        if ( ! isset($mapping['nullable'])) {
1247 41
            $mapping['nullable'] = false;
1248
        }
1249
1250 874
        if (isset($mapping['reference']) && ! empty($mapping['simple']) && ! isset($mapping['targetDocument'])) {
1251 1
            throw MappingException::simpleReferenceRequiresTargetDocument($this->name, $mapping['fieldName']);
1252
        }
1253
1254 873
        if (isset($mapping['reference']) && empty($mapping['targetDocument']) && empty($mapping['discriminatorMap']) &&
1255 873
                (isset($mapping['mappedBy']) || isset($mapping['inversedBy']))) {
1256 4
            throw MappingException::owningAndInverseReferencesRequireTargetDocument($this->name, $mapping['fieldName']);
1257
        }
1258
1259 869
        if ($this->isEmbeddedDocument && $mapping['type'] === 'many' && CollectionHelper::isAtomic($mapping['strategy'])) {
1260 1
            throw MappingException::atomicCollectionStrategyNotAllowed($mapping['strategy'], $this->name, $mapping['fieldName']);
1261
        }
1262
1263 868 View Code Duplication
        if (isset($mapping['reference']) && $mapping['type'] === 'one') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1264 468
            $mapping['association'] = self::REFERENCE_ONE;
1265
        }
1266 868 View Code Duplication
        if (isset($mapping['reference']) && $mapping['type'] === 'many') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1267 417
            $mapping['association'] = self::REFERENCE_MANY;
1268
        }
1269 868 View Code Duplication
        if (isset($mapping['embedded']) && $mapping['type'] === 'one') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1270 418
            $mapping['association'] = self::EMBED_ONE;
1271
        }
1272 868 View Code Duplication
        if (isset($mapping['embedded']) && $mapping['type'] === 'many') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1273 475
            $mapping['association'] = self::EMBED_MANY;
1274
        }
1275
1276 868
        if (isset($mapping['association']) && ! isset($mapping['targetDocument']) && ! isset($mapping['discriminatorField'])) {
1277 113
            $mapping['discriminatorField'] = self::DEFAULT_DISCRIMINATOR_FIELD;
1278
        }
1279
1280
        /*
1281
        if (isset($mapping['type']) && ($mapping['type'] === 'one' || $mapping['type'] === 'many')) {
1282
            $mapping['type'] = $mapping['type'] === 'one' ? self::ONE : self::MANY;
1283
        }
1284
        */
1285 868
        if (isset($mapping['version'])) {
1286 99
            $mapping['notSaved'] = true;
1287 99
            $this->setVersionMapping($mapping);
1288
        }
1289 868
        if (isset($mapping['lock'])) {
1290 26
            $mapping['notSaved'] = true;
1291 26
            $this->setLockMapping($mapping);
1292
        }
1293 868
        $mapping['isOwningSide'] = true;
1294 868
        $mapping['isInverseSide'] = false;
1295 868
        if (isset($mapping['reference'])) {
1296 531 View Code Duplication
            if (isset($mapping['inversedBy']) && $mapping['inversedBy']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1297 226
                $mapping['isOwningSide'] = true;
1298 226
                $mapping['isInverseSide'] = false;
1299
            }
1300 531 View Code Duplication
            if (isset($mapping['mappedBy']) && $mapping['mappedBy']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1301 271
                $mapping['isInverseSide'] = true;
1302 271
                $mapping['isOwningSide'] = false;
1303
            }
1304 531 View Code Duplication
            if (isset($mapping['repositoryMethod'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1305 206
                $mapping['isInverseSide'] = true;
1306 206
                $mapping['isOwningSide'] = false;
1307
            }
1308 531
            if (!isset($mapping['orphanRemoval'])) {
1309 511
                $mapping['orphanRemoval'] = false;
1310
            }
1311
        }
1312
1313 868
        $this->applyStorageStrategy($mapping);
1314
1315 867
        $this->fieldMappings[$mapping['fieldName']] = $mapping;
1316 867
        if (isset($mapping['association'])) {
1317 670
            $this->associationMappings[$mapping['fieldName']] = $mapping;
1318
        }
1319
1320 867
        return $mapping;
1321
    }
1322
1323
    /**
1324
     * Validates the storage strategy of a mapping for consistency
1325
     * @param array $mapping
1326
     * @throws \Doctrine\ODM\MongoDB\Mapping\MappingException
1327
     */
1328 868
    private function applyStorageStrategy(array &$mapping)
1329
    {
1330 868
        if (! isset($mapping['type']) || isset($mapping['id'])) {
1331 855
            return;
1332
        }
1333
1334
        switch (true) {
1335 821
            case $mapping['type'] == 'int':
1336 821
            case $mapping['type'] == 'float':
1337 821
            case $mapping['type'] == 'increment':
1338 313
                $defaultStrategy = self::STORAGE_STRATEGY_SET;
1339 313
                $allowedStrategies = [self::STORAGE_STRATEGY_SET, self::STORAGE_STRATEGY_INCREMENT];
1340 313
                break;
1341
1342 819
            case $mapping['type'] == 'many':
1343 564
                $defaultStrategy = CollectionHelper::DEFAULT_STRATEGY;
1344
                $allowedStrategies = [
1345 564
                    self::STORAGE_STRATEGY_PUSH_ALL,
1346 564
                    self::STORAGE_STRATEGY_ADD_TO_SET,
1347 564
                    self::STORAGE_STRATEGY_SET,
1348 564
                    self::STORAGE_STRATEGY_SET_ARRAY,
1349 564
                    self::STORAGE_STRATEGY_ATOMIC_SET,
1350 564
                    self::STORAGE_STRATEGY_ATOMIC_SET_ARRAY,
1351
                ];
1352 564
                break;
1353
1354
            default:
1355 813
                $defaultStrategy = self::STORAGE_STRATEGY_SET;
1356 813
                $allowedStrategies = [self::STORAGE_STRATEGY_SET];
1357
        }
1358
1359 821
        if (! isset($mapping['strategy'])) {
1360 814
            $mapping['strategy'] = $defaultStrategy;
1361
        }
1362
1363 821
        if (! in_array($mapping['strategy'], $allowedStrategies)) {
1364
            throw MappingException::invalidStorageStrategy($this->name, $mapping['fieldName'], $mapping['type'], $mapping['strategy']);
1365
        }
1366
1367 821
        if (isset($mapping['reference']) && $mapping['type'] === 'many' && $mapping['isOwningSide']
1368 821
            && ! empty($mapping['sort']) && ! CollectionHelper::usesSet($mapping['strategy'])) {
1369 1
            throw MappingException::referenceManySortMustNotBeUsedWithNonSetCollectionStrategy($this->name, $mapping['fieldName'], $mapping['strategy']);
1370
        }
1371 820
    }
1372
1373
    /**
1374
     * Map a MongoGridFSFile.
1375
     *
1376
     * @param array $mapping The mapping information.
1377
     */
1378
    public function mapFile(array $mapping)
1379
    {
1380
        $mapping['file'] = true;
1381
        $mapping['type'] = 'file';
1382
        $this->mapField($mapping);
1383
    }
1384
1385
    /**
1386
     * Map a single embedded document.
1387
     *
1388
     * @param array $mapping The mapping information.
1389
     */
1390 6
    public function mapOneEmbedded(array $mapping)
1391
    {
1392 6
        $mapping['embedded'] = true;
1393 6
        $mapping['type'] = 'one';
1394 6
        $this->mapField($mapping);
1395 5
    }
1396
1397
    /**
1398
     * Map a collection of embedded documents.
1399
     *
1400
     * @param array $mapping The mapping information.
1401
     */
1402 3
    public function mapManyEmbedded(array $mapping)
1403
    {
1404 3
        $mapping['embedded'] = true;
1405 3
        $mapping['type'] = 'many';
1406 3
        $this->mapField($mapping);
1407 3
    }
1408
1409
    /**
1410
     * Map a single document reference.
1411
     *
1412
     * @param array $mapping The mapping information.
1413
     */
1414 8
    public function mapOneReference(array $mapping)
1415
    {
1416 8
        $mapping['reference'] = true;
1417 8
        $mapping['type'] = 'one';
1418 8
        $this->mapField($mapping);
1419 8
    }
1420
1421
    /**
1422
     * Map a collection of document references.
1423
     *
1424
     * @param array $mapping The mapping information.
1425
     */
1426 8
    public function mapManyReference(array $mapping)
1427
    {
1428 8
        $mapping['reference'] = true;
1429 8
        $mapping['type'] = 'many';
1430 8
        $this->mapField($mapping);
1431 8
    }
1432
1433
    /**
1434
     * INTERNAL:
1435
     * Adds a field mapping without completing/validating it.
1436
     * This is mainly used to add inherited field mappings to derived classes.
1437
     *
1438
     * @param array $fieldMapping
1439
     */
1440 125
    public function addInheritedFieldMapping(array $fieldMapping)
1441
    {
1442 125
        $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping;
1443
1444 125
        if (isset($fieldMapping['association'])) {
1445 82
            $this->associationMappings[$fieldMapping['fieldName']] = $fieldMapping;
1446
        }
1447 125
    }
1448
1449
    /**
1450
     * INTERNAL:
1451
     * Adds an association mapping without completing/validating it.
1452
     * This is mainly used to add inherited association mappings to derived classes.
1453
     *
1454
     * @param array $mapping
1455
     *
1456
     * @return void
1457
     *
1458
     * @throws MappingException
1459
     */
1460 83
    public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/)
1461
    {
1462 83
        $this->associationMappings[$mapping['fieldName']] = $mapping;
1463 83
    }
1464
1465
    /**
1466
     * Checks whether the class has a mapped association with the given field name.
1467
     *
1468
     * @param string $fieldName
1469
     * @return boolean
1470
     */
1471 7
    public function hasReference($fieldName)
1472
    {
1473 7
        return isset($this->fieldMappings[$fieldName]['reference']);
1474
    }
1475
1476
    /**
1477
     * Checks whether the class has a mapped embed with the given field name.
1478
     *
1479
     * @param string $fieldName
1480
     * @return boolean
1481
     */
1482 5
    public function hasEmbed($fieldName)
1483
    {
1484 5
        return isset($this->fieldMappings[$fieldName]['embedded']);
1485
    }
1486
1487
    /**
1488
     * {@inheritDoc}
1489
     *
1490
     * Checks whether the class has a mapped association (embed or reference) with the given field name.
1491
     */
1492 7
    public function hasAssociation($fieldName)
1493
    {
1494 7
        return $this->hasReference($fieldName) || $this->hasEmbed($fieldName);
1495
    }
1496
1497
    /**
1498
     * {@inheritDoc}
1499
     *
1500
     * Checks whether the class has a mapped reference or embed for the specified field and
1501
     * is a single valued association.
1502
     */
1503
    public function isSingleValuedAssociation($fieldName)
1504
    {
1505
        return $this->isSingleValuedReference($fieldName) || $this->isSingleValuedEmbed($fieldName);
1506
    }
1507
1508
    /**
1509
     * {@inheritDoc}
1510
     *
1511
     * Checks whether the class has a mapped reference or embed for the specified field and
1512
     * is a collection valued association.
1513
     */
1514
    public function isCollectionValuedAssociation($fieldName)
1515
    {
1516
        return $this->isCollectionValuedReference($fieldName) || $this->isCollectionValuedEmbed($fieldName);
1517
    }
1518
1519
    /**
1520
     * Checks whether the class has a mapped association for the specified field
1521
     * and if yes, checks whether it is a single-valued association (to-one).
1522
     *
1523
     * @param string $fieldName
1524
     * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise.
1525
     */
1526
    public function isSingleValuedReference($fieldName)
1527
    {
1528
        return isset($this->fieldMappings[$fieldName]['association']) &&
1529
            $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_ONE;
1530
    }
1531
1532
    /**
1533
     * Checks whether the class has a mapped association for the specified field
1534
     * and if yes, checks whether it is a collection-valued association (to-many).
1535
     *
1536
     * @param string $fieldName
1537
     * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise.
1538
     */
1539
    public function isCollectionValuedReference($fieldName)
1540
    {
1541
        return isset($this->fieldMappings[$fieldName]['association']) &&
1542
            $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_MANY;
1543
    }
1544
1545
    /**
1546
     * Checks whether the class has a mapped embedded document for the specified field
1547
     * and if yes, checks whether it is a single-valued association (to-one).
1548
     *
1549
     * @param string $fieldName
1550
     * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise.
1551
     */
1552
    public function isSingleValuedEmbed($fieldName)
1553
    {
1554
        return isset($this->fieldMappings[$fieldName]['association']) &&
1555
            $this->fieldMappings[$fieldName]['association'] === self::EMBED_ONE;
1556
    }
1557
1558
    /**
1559
     * Checks whether the class has a mapped embedded document for the specified field
1560
     * and if yes, checks whether it is a collection-valued association (to-many).
1561
     *
1562
     * @param string $fieldName
1563
     * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise.
1564
     */
1565
    public function isCollectionValuedEmbed($fieldName)
1566
    {
1567
        return isset($this->fieldMappings[$fieldName]['association']) &&
1568
            $this->fieldMappings[$fieldName]['association'] === self::EMBED_MANY;
1569
    }
1570
1571
    /**
1572
     * Sets the ID generator used to generate IDs for instances of this class.
1573
     *
1574
     * @param \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator $generator
1575
     */
1576 770
    public function setIdGenerator($generator)
1577
    {
1578 770
        $this->idGenerator = $generator;
1579 770
    }
1580
1581
    /**
1582
     * Casts the identifier to its portable PHP type.
1583
     *
1584
     * @param mixed $id
1585
     * @return mixed $id
1586
     */
1587 593
    public function getPHPIdentifierValue($id)
1588
    {
1589 593
        $idType = $this->fieldMappings[$this->identifier]['type'];
1590 593
        return Type::getType($idType)->convertToPHPValue($id);
1591
    }
1592
1593
    /**
1594
     * Casts the identifier to its database type.
1595
     *
1596
     * @param mixed $id
1597
     * @return mixed $id
1598
     */
1599 655
    public function getDatabaseIdentifierValue($id)
1600
    {
1601 655
        $idType = $this->fieldMappings[$this->identifier]['type'];
1602 655
        return Type::getType($idType)->convertToDatabaseValue($id);
1603
    }
1604
1605
    /**
1606
     * Sets the document identifier of a document.
1607
     *
1608
     * The value will be converted to a PHP type before being set.
1609
     *
1610
     * @param object $document
1611
     * @param mixed $id
1612
     */
1613 526
    public function setIdentifierValue($document, $id)
1614
    {
1615 526
        $id = $this->getPHPIdentifierValue($id);
1616 526
        $this->reflFields[$this->identifier]->setValue($document, $id);
1617 526
    }
1618
1619
    /**
1620
     * Gets the document identifier as a PHP type.
1621
     *
1622
     * @param object $document
1623
     * @return mixed $id
1624
     */
1625 606
    public function getIdentifierValue($document)
1626
    {
1627 606
        return $this->reflFields[$this->identifier]->getValue($document);
1628
    }
1629
1630
    /**
1631
     * {@inheritDoc}
1632
     *
1633
     * Since MongoDB only allows exactly one identifier field this is a proxy
1634
     * to {@see getIdentifierValue()} and returns an array with the identifier
1635
     * field as a key.
1636
     */
1637
    public function getIdentifierValues($object)
1638
    {
1639
        return array($this->identifier => $this->getIdentifierValue($object));
1640
    }
1641
1642
    /**
1643
     * Get the document identifier object as a database type.
1644
     *
1645
     * @param object $document
1646
     *
1647
     * @return \MongoId $id The MongoID object.
1648
     */
1649 32
    public function getIdentifierObject($document)
1650
    {
1651 32
        return $this->getDatabaseIdentifierValue($this->getIdentifierValue($document));
1652
    }
1653
1654
    /**
1655
     * Sets the specified field to the specified value on the given document.
1656
     *
1657
     * @param object $document
1658
     * @param string $field
1659
     * @param mixed $value
1660
     */
1661 7
    public function setFieldValue($document, $field, $value)
1662
    {
1663 7
        if ($document instanceof Proxy && ! $document->__isInitialized()) {
1664
            //property changes to an uninitialized proxy will not be tracked or persisted,
1665
            //so the proxy needs to be loaded first.
1666 1
            $document->__load();
1667
        }
1668
1669 7
        $this->reflFields[$field]->setValue($document, $value);
1670 7
    }
1671
1672
    /**
1673
     * Gets the specified field's value off the given document.
1674
     *
1675
     * @param object $document
1676
     * @param string $field
1677
     *
1678
     * @return mixed
1679
     */
1680 25
    public function getFieldValue($document, $field)
1681
    {
1682 25
        if ($document instanceof Proxy && $field !== $this->identifier && ! $document->__isInitialized()) {
1683 1
            $document->__load();
1684
        }
1685
1686 25
        return $this->reflFields[$field]->getValue($document);
1687
    }
1688
1689
    /**
1690
     * Gets the mapping of a field.
1691
     *
1692
     * @param string $fieldName  The field name.
1693
     *
1694
     * @return array  The field mapping.
1695
     *
1696
     * @throws MappingException if the $fieldName is not found in the fieldMappings array
1697
     */
1698 84
    public function getFieldMapping($fieldName)
1699
    {
1700 84
        if ( ! isset($this->fieldMappings[$fieldName])) {
1701 6
            throw MappingException::mappingNotFound($this->name, $fieldName);
1702
        }
1703 82
        return $this->fieldMappings[$fieldName];
1704
    }
1705
1706
    /**
1707
     * Gets mappings of fields holding embedded document(s).
1708
     *
1709
     * @return array of field mappings
1710
     */
1711 568
    public function getEmbeddedFieldsMappings()
1712
    {
1713 568
        return array_filter(
1714 568
            $this->associationMappings,
1715
            function($assoc) { return ! empty($assoc['embedded']); }
1716
        );
1717
    }
1718
1719
    /**
1720
     * Gets the field mapping by its DB name.
1721
     * E.g. it returns identifier's mapping when called with _id.
1722
     *
1723
     * @param string $dbFieldName
1724
     *
1725
     * @return array
1726
     * @throws MappingException
1727
     */
1728 2
    public function getFieldMappingByDbFieldName($dbFieldName)
1729
    {
1730 2
        foreach ($this->fieldMappings as $mapping) {
1731 2
            if ($mapping['name'] == $dbFieldName) {
1732 2
                return $mapping;
1733
            }
1734
        }
1735
1736
        throw MappingException::mappingNotFoundByDbName($this->name, $dbFieldName);
1737
    }
1738
1739
    /**
1740
     * Check if the field is not null.
1741
     *
1742
     * @param string $fieldName  The field name
1743
     *
1744
     * @return boolean  TRUE if the field is not null, FALSE otherwise.
1745
     */
1746 1
    public function isNullable($fieldName)
1747
    {
1748 1
        $mapping = $this->getFieldMapping($fieldName);
1749 1
        if ($mapping !== false) {
1750 1
            return isset($mapping['nullable']) && $mapping['nullable'] == true;
1751
        }
1752
        return false;
1753
    }
1754
1755
    /**
1756
     * Checks whether the document has a discriminator field and value configured.
1757
     *
1758
     * @return boolean
1759
     */
1760 487
    public function hasDiscriminator()
1761
    {
1762 487
        return isset($this->discriminatorField, $this->discriminatorValue);
1763
    }
1764
1765
    /**
1766
     * Sets the type of Id generator to use for the mapped class.
1767
     *
1768
     * @param string $generatorType Generator type.
1769
     */
1770 352
    public function setIdGeneratorType($generatorType)
1771
    {
1772 352
        $this->generatorType = $generatorType;
1773 352
    }
1774
1775
    /**
1776
     * Sets the Id generator options.
1777
     *
1778
     * @param array $generatorOptions Generator options.
1779
     */
1780
    public function setIdGeneratorOptions($generatorOptions)
1781
    {
1782
        $this->generatorOptions = $generatorOptions;
1783
    }
1784
1785
    /**
1786
     * @return boolean
1787
     */
1788 574
    public function isInheritanceTypeNone()
1789
    {
1790 574
        return $this->inheritanceType == self::INHERITANCE_TYPE_NONE;
1791
    }
1792
1793
    /**
1794
     * Checks whether the mapped class uses the SINGLE_COLLECTION inheritance mapping strategy.
1795
     *
1796
     * @return boolean
1797
     */
1798 345
    public function isInheritanceTypeSingleCollection()
1799
    {
1800 345
        return $this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_COLLECTION;
1801
    }
1802
1803
    /**
1804
     * Checks whether the mapped class uses the COLLECTION_PER_CLASS inheritance mapping strategy.
1805
     *
1806
     * @return boolean
1807
     */
1808
    public function isInheritanceTypeCollectionPerClass()
1809
    {
1810
        return $this->inheritanceType == self::INHERITANCE_TYPE_COLLECTION_PER_CLASS;
1811
    }
1812
1813
    /**
1814
     * Sets the mapped subclasses of this class.
1815
     *
1816
     * @param string[] $subclasses The names of all mapped subclasses.
1817
     */
1818 2 View Code Duplication
    public function setSubclasses(array $subclasses)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1819
    {
1820 2
        foreach ($subclasses as $subclass) {
1821 2
            if (strpos($subclass, '\\') === false && strlen($this->namespace)) {
1822 1
                $this->subClasses[] = $this->namespace . '\\' . $subclass;
1823
            } else {
1824 2
                $this->subClasses[] = $subclass;
1825
            }
1826
        }
1827 2
    }
1828
1829
    /**
1830
     * Sets the parent class names.
1831
     * Assumes that the class names in the passed array are in the order:
1832
     * directParent -> directParentParent -> directParentParentParent ... -> root.
1833
     *
1834
     * @param string[] $classNames
1835
     */
1836 825
    public function setParentClasses(array $classNames)
1837
    {
1838 825
        $this->parentClasses = $classNames;
1839
1840 825
        if (count($classNames) > 0) {
1841 110
            $this->rootDocumentName = array_pop($classNames);
1842
        }
1843 825
    }
1844
1845
    /**
1846
     * Checks whether the class will generate a new \MongoId instance for us.
1847
     *
1848
     * @return boolean TRUE if the class uses the AUTO generator, FALSE otherwise.
1849
     */
1850
    public function isIdGeneratorAuto()
1851
    {
1852
        return $this->generatorType == self::GENERATOR_TYPE_AUTO;
1853
    }
1854
1855
    /**
1856
     * Checks whether the class will use a collection to generate incremented identifiers.
1857
     *
1858
     * @return boolean TRUE if the class uses the INCREMENT generator, FALSE otherwise.
1859
     */
1860
    public function isIdGeneratorIncrement()
1861
    {
1862
        return $this->generatorType == self::GENERATOR_TYPE_INCREMENT;
1863
    }
1864
1865
    /**
1866
     * Checks whether the class will generate a uuid id.
1867
     *
1868
     * @return boolean TRUE if the class uses the UUID generator, FALSE otherwise.
1869
     */
1870
    public function isIdGeneratorUuid()
1871
    {
1872
        return $this->generatorType == self::GENERATOR_TYPE_UUID;
1873
    }
1874
1875
    /**
1876
     * Checks whether the class uses no id generator.
1877
     *
1878
     * @return boolean TRUE if the class does not use any id generator, FALSE otherwise.
1879
     */
1880
    public function isIdGeneratorNone()
1881
    {
1882
        return $this->generatorType == self::GENERATOR_TYPE_NONE;
1883
    }
1884
1885
    /**
1886
     * Sets the version field mapping used for versioning. Sets the default
1887
     * value to use depending on the column type.
1888
     *
1889
     * @param array $mapping   The version field mapping array
1890
     *
1891
     * @throws LockException
1892
     */
1893 99
    public function setVersionMapping(array &$mapping)
1894
    {
1895 99
        if ($mapping['type'] !== 'int' && $mapping['type'] !== 'date') {
1896 1
            throw LockException::invalidVersionFieldType($mapping['type']);
1897
        }
1898
1899 98
        $this->isVersioned  = true;
1900 98
        $this->versionField = $mapping['fieldName'];
1901 98
    }
1902
1903
    /**
1904
     * Sets whether this class is to be versioned for optimistic locking.
1905
     *
1906
     * @param boolean $bool
1907
     */
1908 346
    public function setVersioned($bool)
1909
    {
1910 346
        $this->isVersioned = $bool;
1911 346
    }
1912
1913
    /**
1914
     * Sets the name of the field that is to be used for versioning if this class is
1915
     * versioned for optimistic locking.
1916
     *
1917
     * @param string $versionField
1918
     */
1919 346
    public function setVersionField($versionField)
1920
    {
1921 346
        $this->versionField = $versionField;
1922 346
    }
1923
1924
    /**
1925
     * Sets the version field mapping used for versioning. Sets the default
1926
     * value to use depending on the column type.
1927
     *
1928
     * @param array $mapping   The version field mapping array
1929
     *
1930
     * @throws \Doctrine\ODM\MongoDB\LockException
1931
     */
1932 26
    public function setLockMapping(array &$mapping)
1933
    {
1934 26
        if ($mapping['type'] !== 'int') {
1935 1
            throw LockException::invalidLockFieldType($mapping['type']);
1936
        }
1937
1938 25
        $this->isLockable = true;
1939 25
        $this->lockField = $mapping['fieldName'];
1940 25
    }
1941
1942
    /**
1943
     * Sets whether this class is to allow pessimistic locking.
1944
     *
1945
     * @param boolean $bool
1946
     */
1947
    public function setLockable($bool)
1948
    {
1949
        $this->isLockable = $bool;
1950
    }
1951
1952
    /**
1953
     * Sets the name of the field that is to be used for storing whether a document
1954
     * is currently locked or not.
1955
     *
1956
     * @param string $lockField
1957
     */
1958
    public function setLockField($lockField)
1959
    {
1960
        $this->lockField = $lockField;
1961
    }
1962
1963
    /**
1964
     * {@inheritDoc}
1965
     */
1966
    public function getFieldNames()
1967
    {
1968
        return array_keys($this->fieldMappings);
1969
    }
1970
1971
    /**
1972
     * {@inheritDoc}
1973
     */
1974
    public function getAssociationNames()
1975
    {
1976
        return array_keys($this->associationMappings);
1977
    }
1978
1979
    /**
1980
     * {@inheritDoc}
1981
     */
1982 39
    public function getTypeOfField($fieldName)
1983
    {
1984 39
        return isset($this->fieldMappings[$fieldName]) ?
1985 39
            $this->fieldMappings[$fieldName]['type'] : null;
1986
    }
1987
1988
    /**
1989
     * {@inheritDoc}
1990
     */
1991 6
    public function getAssociationTargetClass($assocName)
1992
    {
1993 6
        if ( ! isset($this->associationMappings[$assocName])) {
1994 3
            throw new InvalidArgumentException("Association name expected, '" . $assocName . "' is not an association.");
1995
        }
1996
1997 3
        return $this->associationMappings[$assocName]['targetDocument'];
1998
    }
1999
2000
    /**
2001
     * {@inheritDoc}
2002
     */
2003
    public function isAssociationInverseSide($fieldName)
2004
    {
2005
        throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.');
2006
    }
2007
2008
    /**
2009
     * {@inheritDoc}
2010
     */
2011
    public function getAssociationMappedByTargetField($fieldName)
2012
    {
2013
        throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.');
2014
    }
2015
}
2016