Completed
Push — master ( a47e46...ae9680 )
by Andreas
15:39
created

DocumentManager::getDiscriminatorData()   B

Complexity

Conditions 10
Paths 36

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 14.0992

Importance

Changes 0
Metric Value
dl 0
loc 46
ccs 19
cts 29
cp 0.6552
rs 7.3115
c 0
b 0
f 0
cc 10
nc 36
nop 2
crap 14.0992

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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