Completed
Pull Request — master (#1790)
by Andreas
16:15
created

DocumentManager::getHydratorFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
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 MongoDB\GridFS\Bucket;
22
use function array_search;
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
     * Array of cached document bucket instances that are lazily loaded.
120
     *
121
     * @var Bucket[]
122
     */
123
    private $documentBuckets = [];
124
125
    /**
126
     * Whether the DocumentManager is closed or not.
127
     *
128
     * @var bool
129
     */
130
    private $closed = false;
131
132
    /**
133
     * Collection of query filters.
134
     *
135
     * @var FilterCollection
136
     */
137
    private $filterCollection;
138
139
    /**
140
     * Creates a new Document that operates on the given Mongo connection
141
     * and uses the given Configuration.
142
     *
143
     */
144 1602
    protected function __construct(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null)
145
    {
146 1602
        $this->config = $config ?: new Configuration();
147 1602
        $this->eventManager = $eventManager ?: new EventManager();
148 1602
        $this->client = $client ?: new Client('mongodb://127.0.0.1', [], ['typeMap' => ['root' => 'array', 'document' => 'array']]);
149
150 1602
        $metadataFactoryClassName = $this->config->getClassMetadataFactoryName();
151 1602
        $this->metadataFactory = new $metadataFactoryClassName();
152 1602
        $this->metadataFactory->setDocumentManager($this);
153 1602
        $this->metadataFactory->setConfiguration($this->config);
154
155 1602
        $cacheDriver = $this->config->getMetadataCacheImpl();
156 1602
        if ($cacheDriver) {
157
            $this->metadataFactory->setCacheDriver($cacheDriver);
158
        }
159
160 1602
        $hydratorDir = $this->config->getHydratorDir();
161 1602
        $hydratorNs = $this->config->getHydratorNamespace();
162 1602
        $this->hydratorFactory = new HydratorFactory(
163 1602
            $this,
164 1602
            $this->eventManager,
165 1602
            $hydratorDir,
166 1602
            $hydratorNs,
167 1602
            $this->config->getAutoGenerateHydratorClasses()
168
        );
169
170 1602
        $this->unitOfWork = new UnitOfWork($this, $this->eventManager, $this->hydratorFactory);
171 1602
        $this->hydratorFactory->setUnitOfWork($this->unitOfWork);
172 1602
        $this->schemaManager = new SchemaManager($this, $this->metadataFactory);
173 1602
        $this->proxyFactory = new ProxyFactory(
174 1602
            $this,
175 1602
            $this->config->getProxyDir(),
176 1602
            $this->config->getProxyNamespace(),
177 1602
            $this->config->getAutoGenerateProxyClasses()
178
        );
179 1602
        $this->repositoryFactory = $this->config->getRepositoryFactory();
180 1602
    }
181
182
    /**
183
     * Gets the proxy factory used by the DocumentManager to create document proxies.
184
     *
185
     * @return ProxyFactory
186
     */
187 1
    public function getProxyFactory()
188
    {
189 1
        return $this->proxyFactory;
190
    }
191
192
    /**
193
     * Creates a new Document that operates on the given Mongo connection
194
     * and uses the given Configuration.
195
     *
196
     * @static
197
     * @return DocumentManager
198
     */
199 1602
    public static function create(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null)
200
    {
201 1602
        return new static($client, $config, $eventManager);
202
    }
203
204
    /**
205
     * Gets the EventManager used by the DocumentManager.
206
     *
207
     * @return EventManager
208
     */
209 1665
    public function getEventManager()
210
    {
211 1665
        return $this->eventManager;
212
    }
213
214
    /**
215
     * Gets the MongoDB client instance that this DocumentManager wraps.
216
     *
217
     * @return Client
218
     */
219 1602
    public function getClient()
220
    {
221 1602
        return $this->client;
222
    }
223
224
    /**
225
     * Gets the metadata factory used to gather the metadata of classes.
226
     *
227
     * @return ClassMetadataFactory
228
     */
229 1602
    public function getMetadataFactory()
230
    {
231 1602
        return $this->metadataFactory;
232
    }
233
234
    /**
235
     * Helper method to initialize a lazy loading proxy or persistent collection.
236
     *
237
     * This method is a no-op for other objects.
238
     *
239
     * @param object $obj
240
     */
241
    public function initializeObject($obj)
242
    {
243
        $this->unitOfWork->initializeObject($obj);
244
    }
245
246
    /**
247
     * Gets the UnitOfWork used by the DocumentManager to coordinate operations.
248
     *
249
     * @return UnitOfWork
250
     */
251 1609
    public function getUnitOfWork()
252
    {
253 1609
        return $this->unitOfWork;
254
    }
255
256
    /**
257
     * Gets the Hydrator factory used by the DocumentManager to generate and get hydrators
258
     * for each type of document.
259
     *
260
     * @return HydratorFactory
261
     */
262 69
    public function getHydratorFactory()
263
    {
264 69
        return $this->hydratorFactory;
265
    }
266
267
    /**
268
     * Returns SchemaManager, used to create/drop indexes/collections/databases.
269
     *
270
     * @return SchemaManager
271
     */
272 19
    public function getSchemaManager()
273
    {
274 19
        return $this->schemaManager;
275
    }
276
277
    /**
278
     * Returns the metadata for a class.
279
     *
280
     * @param string $className The class name.
281
     * @return ClassMetadata
282
     * @internal Performance-sensitive method.
283
     */
284 1340
    public function getClassMetadata($className)
285
    {
286 1340
        return $this->metadataFactory->getMetadataFor(ltrim($className, '\\'));
287
    }
288
289
    /**
290
     * Returns the MongoDB instance for a class.
291
     *
292
     * @param string $className The class name.
293
     * @return Database
294
     */
295 1269
    public function getDocumentDatabase($className)
296
    {
297 1269
        $className = ltrim($className, '\\');
298
299 1269
        if (isset($this->documentDatabases[$className])) {
300 37
            return $this->documentDatabases[$className];
301
        }
302
303 1264
        $metadata = $this->metadataFactory->getMetadataFor($className);
304 1264
        $db = $metadata->getDatabase();
305 1264
        $db = $db ?: $this->config->getDefaultDB();
306 1264
        $db = $db ?: 'doctrine';
307 1264
        $this->documentDatabases[$className] = $this->client->selectDatabase($db);
308
309 1264
        return $this->documentDatabases[$className];
310
    }
311
312
    /**
313
     * Gets the array of instantiated document database instances.
314
     *
315
     * @return Database[]
316
     */
317
    public function getDocumentDatabases()
318
    {
319
        return $this->documentDatabases;
320
    }
321
322
    /**
323
     * Returns the collection instance for a class.
324
     *
325
     * @param string $className The class name.
326
     * @throws MongoDBException When the $className param is not mapped to a collection.
327
     * @return Collection
328
     */
329 1272
    public function getDocumentCollection($className)
330
    {
331 1272
        $className = ltrim($className, '\\');
332
333
        /** @var ClassMetadata $metadata */
334 1272
        $metadata = $this->metadataFactory->getMetadataFor($className);
335 1272
        if ($metadata->isFile) {
336 16
            return $this->getDocumentBucket($className)->getFilesCollection();
337
        }
338
339 1261
        $collectionName = $metadata->getCollection();
340
341 1261
        if (! $collectionName) {
342
            throw MongoDBException::documentNotMappedToCollection($className);
343
        }
344
345 1261
        if (! isset($this->documentCollections[$className])) {
346 1251
            $db = $this->getDocumentDatabase($className);
347
348 1251
            $options = [];
349 1251
            if ($metadata->readPreference !== null) {
350 3
                $options['readPreference'] = new ReadPreference($metadata->readPreference, $metadata->readPreferenceTags);
351
            }
352
353 1251
            $this->documentCollections[$className] = $db->selectCollection($collectionName, $options);
354
        }
355
356 1261
        return $this->documentCollections[$className];
357
    }
358
359
    /**
360
     * Returns the bucket instance for a class.
361
     *
362
     * @param string $className The class name.
363
     * @throws MongoDBException When the $className param is not mapped to a collection.
364
     */
365 16
    public function getDocumentBucket(string $className): Bucket
366
    {
367 16
        $className = ltrim($className, '\\');
368
369
        /** @var ClassMetadata $metadata */
370 16
        $metadata = $this->metadataFactory->getMetadataFor($className);
371 16
        if (! $metadata->isFile) {
372
            throw MongoDBException::documentBucketOnlyAvailableForGridFSFiles($className);
373
        }
374
375 16
        $bucketName = $metadata->getBucketName();
376
377 16
        if (! $bucketName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $bucketName of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
378
            throw MongoDBException::documentNotMappedToCollection($className);
379
        }
380
381 16
        if (! isset($this->documentBuckets[$className])) {
382 11
            $db = $this->getDocumentDatabase($className);
383
384 11
            $options = ['bucketName' => $bucketName];
385 11
            if ($metadata->readPreference !== null) {
386
                $options['readPreference'] = new ReadPreference($metadata->readPreference, $metadata->readPreferenceTags);
387
            }
388
389 11
            $this->documentBuckets[$className] = $db->selectGridFSBucket($options);
390
        }
391
392 16
        return $this->documentBuckets[$className];
393
    }
394
395
    /**
396
     * Gets the array of instantiated document collection instances.
397
     *
398
     * @return Collection[]
399
     */
400
    public function getDocumentCollections()
401
    {
402
        return $this->documentCollections;
403
    }
404
405
    /**
406
     * Create a new Query instance for a class.
407
     *
408
     * @param string $documentName The document class name.
409
     * @return Query\Builder
410
     */
411 182
    public function createQueryBuilder($documentName = null)
412
    {
413 182
        return new Query\Builder($this, $documentName);
414
    }
415
416
    /**
417
     * Creates a new aggregation builder instance for a class.
418
     *
419
     * @param string $documentName The document class name.
420
     * @return Aggregation\Builder
421
     */
422 41
    public function createAggregationBuilder($documentName)
423
    {
424 41
        return new Aggregation\Builder($this, $documentName);
425
    }
426
427
    /**
428
     * Tells the DocumentManager to make an instance managed and persistent.
429
     *
430
     * The document will be entered into the database at or before transaction
431
     * commit or as a result of the flush operation.
432
     *
433
     * NOTE: The persist operation always considers documents that are not yet known to
434
     * this DocumentManager as NEW. Do not pass detached documents to the persist operation.
435
     *
436
     * @param object $document The instance to make managed and persistent.
437
     * @throws \InvalidArgumentException When the given $document param is not an object.
438
     */
439 585
    public function persist($document)
440
    {
441 585
        if (! is_object($document)) {
442 1
            throw new \InvalidArgumentException(gettype($document));
443
        }
444 584
        $this->errorIfClosed();
445 583
        $this->unitOfWork->persist($document);
446 579
    }
447
448
    /**
449
     * Removes a document instance.
450
     *
451
     * A removed document will be removed from the database at or before transaction commit
452
     * or as a result of the flush operation.
453
     *
454
     * @param object $document The document instance to remove.
455
     * @throws \InvalidArgumentException When the $document param is not an object.
456
     */
457 26
    public function remove($document)
458
    {
459 26
        if (! is_object($document)) {
460 1
            throw new \InvalidArgumentException(gettype($document));
461
        }
462 25
        $this->errorIfClosed();
463 24
        $this->unitOfWork->remove($document);
464 24
    }
465
466
    /**
467
     * Refreshes the persistent state of a document from the database,
468
     * overriding any local changes that have not yet been persisted.
469
     *
470
     * @param object $document The document to refresh.
471
     * @throws \InvalidArgumentException When the given $document param is not an object.
472
     */
473 25
    public function refresh($document)
474
    {
475 25
        if (! is_object($document)) {
476 1
            throw new \InvalidArgumentException(gettype($document));
477
        }
478 24
        $this->errorIfClosed();
479 23
        $this->unitOfWork->refresh($document);
480 22
    }
481
482
    /**
483
     * Detaches a document from the DocumentManager, causing a managed document to
484
     * become detached.  Unflushed changes made to the document if any
485
     * (including removal of the document), will not be synchronized to the database.
486
     * Documents which previously referenced the detached document will continue to
487
     * reference it.
488
     *
489
     * @param object $document The document to detach.
490
     * @throws \InvalidArgumentException When the $document param is not an object.
491
     */
492 11
    public function detach($document)
493
    {
494 11
        if (! is_object($document)) {
495 1
            throw new \InvalidArgumentException(gettype($document));
496
        }
497 10
        $this->unitOfWork->detach($document);
498 10
    }
499
500
    /**
501
     * Merges the state of a detached document into the persistence context
502
     * of this DocumentManager and returns the managed copy of the document.
503
     * The document passed to merge will not become associated/managed with this DocumentManager.
504
     *
505
     * @param object $document The detached document to merge into the persistence context.
506
     * @throws LockException
507
     * @throws \InvalidArgumentException If the $document param is not an object.
508
     * @return object The managed copy of the document.
509
     */
510 14
    public function merge($document)
511
    {
512 14
        if (! is_object($document)) {
513 1
            throw new \InvalidArgumentException(gettype($document));
514
        }
515 13
        $this->errorIfClosed();
516 12
        return $this->unitOfWork->merge($document);
517
    }
518
519
    /**
520
     * Acquire a lock on the given document.
521
     *
522
     * @param object $document
523
     * @param int    $lockMode
524
     * @param int    $lockVersion
525
     * @throws \InvalidArgumentException
526
     */
527 8
    public function lock($document, $lockMode, $lockVersion = null)
528
    {
529 8
        if (! is_object($document)) {
530
            throw new \InvalidArgumentException(gettype($document));
531
        }
532 8
        $this->unitOfWork->lock($document, $lockMode, $lockVersion);
533 5
    }
534
535
    /**
536
     * Releases a lock on the given document.
537
     *
538
     * @param object $document
539
     * @throws \InvalidArgumentException If the $document param is not an object.
540
     */
541 1
    public function unlock($document)
542
    {
543 1
        if (! is_object($document)) {
544
            throw new \InvalidArgumentException(gettype($document));
545
        }
546 1
        $this->unitOfWork->unlock($document);
547 1
    }
548
549
    /**
550
     * Gets the repository for a document class.
551
     *
552
     * @param string $documentName The name of the Document.
553
     * @return ObjectRepository  The repository.
554
     */
555 337
    public function getRepository($documentName)
556
    {
557 337
        return $this->repositoryFactory->getRepository($this, $documentName);
558
    }
559
560
    /**
561
     * Flushes all changes to objects that have been queued up to now to the database.
562
     * This effectively synchronizes the in-memory state of managed objects with the
563
     * database.
564
     *
565
     * @param array $options Array of options to be used with batchInsert(), update() and remove()
566
     * @throws \InvalidArgumentException
567
     */
568 557
    public function flush(array $options = [])
569
    {
570 557
        $this->errorIfClosed();
571 556
        $this->unitOfWork->commit($options);
572 553
    }
573
574
    /**
575
     * Gets a reference to the document identified by the given type and identifier
576
     * without actually loading it.
577
     *
578
     * If partial objects are allowed, this method will return a partial object that only
579
     * has its identifier populated. Otherwise a proxy is returned that automatically
580
     * loads itself on first access.
581
     *
582
     * @param string        $documentName
583
     * @param string|object $identifier
584
     * @return mixed|object The document reference.
585
     */
586 133
    public function getReference($documentName, $identifier)
587
    {
588
        /** @var ClassMetadata $class */
589 133
        $class = $this->metadataFactory->getMetadataFor(ltrim($documentName, '\\'));
590 133
        $document = $this->unitOfWork->tryGetById($identifier, $class);
591
592
        // Check identity map first, if its already in there just return it.
593 133
        if ($document) {
594 56
            return $document;
595
        }
596
597 104
        $document = $this->proxyFactory->getProxy($class->name, [$class->identifier => $identifier]);
598 104
        $this->unitOfWork->registerManaged($document, $identifier, []);
599
600 104
        return $document;
601
    }
602
603
    /**
604
     * Gets a partial reference to the document identified by the given type and identifier
605
     * without actually loading it, if the document is not yet loaded.
606
     *
607
     * The returned reference may be a partial object if the document is not yet loaded/managed.
608
     * If it is a partial object it will not initialize the rest of the document state on access.
609
     * Thus you can only ever safely access the identifier of a document obtained through
610
     * this method.
611
     *
612
     * The use-cases for partial references involve maintaining bidirectional associations
613
     * without loading one side of the association or to update a document without loading it.
614
     * Note, however, that in the latter case the original (persistent) document data will
615
     * never be visible to the application (especially not event listeners) as it will
616
     * never be loaded in the first place.
617
     *
618
     * @param string $documentName The name of the document type.
619
     * @param mixed  $identifier   The document identifier.
620
     * @return object The (partial) document reference.
621
     */
622 1
    public function getPartialReference($documentName, $identifier)
623
    {
624 1
        $class = $this->metadataFactory->getMetadataFor(ltrim($documentName, '\\'));
625 1
        $document = $this->unitOfWork->tryGetById($identifier, $class);
626
627
        // Check identity map first, if its already in there just return it.
628 1
        if ($document) {
629
            return $document;
630
        }
631 1
        $document = $class->newInstance();
632 1
        $class->setIdentifierValue($document, $identifier);
633 1
        $this->unitOfWork->registerManaged($document, $identifier, []);
634
635 1
        return $document;
636
    }
637
638
    /**
639
     * Finds a Document by its identifier.
640
     *
641
     * This is just a convenient shortcut for getRepository($documentName)->find($id).
642
     *
643
     * @param string $documentName
644
     * @param mixed  $identifier
645
     * @param int    $lockMode
646
     * @param int    $lockVersion
647
     * @return object $document
648
     */
649 182
    public function find($documentName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
650
    {
651 182
        return $this->getRepository($documentName)->find($identifier, $lockMode, $lockVersion);
652
    }
653
654
    /**
655
     * Clears the DocumentManager.
656
     *
657
     * All documents that are currently managed by this DocumentManager become
658
     * detached.
659
     *
660
     * @param string|null $documentName if given, only documents of this type will get detached
661
     */
662 372
    public function clear($documentName = null)
663
    {
664 372
        $this->unitOfWork->clear($documentName);
665 372
    }
666
667
    /**
668
     * Closes the DocumentManager. All documents that are currently managed
669
     * by this DocumentManager become detached. The DocumentManager may no longer
670
     * be used after it is closed.
671
     */
672 6
    public function close()
673
    {
674 6
        $this->clear();
675 6
        $this->closed = true;
676 6
    }
677
678
    /**
679
     * Determines whether a document instance is managed in this DocumentManager.
680
     *
681
     * @param object $document
682
     * @throws \InvalidArgumentException When the $document param is not an object.
683
     * @return bool TRUE if this DocumentManager currently manages the given document, FALSE otherwise.
684
     */
685 3
    public function contains($document)
686
    {
687 3
        if (! is_object($document)) {
688
            throw new \InvalidArgumentException(gettype($document));
689
        }
690 3
        return $this->unitOfWork->isScheduledForInsert($document) ||
691 3
            $this->unitOfWork->isInIdentityMap($document) &&
692 3
            ! $this->unitOfWork->isScheduledForDelete($document);
693
    }
694
695
    /**
696
     * Gets the Configuration used by the DocumentManager.
697
     *
698
     * @return Configuration
699
     */
700 753
    public function getConfiguration()
701
    {
702 753
        return $this->config;
703
    }
704
705
    /**
706
     * Returns a reference to the supplied document.
707
     *
708
     * @param object $document         A document object
709
     * @param array  $referenceMapping Mapping for the field that references the document
710
     *
711
     * @throws \InvalidArgumentException
712
     * @throws MappingException
713
     * @return mixed The reference for the document in question, according to the desired mapping
714
     */
715 225
    public function createReference($document, array $referenceMapping)
716
    {
717 225
        if (! is_object($document)) {
718
            throw new \InvalidArgumentException('Cannot create a DBRef, the document is not an object');
719
        }
720
721 225
        $class = $this->getClassMetadata(get_class($document));
722 225
        $id = $this->unitOfWork->getDocumentIdentifier($document);
723
724 225
        if ($id === null) {
725 1
            throw new \RuntimeException(
726 1
                sprintf('Cannot create a DBRef for class %s without an identifier. Have you forgotten to persist/merge the document first?', $class->name)
727
            );
728
        }
729
730 224
        $storeAs = $referenceMapping['storeAs'] ?? null;
731 224
        $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...
732 224
        switch ($storeAs) {
733
            case ClassMetadata::REFERENCE_STORE_AS_ID:
734 46
                if ($class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION) {
735 1
                    throw MappingException::simpleReferenceMustNotTargetDiscriminatedDocument($referenceMapping['targetDocument']);
736
                }
737
738 45
                return $class->getDatabaseIdentifierValue($id);
739
                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...
740
741
            case ClassMetadata::REFERENCE_STORE_AS_REF:
742 20
                $reference = ['id' => $class->getDatabaseIdentifierValue($id)];
743 20
                break;
744
745
            case ClassMetadata::REFERENCE_STORE_AS_DB_REF:
746
                $reference = [
747 180
                    '$ref' => $class->getCollection(),
748 180
                    '$id'  => $class->getDatabaseIdentifierValue($id),
749
                ];
750 180
                break;
751
752
            case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB:
753
                $reference = [
754 17
                    '$ref' => $class->getCollection(),
755 17
                    '$id'  => $class->getDatabaseIdentifierValue($id),
756 17
                    '$db'  => $this->getDocumentDatabase($class->name)->getDatabaseName(),
757
                ];
758 17
                break;
759
760
            default:
761
                throw new \InvalidArgumentException(sprintf('Reference type %s is invalid.', $storeAs));
762
        }
763
764
        /* If the class has a discriminator (field and value), use it. A child
765
         * class that is not defined in the discriminator map may only have a
766
         * discriminator field and no value, so default to the full class name.
767
         */
768 202
        if (isset($class->discriminatorField)) {
769 18
            $reference[$class->discriminatorField] = $class->discriminatorValue ?? $class->name;
770
        }
771
772
        /* Add a discriminator value if the referenced document is not mapped
773
         * explicitly to a targetDocument class.
774
         */
775 202
        if (! isset($referenceMapping['targetDocument'])) {
776 33
            $discriminatorField = $referenceMapping['discriminatorField'];
777 33
            $discriminatorValue = isset($referenceMapping['discriminatorMap'])
778 8
                ? array_search($class->name, $referenceMapping['discriminatorMap'])
779 33
                : $class->name;
780
781
            /* If the discriminator value was not found in the map, use the full
782
             * class name. In the future, it may be preferable to throw an
783
             * exception here (perhaps based on some strictness option).
784
             *
785
             * @see PersistenceBuilder::prepareEmbeddedDocumentValue()
786
             */
787 33
            if ($discriminatorValue === false) {
788 3
                $discriminatorValue = $class->name;
789
            }
790
791 33
            $reference[$discriminatorField] = $discriminatorValue;
792
        }
793
794 202
        return $reference;
795
    }
796
797
    /**
798
     * Throws an exception if the DocumentManager is closed or currently not active.
799
     *
800
     * @throws MongoDBException If the DocumentManager is closed.
801
     */
802 590
    private function errorIfClosed()
803
    {
804 590
        if ($this->closed) {
805 5
            throw MongoDBException::documentManagerClosed();
806
        }
807 585
    }
808
809
    /**
810
     * Check if the Document manager is open or closed.
811
     *
812
     * @return bool
813
     */
814 1
    public function isOpen()
815
    {
816 1
        return ! $this->closed;
817
    }
818
819
    /**
820
     * Gets the filter collection.
821
     *
822
     * @return FilterCollection The active filter collection.
823
     */
824 517
    public function getFilterCollection()
825
    {
826 517
        if ($this->filterCollection === null) {
827 517
            $this->filterCollection = new FilterCollection($this);
828
        }
829
830 517
        return $this->filterCollection;
831
    }
832
}
833