Completed
Push — master ( 7db4b5...da5074 )
by Andreas
10s
created

DocumentManager::__construct()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 5.0009

Importance

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