Completed
Pull Request — master (#1803)
by Maciej
23:34
created

DocumentManager   F

Complexity

Total Complexity 73

Size/Duplication

Total Lines 754
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 13

Test Coverage

Coverage 92.65%

Importance

Changes 0
Metric Value
wmc 73
lcom 3
cbo 13
dl 0
loc 754
ccs 189
cts 204
cp 0.9265
rs 3.7209
c 0
b 0
f 0

37 Methods

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