Completed
Push — master ( 86e4a2...748e61 )
by Andreas
12:28 queued 06:19
created

DocumentManager   D

Complexity

Total Complexity 72

Size/Duplication

Total Lines 746
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 12

Test Coverage

Coverage 92.65%

Importance

Changes 0
Metric Value
wmc 72
lcom 3
cbo 12
dl 0
loc 746
ccs 189
cts 204
cp 0.9265
rs 4.6153
c 0
b 0
f 0

37 Methods

Rating   Name   Duplication   Size   Complexity  
A detach() 0 7 2
A lock() 0 7 2
A unlock() 0 7 2
A getRepository() 0 4 1
B __construct() 0 37 5
A getProxyFactory() 0 4 1
A create() 0 4 1
A getEventManager() 0 4 1
A getClient() 0 4 1
A getMetadataFactory() 0 4 1
A initializeObject() 0 4 1
A getUnitOfWork() 0 4 1
A getHydratorFactory() 0 4 1
A getSchemaManager() 0 4 1
A getClassMetadata() 0 4 1
A getDocumentDatabase() 0 16 4
A getDocumentDatabases() 0 4 1
B getDocumentCollection() 0 24 4
A getDocumentCollections() 0 4 1
A createQueryBuilder() 0 4 1
A createAggregationBuilder() 0 4 1
A persist() 0 8 2
A remove() 0 8 2
A refresh() 0 8 2
A merge() 0 8 2
A flush() 0 5 1
A getReference() 0 16 2
A getPartialReference() 0 15 2
A find() 0 4 1
A clear() 0 4 1
A close() 0 5 1
A contains() 0 9 4
A getConfiguration() 0 4 1
C createReference() 0 81 12
A errorIfClosed() 0 6 2
A isOpen() 0 4 1
A getFilterCollection() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like DocumentManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DocumentManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\Common\Persistence\ObjectManager;
9
use Doctrine\Common\Persistence\ObjectRepository;
10
use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory;
11
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
12
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
13
use Doctrine\ODM\MongoDB\Mapping\MappingException;
14
use Doctrine\ODM\MongoDB\Proxy\ProxyFactory;
15
use Doctrine\ODM\MongoDB\Query\FilterCollection;
16
use Doctrine\ODM\MongoDB\Repository\RepositoryFactory;
17
use MongoDB\Client;
18
use MongoDB\Collection;
19
use MongoDB\Database;
20
use MongoDB\Driver\ReadPreference;
21
use function array_search;
22
use function get_class;
23
use function gettype;
24
use function is_object;
25
use function ltrim;
26
use function sprintf;
27
28
/**
29
 * The DocumentManager class is the central access point for managing the
30
 * persistence of documents.
31
 *
32
 *     <?php
33
 *
34
 *     $config = new Configuration();
35
 *     $dm = DocumentManager::create(new Connection(), $config);
36
 *
37
 */
38
class DocumentManager implements ObjectManager
39
{
40
    /**
41
     * The Doctrine MongoDB connection instance.
42
     *
43
     * @var Client
44
     */
45
    private $client;
46
47
    /**
48
     * The used Configuration.
49
     *
50
     * @var Configuration
51
     */
52
    private $config;
53
54
    /**
55
     * The metadata factory, used to retrieve the ODM metadata of document classes.
56
     *
57
     * @var ClassMetadataFactory
58
     */
59
    private $metadataFactory;
60
61
    /**
62
     * The UnitOfWork used to coordinate object-level transactions.
63
     *
64
     * @var UnitOfWork
65
     */
66
    private $unitOfWork;
67
68
    /**
69
     * The event manager that is the central point of the event system.
70
     *
71
     * @var EventManager
72
     */
73
    private $eventManager;
74
75
    /**
76
     * The Hydrator factory instance.
77
     *
78
     * @var HydratorFactory
79
     */
80
    private $hydratorFactory;
81
82
    /**
83
     * The Proxy factory instance.
84
     *
85
     * @var ProxyFactory
86
     */
87
    private $proxyFactory;
88
89
    /**
90
     * The repository factory used to create dynamic repositories.
91
     *
92
     * @var RepositoryFactory
93
     */
94
    private $repositoryFactory;
95
96
    /**
97
     * SchemaManager instance
98
     *
99
     * @var SchemaManager
100
     */
101
    private $schemaManager;
102
103
    /**
104
     * Array of cached document database instances that are lazily loaded.
105
     *
106
     * @var Database[]
107
     */
108
    private $documentDatabases = [];
109
110
    /**
111
     * Array of cached document collection instances that are lazily loaded.
112
     *
113
     * @var Collection[]
114
     */
115
    private $documentCollections = [];
116
117
    /**
118
     * Whether the DocumentManager is closed or not.
119
     *
120
     * @var bool
121
     */
122
    private $closed = false;
123
124
    /**
125
     * Collection of query filters.
126
     *
127
     * @var FilterCollection
128
     */
129
    private $filterCollection;
130
131
    /**
132
     * Creates a new Document that operates on the given Mongo connection
133
     * and uses the given Configuration.
134
     *
135
     */
136 1576
    protected function __construct(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null)
137
    {
138 1576
        $this->config = $config ?: new Configuration();
139 1576
        $this->eventManager = $eventManager ?: new EventManager();
140 1576
        $this->client = $client ?: new Client('mongodb://127.0.0.1', [], ['typeMap' => ['root' => 'array', 'document' => 'array']]);
141
142 1576
        $metadataFactoryClassName = $this->config->getClassMetadataFactoryName();
143 1576
        $this->metadataFactory = new $metadataFactoryClassName();
144 1576
        $this->metadataFactory->setDocumentManager($this);
145 1576
        $this->metadataFactory->setConfiguration($this->config);
146
147 1576
        $cacheDriver = $this->config->getMetadataCacheImpl();
148 1576
        if ($cacheDriver) {
149
            $this->metadataFactory->setCacheDriver($cacheDriver);
150
        }
151
152 1576
        $hydratorDir = $this->config->getHydratorDir();
153 1576
        $hydratorNs = $this->config->getHydratorNamespace();
154 1576
        $this->hydratorFactory = new HydratorFactory(
155 1576
            $this,
156 1576
            $this->eventManager,
157 1576
            $hydratorDir,
158 1576
            $hydratorNs,
159 1576
            $this->config->getAutoGenerateHydratorClasses()
160
        );
161
162 1576
        $this->unitOfWork = new UnitOfWork($this, $this->eventManager, $this->hydratorFactory);
163 1576
        $this->hydratorFactory->setUnitOfWork($this->unitOfWork);
164 1576
        $this->schemaManager = new SchemaManager($this, $this->metadataFactory);
165 1576
        $this->proxyFactory = new ProxyFactory(
166 1576
            $this,
167 1576
            $this->config->getProxyDir(),
168 1576
            $this->config->getProxyNamespace(),
169 1576
            $this->config->getAutoGenerateProxyClasses()
170
        );
171 1576
        $this->repositoryFactory = $this->config->getRepositoryFactory();
172 1576
    }
173
174
    /**
175
     * Gets the proxy factory used by the DocumentManager to create document proxies.
176
     *
177
     * @return ProxyFactory
178
     */
179 1
    public function getProxyFactory()
180
    {
181 1
        return $this->proxyFactory;
182
    }
183
184
    /**
185
     * Creates a new Document that operates on the given Mongo connection
186
     * and uses the given Configuration.
187
     *
188
     * @static
189
     * @return DocumentManager
190
     */
191 1576
    public static function create(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null)
192
    {
193 1576
        return new static($client, $config, $eventManager);
194
    }
195
196
    /**
197
     * Gets the EventManager used by the DocumentManager.
198
     *
199
     * @return EventManager
200
     */
201 1619
    public function getEventManager()
202
    {
203 1619
        return $this->eventManager;
204
    }
205
206
    /**
207
     * Gets the MongoDB client instance that this DocumentManager wraps.
208
     *
209
     * @return Client
210
     */
211 1576
    public function getClient()
212
    {
213 1576
        return $this->client;
214
    }
215
216
    /**
217
     * Gets the metadata factory used to gather the metadata of classes.
218
     *
219
     * @return ClassMetadataFactory
220
     */
221 1576
    public function getMetadataFactory()
222
    {
223 1576
        return $this->metadataFactory;
224
    }
225
226
    /**
227
     * Helper method to initialize a lazy loading proxy or persistent collection.
228
     *
229
     * This method is a no-op for other objects.
230
     *
231
     * @param object $obj
232
     */
233
    public function initializeObject($obj)
234
    {
235
        $this->unitOfWork->initializeObject($obj);
236
    }
237
238
    /**
239
     * Gets the UnitOfWork used by the DocumentManager to coordinate operations.
240
     *
241
     * @return UnitOfWork
242
     */
243 1582
    public function getUnitOfWork()
244
    {
245 1582
        return $this->unitOfWork;
246
    }
247
248
    /**
249
     * Gets the Hydrator factory used by the DocumentManager to generate and get hydrators
250
     * for each type of document.
251
     *
252
     * @return HydratorFactory
253
     */
254 66
    public function getHydratorFactory()
255
    {
256 66
        return $this->hydratorFactory;
257
    }
258
259
    /**
260
     * Returns SchemaManager, used to create/drop indexes/collections/databases.
261
     *
262
     * @return SchemaManager
263
     */
264 19
    public function getSchemaManager()
265
    {
266 19
        return $this->schemaManager;
267
    }
268
269
    /**
270
     * Returns the metadata for a class.
271
     *
272
     * @param string $className The class name.
273
     * @return ClassMetadata
274
     * @internal Performance-sensitive method.
275
     */
276 1318
    public function getClassMetadata($className)
277
    {
278 1318
        return $this->metadataFactory->getMetadataFor(ltrim($className, '\\'));
279
    }
280
281
    /**
282
     * Returns the MongoDB instance for a class.
283
     *
284
     * @param string $className The class name.
285
     * @return Database
286
     */
287 1252
    public function getDocumentDatabase($className)
288
    {
289 1252
        $className = ltrim($className, '\\');
290
291 1252
        if (isset($this->documentDatabases[$className])) {
292 36
            return $this->documentDatabases[$className];
293
        }
294
295 1248
        $metadata = $this->metadataFactory->getMetadataFor($className);
296 1248
        $db = $metadata->getDatabase();
297 1248
        $db = $db ?: $this->config->getDefaultDB();
298 1248
        $db = $db ?: 'doctrine';
299 1248
        $this->documentDatabases[$className] = $this->client->selectDatabase($db);
300
301 1248
        return $this->documentDatabases[$className];
302
    }
303
304
    /**
305
     * Gets the array of instantiated document database instances.
306
     *
307
     * @return Database[]
308
     */
309
    public function getDocumentDatabases()
310
    {
311
        return $this->documentDatabases;
312
    }
313
314
    /**
315
     * Returns the MongoCollection instance for a class.
316
     *
317
     * @param string $className The class name.
318
     * @throws MongoDBException When the $className param is not mapped to a collection
319
     * @return Collection
320
     */
321 1254
    public function getDocumentCollection($className)
322
    {
323 1254
        $className = ltrim($className, '\\');
324
325 1254
        $metadata = $this->metadataFactory->getMetadataFor($className);
326 1254
        $collectionName = $metadata->getCollection();
327
328 1254
        if (! $collectionName) {
329
            throw MongoDBException::documentNotMappedToCollection($className);
330
        }
331
332 1254
        if (! isset($this->documentCollections[$className])) {
333 1244
            $db = $this->getDocumentDatabase($className);
334
335 1244
            $options = [];
336 1244
            if ($metadata->readPreference !== null) {
337 3
                $options['readPreference'] = new ReadPreference($metadata->readPreference, $metadata->readPreferenceTags);
338
            }
339
340 1244
            $this->documentCollections[$className] = $db->selectCollection($collectionName, $options);
341
        }
342
343 1254
        return $this->documentCollections[$className];
344
    }
345
346
    /**
347
     * Gets the array of instantiated document collection instances.
348
     *
349
     * @return Collection[]
350
     */
351
    public function getDocumentCollections()
352
    {
353
        return $this->documentCollections;
354
    }
355
356
    /**
357
     * Create a new Query instance for a class.
358
     *
359
     * @param string $documentName The document class name.
360
     * @return Query\Builder
361
     */
362 178
    public function createQueryBuilder($documentName = null)
363
    {
364 178
        return new Query\Builder($this, $documentName);
365
    }
366
367
    /**
368
     * Creates a new aggregation builder instance for a class.
369
     *
370
     * @param string $documentName The document class name.
371
     * @return Aggregation\Builder
372
     */
373 41
    public function createAggregationBuilder($documentName)
374
    {
375 41
        return new Aggregation\Builder($this, $documentName);
376
    }
377
378
    /**
379
     * Tells the DocumentManager to make an instance managed and persistent.
380
     *
381
     * The document will be entered into the database at or before transaction
382
     * commit or as a result of the flush operation.
383
     *
384
     * NOTE: The persist operation always considers documents that are not yet known to
385
     * this DocumentManager as NEW. Do not pass detached documents to the persist operation.
386
     *
387
     * @param object $document The instance to make managed and persistent.
388
     * @throws \InvalidArgumentException When the given $document param is not an object
389
     */
390 578
    public function persist($document)
391
    {
392 578
        if (! is_object($document)) {
393 1
            throw new \InvalidArgumentException(gettype($document));
394
        }
395 577
        $this->errorIfClosed();
396 576
        $this->unitOfWork->persist($document);
397 572
    }
398
399
    /**
400
     * Removes a document instance.
401
     *
402
     * A removed document will be removed from the database at or before transaction commit
403
     * or as a result of the flush operation.
404
     *
405
     * @param object $document The document instance to remove.
406
     * @throws \InvalidArgumentException when the $document param is not an object
407
     */
408 23
    public function remove($document)
409
    {
410 23
        if (! is_object($document)) {
411 1
            throw new \InvalidArgumentException(gettype($document));
412
        }
413 22
        $this->errorIfClosed();
414 21
        $this->unitOfWork->remove($document);
415 21
    }
416
417
    /**
418
     * Refreshes the persistent state of a document from the database,
419
     * overriding any local changes that have not yet been persisted.
420
     *
421
     * @param object $document The document to refresh.
422
     * @throws \InvalidArgumentException When the given $document param is not an object
423
     */
424 23
    public function refresh($document)
425
    {
426 23
        if (! is_object($document)) {
427 1
            throw new \InvalidArgumentException(gettype($document));
428
        }
429 22
        $this->errorIfClosed();
430 21
        $this->unitOfWork->refresh($document);
431 20
    }
432
433
    /**
434
     * Detaches a document from the DocumentManager, causing a managed document to
435
     * become detached.  Unflushed changes made to the document if any
436
     * (including removal of the document), will not be synchronized to the database.
437
     * Documents which previously referenced the detached document will continue to
438
     * reference it.
439
     *
440
     * @param object $document The document to detach.
441
     * @throws \InvalidArgumentException when the $document param is not an object
442
     */
443 11
    public function detach($document)
444
    {
445 11
        if (! is_object($document)) {
446 1
            throw new \InvalidArgumentException(gettype($document));
447
        }
448 10
        $this->unitOfWork->detach($document);
449 10
    }
450
451
    /**
452
     * Merges the state of a detached document into the persistence context
453
     * of this DocumentManager and returns the managed copy of the document.
454
     * The document passed to merge will not become associated/managed with this DocumentManager.
455
     *
456
     * @param object $document The detached document to merge into the persistence context.
457
     * @throws LockException
458
     * @throws \InvalidArgumentException if the $document param is not an object
459
     * @return object The managed copy of the document.
460
     */
461 14
    public function merge($document)
462
    {
463 14
        if (! is_object($document)) {
464 1
            throw new \InvalidArgumentException(gettype($document));
465
        }
466 13
        $this->errorIfClosed();
467 12
        return $this->unitOfWork->merge($document);
468
    }
469
470
    /**
471
     * Acquire a lock on the given document.
472
     *
473
     * @param object $document
474
     * @param int    $lockMode
475
     * @param int    $lockVersion
476
     * @throws \InvalidArgumentException
477
     */
478 8
    public function lock($document, $lockMode, $lockVersion = null)
479
    {
480 8
        if (! is_object($document)) {
481
            throw new \InvalidArgumentException(gettype($document));
482
        }
483 8
        $this->unitOfWork->lock($document, $lockMode, $lockVersion);
484 5
    }
485
486
    /**
487
     * Releases a lock on the given document.
488
     *
489
     * @param object $document
490
     * @throws \InvalidArgumentException if the $document param is not an object
491
     */
492 1
    public function unlock($document)
493
    {
494 1
        if (! is_object($document)) {
495
            throw new \InvalidArgumentException(gettype($document));
496
        }
497 1
        $this->unitOfWork->unlock($document);
498 1
    }
499
500
    /**
501
     * Gets the repository for a document class.
502
     *
503
     * @param string $documentName The name of the Document.
504
     * @return ObjectRepository  The repository.
505
     */
506 325
    public function getRepository($documentName)
507
    {
508 325
        return $this->repositoryFactory->getRepository($this, $documentName);
509
    }
510
511
    /**
512
     * Flushes all changes to objects that have been queued up to now to the database.
513
     * This effectively synchronizes the in-memory state of managed objects with the
514
     * database.
515
     *
516
     * @param array $options Array of options to be used with batchInsert(), update() and remove()
517
     * @throws \InvalidArgumentException
518
     */
519 549
    public function flush(array $options = [])
520
    {
521 549
        $this->errorIfClosed();
522 548
        $this->unitOfWork->commit($options);
523 545
    }
524
525
    /**
526
     * Gets a reference to the document identified by the given type and identifier
527
     * without actually loading it.
528
     *
529
     * If partial objects are allowed, this method will return a partial object that only
530
     * has its identifier populated. Otherwise a proxy is returned that automatically
531
     * loads itself on first access.
532
     *
533
     * @param string        $documentName
534
     * @param string|object $identifier
535
     * @return mixed|object The document reference.
536
     */
537 125
    public function getReference($documentName, $identifier)
538
    {
539
        /* @var $class \Doctrine\ODM\MongoDB\Mapping\ClassMetadata */
540 125
        $class = $this->metadataFactory->getMetadataFor(ltrim($documentName, '\\'));
541 125
        $document = $this->unitOfWork->tryGetById($identifier, $class);
542
543
        // Check identity map first, if its already in there just return it.
544 125
        if ($document) {
545 55
            return $document;
546
        }
547
548 96
        $document = $this->proxyFactory->getProxy($class->name, [$class->identifier => $identifier]);
549 96
        $this->unitOfWork->registerManaged($document, $identifier, []);
550
551 96
        return $document;
552
    }
553
554
    /**
555
     * Gets a partial reference to the document identified by the given type and identifier
556
     * without actually loading it, if the document is not yet loaded.
557
     *
558
     * The returned reference may be a partial object if the document is not yet loaded/managed.
559
     * If it is a partial object it will not initialize the rest of the document state on access.
560
     * Thus you can only ever safely access the identifier of a document obtained through
561
     * this method.
562
     *
563
     * The use-cases for partial references involve maintaining bidirectional associations
564
     * without loading one side of the association or to update a document without loading it.
565
     * Note, however, that in the latter case the original (persistent) document data will
566
     * never be visible to the application (especially not event listeners) as it will
567
     * never be loaded in the first place.
568
     *
569
     * @param string $documentName The name of the document type.
570
     * @param mixed  $identifier   The document identifier.
571
     * @return object The (partial) document reference.
572
     */
573 1
    public function getPartialReference($documentName, $identifier)
574
    {
575 1
        $class = $this->metadataFactory->getMetadataFor(ltrim($documentName, '\\'));
576 1
        $document = $this->unitOfWork->tryGetById($identifier, $class);
577
578
        // Check identity map first, if its already in there just return it.
579 1
        if ($document) {
580
            return $document;
581
        }
582 1
        $document = $class->newInstance();
583 1
        $class->setIdentifierValue($document, $identifier);
584 1
        $this->unitOfWork->registerManaged($document, $identifier, []);
585
586 1
        return $document;
587
    }
588
589
    /**
590
     * Finds a Document by its identifier.
591
     *
592
     * This is just a convenient shortcut for getRepository($documentName)->find($id).
593
     *
594
     * @param string $documentName
595
     * @param mixed  $identifier
596
     * @param int    $lockMode
597
     * @param int    $lockVersion
598
     * @return object $document
599
     */
600 181
    public function find($documentName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
601
    {
602 181
        return $this->getRepository($documentName)->find($identifier, $lockMode, $lockVersion);
603
    }
604
605
    /**
606
     * Clears the DocumentManager.
607
     *
608
     * All documents that are currently managed by this DocumentManager become
609
     * detached.
610
     *
611
     * @param string|null $documentName if given, only documents of this type will get detached
612
     */
613 370
    public function clear($documentName = null)
614
    {
615 370
        $this->unitOfWork->clear($documentName);
616 370
    }
617
618
    /**
619
     * Closes the DocumentManager. All documents that are currently managed
620
     * by this DocumentManager become detached. The DocumentManager may no longer
621
     * be used after it is closed.
622
     */
623 6
    public function close()
624
    {
625 6
        $this->clear();
626 6
        $this->closed = true;
627 6
    }
628
629
    /**
630
     * Determines whether a document instance is managed in this DocumentManager.
631
     *
632
     * @param object $document
633
     * @throws \InvalidArgumentException When the $document param is not an object
634
     * @return bool TRUE if this DocumentManager currently manages the given document, FALSE otherwise.
635
     */
636 3
    public function contains($document)
637
    {
638 3
        if (! is_object($document)) {
639
            throw new \InvalidArgumentException(gettype($document));
640
        }
641 3
        return $this->unitOfWork->isScheduledForInsert($document) ||
642 3
            $this->unitOfWork->isInIdentityMap($document) &&
643 3
            ! $this->unitOfWork->isScheduledForDelete($document);
644
    }
645
646
    /**
647
     * Gets the Configuration used by the DocumentManager.
648
     *
649
     * @return Configuration
650
     */
651 716
    public function getConfiguration()
652
    {
653 716
        return $this->config;
654
    }
655
656
    /**
657
     * Returns a reference to the supplied document.
658
     *
659
     * @param object $document         A document object
660
     * @param array  $referenceMapping Mapping for the field that references the document
661
     *
662
     * @throws \InvalidArgumentException
663
     * @throws MappingException
664
     * @return mixed The reference for the document in question, according to the desired mapping
665
     */
666 220
    public function createReference($document, array $referenceMapping)
667
    {
668 220
        if (! is_object($document)) {
669
            throw new \InvalidArgumentException('Cannot create a DBRef, the document is not an object');
670
        }
671
672 220
        $class = $this->getClassMetadata(get_class($document));
673 220
        $id = $this->unitOfWork->getDocumentIdentifier($document);
674
675 220
        if ($id === null) {
676 1
            throw new \RuntimeException(
677 1
                sprintf('Cannot create a DBRef for class %s without an identifier. Have you forgotten to persist/merge the document first?', $class->name)
678
            );
679
        }
680
681 219
        $storeAs = $referenceMapping['storeAs'] ?? null;
682 219
        $reference = [];
0 ignored issues
show
Unused Code introduced by
$reference is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
683 219
        switch ($storeAs) {
684
            case ClassMetadata::REFERENCE_STORE_AS_ID:
685 45
                if ($class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION) {
686 1
                    throw MappingException::simpleReferenceMustNotTargetDiscriminatedDocument($referenceMapping['targetDocument']);
687
                }
688
689 44
                return $class->getDatabaseIdentifierValue($id);
690
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
691
692
            case ClassMetadata::REFERENCE_STORE_AS_REF:
693 19
                $reference = ['id' => $class->getDatabaseIdentifierValue($id)];
694 19
                break;
695
696
            case ClassMetadata::REFERENCE_STORE_AS_DB_REF:
697
                $reference = [
698 176
                    '$ref' => $class->getCollection(),
699 176
                    '$id'  => $class->getDatabaseIdentifierValue($id),
700
                ];
701 176
                break;
702
703
            case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB:
704
                $reference = [
705 17
                    '$ref' => $class->getCollection(),
706 17
                    '$id'  => $class->getDatabaseIdentifierValue($id),
707 17
                    '$db'  => $this->getDocumentDatabase($class->name)->getDatabaseName(),
708
                ];
709 17
                break;
710
711
            default:
712
                throw new \InvalidArgumentException("Reference type {$storeAs} is invalid.");
713
        }
714
715
        /* If the class has a discriminator (field and value), use it. A child
716
         * class that is not defined in the discriminator map may only have a
717
         * discriminator field and no value, so default to the full class name.
718
         */
719 197
        if (isset($class->discriminatorField)) {
720 18
            $reference[$class->discriminatorField] = $class->discriminatorValue ?? $class->name;
721
        }
722
723
        /* Add a discriminator value if the referenced document is not mapped
724
         * explicitly to a targetDocument class.
725
         */
726 197
        if (! isset($referenceMapping['targetDocument'])) {
727 33
            $discriminatorField = $referenceMapping['discriminatorField'];
728 33
            $discriminatorValue = isset($referenceMapping['discriminatorMap'])
729 8
                ? array_search($class->name, $referenceMapping['discriminatorMap'])
730 33
                : $class->name;
731
732
            /* If the discriminator value was not found in the map, use the full
733
             * class name. In the future, it may be preferable to throw an
734
             * exception here (perhaps based on some strictness option).
735
             *
736
             * @see PersistenceBuilder::prepareEmbeddedDocumentValue()
737
             */
738 33
            if ($discriminatorValue === false) {
739 2
                $discriminatorValue = $class->name;
740
            }
741
742 33
            $reference[$discriminatorField] = $discriminatorValue;
743
        }
744
745 197
        return $reference;
746
    }
747
748
    /**
749
     * Throws an exception if the DocumentManager is closed or currently not active.
750
     *
751
     * @throws MongoDBException If the DocumentManager is closed.
752
     */
753 582
    private function errorIfClosed()
754
    {
755 582
        if ($this->closed) {
756 5
            throw MongoDBException::documentManagerClosed();
757
        }
758 577
    }
759
760
    /**
761
     * Check if the Document manager is open or closed.
762
     *
763
     * @return bool
764
     */
765 1
    public function isOpen()
766
    {
767 1
        return ! $this->closed;
768
    }
769
770
    /**
771
     * Gets the filter collection.
772
     *
773
     * @return FilterCollection The active filter collection.
774
     */
775 502
    public function getFilterCollection()
776
    {
777 502
        if ($this->filterCollection === null) {
778 502
            $this->filterCollection = new FilterCollection($this);
779
        }
780
781 502
        return $this->filterCollection;
782
    }
783
}
784