Failed Conditions
Push — master ( ddb3cd...4476ec )
by Marco
11:47
created

EntityManager   F

Complexity

Total Complexity 115

Size/Duplication

Total Lines 867
Duplicated Lines 0 %

Test Coverage

Coverage 85.09%

Importance

Changes 0
Metric Value
dl 0
loc 867
ccs 234
cts 275
cp 0.8509
rs 1.263
c 0
b 0
f 0
wmc 115

44 Methods

Rating   Name   Duplication   Size   Complexity  
A getConnection() 0 3 1
A initializeObject() 0 3 1
A contains() 0 4 3
C getPartialReference() 0 53 12
A createNamedNativeQuery() 0 5 1
A getConfiguration() 0 3 1
A transactional() 0 16 2
A createNamedQuery() 0 3 1
A getProxyFactory() 0 3 1
A getCache() 0 3 1
A detach() 0 3 1
A lock() 0 3 1
A createNativeQuery() 0 8 1
A remove() 0 9 2
A refresh() 0 9 2
A createQueryBuilder() 0 3 1
A getUnitOfWork() 0 3 1
A beginTransaction() 0 3 1
A commit() 0 3 1
A rollback() 0 3 1
B createConnection() 0 21 8
A getRepository() 0 3 1
A createQuery() 0 9 2
A isOpen() 0 3 1
A getEventManager() 0 3 1
A __construct() 0 22 2
A persist() 0 9 2
A getHydrator() 0 3 1
A create() 0 9 2
A getClassMetadata() 0 3 1
A hasFilters() 0 3 1
A getIdentifierFlattener() 0 3 1
A close() 0 5 1
A getExpressionBuilder() 0 7 2
A merge() 0 3 1
A flush() 0 5 1
A clear() 0 8 2
A isFiltersStateClean() 0 3 2
A getFilters() 0 7 2
A getMetadataFactory() 0 3 1
C newHydrator() 0 26 7
C getReference() 0 61 14
A errorIfClosed() 0 4 2
D find() 0 87 21

How to fix   Complexity   

Complex Class

Complex classes like EntityManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

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

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

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\DBAL\DriverManager;
10
use Doctrine\DBAL\LockMode;
11
use Doctrine\ORM\Proxy\Factory\StaticProxyFactory;
12
use Doctrine\ORM\Query\FilterCollection;
13
use Doctrine\ORM\Query\ResultSetMapping;
14
use Doctrine\ORM\Utility\IdentifierFlattener;
15
use Doctrine\ORM\Utility\StaticClassNameConverter;
16
17
/**
18
 * The EntityManager is the central access point to ORM functionality.
19
 *
20
 * It is a facade to all different ORM subsystems such as UnitOfWork,
21
 * Query Language and Repository API. Instantiation is done through
22
 * the static create() method. The quickest way to obtain a fully
23
 * configured EntityManager is:
24
 *
25
 *     use Doctrine\ORM\Tools\Setup;
26
 *     use Doctrine\ORM\EntityManager;
27
 *
28
 *     $paths = array('/path/to/entity/mapping/files');
29
 *
30
 *     $config = Setup::createAnnotationMetadataConfiguration($paths);
31
 *     $dbParams = array('driver' => 'pdo_sqlite', 'memory' => true);
32
 *     $entityManager = EntityManager::create($dbParams, $config);
33
 *
34
 * For more information see
35
 * {@link http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html}
36
 *
37
 * You should never attempt to inherit from the EntityManager: Inheritance
38
 * is not a valid extension point for the EntityManager. Instead you
39
 * should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator}
40
 * and wrap your entity manager in a decorator.
41
 */
42
final class EntityManager implements EntityManagerInterface
43
{
44
    /**
45
     * The used Configuration.
46
     *
47
     * @var \Doctrine\ORM\Configuration
48
     */
49
    private $config;
50
51
    /**
52
     * The database connection used by the EntityManager.
53
     *
54
     * @var \Doctrine\DBAL\Connection
55
     */
56
    private $conn;
57
58
    /**
59
     * The metadata factory, used to retrieve the ORM metadata of entity classes.
60
     *
61
     * @var \Doctrine\ORM\Mapping\ClassMetadataFactory
62
     */
63
    private $metadataFactory;
64
65
    /**
66
     * The UnitOfWork used to coordinate object-level transactions.
67
     *
68
     * @var \Doctrine\ORM\UnitOfWork
69
     */
70
    private $unitOfWork;
71
72
    /**
73
     * The event manager that is the central point of the event system.
74
     *
75
     * @var \Doctrine\Common\EventManager
76
     */
77
    private $eventManager;
78
79
    /**
80
     * The proxy factory used to create dynamic proxies.
81
     *
82
     * @var \Doctrine\ORM\Proxy\Factory\ProxyFactory
83
     */
84
    private $proxyFactory;
85
86
    /**
87
     * The repository factory used to create dynamic repositories.
88
     *
89
     * @var \Doctrine\ORM\Repository\RepositoryFactory
90
     */
91
    private $repositoryFactory;
92
93
    /**
94
     * The expression builder instance used to generate query expressions.
95
     *
96
     * @var \Doctrine\ORM\Query\Expr
97
     */
98
    private $expressionBuilder;
99
100
    /**
101
     * The IdentifierFlattener used for manipulating identifiers
102
     *
103
     * @var \Doctrine\ORM\Utility\IdentifierFlattener
104
     */
105
    private $identifierFlattener;
106
107
    /**
108
     * Whether the EntityManager is closed or not.
109
     *
110
     * @var bool
111
     */
112
    private $closed = false;
113
114
    /**
115
     * Collection of query filters.
116
     *
117
     * @var \Doctrine\ORM\Query\FilterCollection
118
     */
119
    private $filterCollection;
120
121
    /**
122
     * @var \Doctrine\ORM\Cache The second level cache regions API.
123
     */
124
    private $cache;
125
126
    /**
127
     * Creates a new EntityManager that operates on the given database connection
128
     * and uses the given Configuration and EventManager implementations.
129
     *
130
     */
131 2076
    protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
132
    {
133 2076
        $this->conn         = $conn;
134 2076
        $this->config       = $config;
135 2076
        $this->eventManager = $eventManager;
136
137 2076
        $metadataFactoryClassName = $config->getClassMetadataFactoryName();
138
139 2076
        $this->metadataFactory = new $metadataFactoryClassName;
140
141 2076
        $this->metadataFactory->setEntityManager($this);
142 2076
        $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
143
144 2076
        $this->repositoryFactory   = $config->getRepositoryFactory();
145 2076
        $this->unitOfWork          = new UnitOfWork($this);
146 2076
        $this->proxyFactory        = new StaticProxyFactory($this, $this->config->buildGhostObjectFactory());
147 2076
        $this->identifierFlattener = new IdentifierFlattener($this->unitOfWork, $this->metadataFactory);
148
149 2076
        if ($config->isSecondLevelCacheEnabled()) {
150 271
            $cacheConfig  = $config->getSecondLevelCacheConfiguration();
151 271
            $cacheFactory = $cacheConfig->getCacheFactory();
152 271
            $this->cache  = $cacheFactory->createCache($this);
153
        }
154 2076
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159 1657
    public function getConnection()
160
    {
161 1657
        return $this->conn;
162
    }
163
164
    /**
165
     * Gets the metadata factory used to gather the metadata of classes.
166
     *
167
     * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
168
     */
169 775
    public function getMetadataFactory()
170
    {
171 775
        return $this->metadataFactory;
172
    }
173
174
    /**
175
     * {@inheritDoc}
176
     */
177 17
    public function getExpressionBuilder()
178
    {
179 17
        if ($this->expressionBuilder === null) {
180 17
            $this->expressionBuilder = new Query\Expr;
181
        }
182
183 17
        return $this->expressionBuilder;
184
    }
185
186 1012
    public function getIdentifierFlattener() : IdentifierFlattener
187
    {
188 1012
        return $this->identifierFlattener;
189
    }
190
191
    /**
192
     * {@inheritDoc}
193
     */
194 1
    public function beginTransaction()
195
    {
196 1
        $this->conn->beginTransaction();
197 1
    }
198
199
    /**
200
     * {@inheritDoc}
201
     */
202 206
    public function getCache()
203
    {
204 206
        return $this->cache;
205
    }
206
207
    /**
208
     * {@inheritDoc}
209
     */
210 6
    public function transactional(callable $func)
211
    {
212 6
        $this->conn->beginTransaction();
213
214
        try {
215 6
            $return = $func($this);
216
217 5
            $this->flush();
218 5
            $this->conn->commit();
219
220 5
            return $return;
221 1
        } catch (\Throwable $e) {
222 1
            $this->close();
223 1
            $this->conn->rollBack();
224
225 1
            throw $e;
226
        }
227
    }
228
229
    /**
230
     * {@inheritDoc}
231
     */
232 1
    public function commit()
233
    {
234 1
        $this->conn->commit();
235 1
    }
236
237
    /**
238
     * {@inheritDoc}
239
     */
240
    public function rollback()
241
    {
242
        $this->conn->rollBack();
243
    }
244
245
    /**
246
     * Returns the ORM metadata descriptor for a class.
247
     *
248
     * The class name must be the fully-qualified class name without a leading backslash
249
     * (as it is returned by get_class($obj)) or an aliased class name.
250
     *
251
     * Examples:
252
     * MyProject\Domain\User
253
     * sales:PriceRequest
254
     *
255
     * Internal note: Performance-sensitive method.
256
     *
257
     * @param string $className
258
     *
259
     *
260
     * @throws \ReflectionException
261
     * @throws \InvalidArgumentException
262
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
263
     */
264 1756
    public function getClassMetadata($className) : Mapping\ClassMetadata
265
    {
266 1756
        return $this->metadataFactory->getMetadataFor($className);
267
    }
268
269
    /**
270
     * {@inheritDoc}
271
     */
272 859
    public function createQuery($dql = '')
273
    {
274 859
        $query = new Query($this);
275
276 859
        if (! empty($dql)) {
277 856
            $query->setDQL($dql);
278
        }
279
280 859
        return $query;
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     */
286 1
    public function createNamedQuery($name)
287
    {
288 1
        return $this->createQuery($this->config->getNamedQuery($name));
289
    }
290
291
    /**
292
     * {@inheritDoc}
293
     */
294 20
    public function createNativeQuery($sql, ResultSetMapping $rsm)
295
    {
296 20
        $query = new NativeQuery($this);
297
298 20
        $query->setSQL($sql);
299 20
        $query->setResultSetMapping($rsm);
300
301 20
        return $query;
302
    }
303
304
    /**
305
     * {@inheritDoc}
306
     */
307 1
    public function createNamedNativeQuery($name)
308
    {
309 1
        list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
310
311 1
        return $this->createNativeQuery($sql, $rsm);
312
    }
313
314
    /**
315
     * {@inheritDoc}
316
     */
317 120
    public function createQueryBuilder()
318
    {
319 120
        return new QueryBuilder($this);
320
    }
321
322
    /**
323
     * {@inheritDoc}
324
     *
325
     * @deprecated
326
     */
327
    public function merge($object)
328
    {
329
        throw new \BadMethodCallException('@TODO method disabled - will be removed in 3.0 with a release of doctrine/common');
330
    }
331
332
    /**
333
     * {@inheritDoc}
334
     *
335
     * @deprecated
336
     */
337
    public function detach($object)
338
    {
339
        throw new \BadMethodCallException('@TODO method disabled - will be removed in 3.0 with a release of doctrine/common');
340
    }
341
342
    /**
343
     * Flushes all changes to objects that have been queued up to now to the database.
344
     * This effectively synchronizes the in-memory state of managed objects with the
345
     * database.
346
     *
347
     * If an entity is explicitly passed to this method only this entity and
348
     * the cascade-persist semantics + scheduled inserts/removals are synchronized.
349
     *
350
     *
351
     * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
352
     *         makes use of optimistic locking fails.
353
     * @throws ORMException
354
     */
355 934
    public function flush()
356
    {
357 934
        $this->errorIfClosed();
358
359 934
        $this->unitOfWork->commit();
360 928
    }
361
362
    /**
363
     * Finds an Entity by its identifier.
364
     *
365
     * @param string   $entityName  The class name of the entity to find.
366
     * @param mixed    $id          The identity of the entity to find.
367
     * @param int|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
368
     *                              or NULL if no specific lock mode should be used
369
     *                              during the search.
370
     * @param int|null $lockVersion The version of the entity to find when using
371
     *                              optimistic locking.
372
     *
373
     * @return object|null The entity instance or NULL if the entity can not be found.
374
     *
375
     * @throws OptimisticLockException
376
     * @throws ORMInvalidArgumentException
377
     * @throws TransactionRequiredException
378
     * @throws ORMException
379
     */
380 368
    public function find($entityName, $id, $lockMode = null, $lockVersion = null)
381
    {
382 368
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
383 368
        $className = $class->getClassName();
384
385 368
        if (! is_array($id)) {
386 342
            if ($class->isIdentifierComposite()) {
387
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
388
            }
389
390 342
            $id = [$class->identifier[0] => $id];
391
        }
392
393 368
        foreach ($id as $i => $value) {
394 368
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
395 5
                $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
396
397 5
                if ($id[$i] === null) {
398 368
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
399
                }
400
            }
401
        }
402
403 368
        $sortedId = [];
404
405 368
        foreach ($class->identifier as $identifier) {
406 368
            if (! isset($id[$identifier])) {
407
                throw ORMException::missingIdentifierField($className, $identifier);
408
            }
409
410 368
            $sortedId[$identifier] = $id[$identifier];
411 368
            unset($id[$identifier]);
412
        }
413
414 368
        if ($id) {
415
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($id));
416
        }
417
418 368
        $unitOfWork = $this->getUnitOfWork();
419
420
        // Check identity map first
421 368
        $entity = $unitOfWork->tryGetById($sortedId, $class->getRootClassName());
422 368
        if ($entity !== false) {
423 38
            if (! ($entity instanceof $className)) {
424 1
                return null;
425
            }
426
427
            switch (true) {
428 37
                case $lockMode === LockMode::OPTIMISTIC:
429
                    $this->lock($entity, $lockMode, $lockVersion);
430
                    break;
431
432 37
                case $lockMode === LockMode::NONE:
433 37
                case $lockMode === LockMode::PESSIMISTIC_READ:
434 37
                case $lockMode === LockMode::PESSIMISTIC_WRITE:
435
                    $persister = $unitOfWork->getEntityPersister($className);
436
                    $persister->refresh($sortedId, $entity, $lockMode);
437
                    break;
438
            }
439
440 37
            return $entity; // Hit!
441
        }
442
443 353
        $persister = $unitOfWork->getEntityPersister($className);
444
445
        switch (true) {
446 353
            case $lockMode === LockMode::OPTIMISTIC:
447
                if (! $class->isVersioned()) {
448
                    throw OptimisticLockException::notVersioned($className);
449
                }
450
451
                $entity = $persister->load($sortedId);
452
453
                $unitOfWork->lock($entity, $lockMode, $lockVersion);
454
455
                return $entity;
456
457 353
            case $lockMode === LockMode::PESSIMISTIC_READ:
458 353
            case $lockMode === LockMode::PESSIMISTIC_WRITE:
459
                if (! $this->getConnection()->isTransactionActive()) {
460
                    throw TransactionRequiredException::transactionRequired();
461
                }
462
463
                return $persister->load($sortedId, null, null, [], $lockMode);
464
465
            default:
466 353
                return $persister->loadById($sortedId);
467
        }
468
    }
469
470
    /**
471
     * {@inheritDoc}
472
     */
473 80
    public function getReference($entityName, $id)
474
    {
475 80
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
476 80
        $className = $class->getClassName();
477
478 80
        if (! is_array($id)) {
479 31
            if ($class->isIdentifierComposite()) {
480
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
481
            }
482
483 31
            $id = [$class->identifier[0] => $id];
484
        }
485
486 80
        $scalarId = [];
487
488 80
        foreach ($id as $i => $value) {
489 80
            $scalarId[$i] = $value;
490
491 80
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
492 2
                $scalarId[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
493
494 2
                if ($scalarId[$i] === null) {
495 80
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
496
                }
497
            }
498
        }
499
500 80
        $sortedId = [];
501
502 80
        foreach ($class->identifier as $identifier) {
503 80
            if (! isset($scalarId[$identifier])) {
504
                throw ORMException::missingIdentifierField($className, $identifier);
505
            }
506
507 80
            $sortedId[$identifier] = $scalarId[$identifier];
508 80
            unset($scalarId[$identifier]);
509
        }
510
511 80
        if ($scalarId) {
512
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($scalarId));
513
        }
514
515
        // Check identity map first, if its already in there just return it.
516 80
        $entity = $this->unitOfWork->tryGetById($sortedId, $class->getRootClassName());
517 80
        if ($entity !== false) {
518 29
            return ($entity instanceof $className) ? $entity : null;
519
        }
520
521 75
        if ($class->getSubClasses()) {
522 2
            return $this->find($entityName, $sortedId);
523
        }
524
525 75
        $entity = $this->proxyFactory->getProxy($class, $id);
526
527 75
        $this->unitOfWork->registerManaged($entity, $sortedId, []);
528
529 75
        if ($entity instanceof EntityManagerAware) {
530 1
            $entity->injectEntityManager($this, $class);
531
        }
532
533 75
        return $entity;
534
    }
535
536
    /**
537
     * {@inheritDoc}
538
     */
539 3
    public function getPartialReference($entityName, $id)
540
    {
541 3
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
542 3
        $className = $class->getClassName();
543
544 3
        if (! is_array($id)) {
545 3
            if ($class->isIdentifierComposite()) {
546
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
547
            }
548
549 3
            $id = [$class->identifier[0] => $id];
550
        }
551
552 3
        foreach ($id as $i => $value) {
553 3
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
554
                $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
555
556
                if ($id[$i] === null) {
557 3
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
558
                }
559
            }
560
        }
561
562 3
        $sortedId = [];
563
564 3
        foreach ($class->identifier as $identifier) {
565 3
            if (! isset($id[$identifier])) {
566
                throw ORMException::missingIdentifierField($className, $identifier);
567
            }
568
569 3
            $sortedId[$identifier] = $id[$identifier];
570 3
            unset($id[$identifier]);
571
        }
572
573 3
        if ($id) {
574
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($id));
575
        }
576
577
        // Check identity map first, if its already in there just return it.
578 3
        $entity = $this->unitOfWork->tryGetById($sortedId, $class->getRootClassName());
579 3
        if ($entity !== false) {
580 1
            return ($entity instanceof $className) ? $entity : null;
581
        }
582
583 2
        $persister = $this->unitOfWork->getEntityPersister($class->getClassName());
584 2
        $entity    = $this->unitOfWork->newInstance($class);
585
586 2
        $persister->setIdentifier($entity, $sortedId);
587
588 2
        $this->unitOfWork->registerManaged($entity, $sortedId, []);
589 2
        $this->unitOfWork->markReadOnly($entity);
590
591 2
        return $entity;
592
    }
593
594
    /**
595
     * Clears the EntityManager. All entities that are currently managed
596
     * by this EntityManager become detached.
597
     *
598
     * @param null $entityName Unused. @todo Remove from ObjectManager.
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $entityName is correct as it would always require null to be passed?
Loading history...
599
     *
600
     */
601 1090
    public function clear($entityName = null)
602
    {
603 1090
        $this->unitOfWork->clear();
604
605 1090
        $this->unitOfWork = new UnitOfWork($this);
606
607 1090
        if ($this->eventManager->hasListeners(Events::onClear)) {
608 3
            $this->eventManager->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this));
609
        }
610 1090
    }
611
612
    /**
613
     * {@inheritDoc}
614
     */
615 10
    public function close()
616
    {
617 10
        $this->clear();
618
619 10
        $this->closed = true;
620 10
    }
621
622
    /**
623
     * Tells the EntityManager to make an instance managed and persistent.
624
     *
625
     * The entity will be entered into the database at or before transaction
626
     * commit or as a result of the flush operation.
627
     *
628
     * NOTE: The persist operation always considers entities that are not yet known to
629
     * this EntityManager as NEW. Do not pass detached entities to the persist operation.
630
     *
631
     * @param object $entity The instance to make managed and persistent.
632
     *
633
     *
634
     * @throws ORMInvalidArgumentException
635
     * @throws ORMException
636
     */
637 932
    public function persist($entity)
638
    {
639 932
        if (! is_object($entity)) {
640 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()', $entity);
641
        }
642
643 931
        $this->errorIfClosed();
644
645 931
        $this->unitOfWork->persist($entity);
646 930
    }
647
648
    /**
649
     * Removes an entity instance.
650
     *
651
     * A removed entity will be removed from the database at or before transaction commit
652
     * or as a result of the flush operation.
653
     *
654
     * @param object $entity The entity instance to remove.
655
     *
656
     *
657
     * @throws ORMInvalidArgumentException
658
     * @throws ORMException
659
     */
660 43
    public function remove($entity)
661
    {
662 43
        if (! is_object($entity)) {
663 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()', $entity);
664
        }
665
666 42
        $this->errorIfClosed();
667
668 42
        $this->unitOfWork->remove($entity);
669 42
    }
670
671
    /**
672
     * Refreshes the persistent state of an entity from the database,
673
     * overriding any local changes that have not yet been persisted.
674
     *
675
     * @param object $entity The entity to refresh.
676
     *
677
     *
678
     * @throws ORMInvalidArgumentException
679
     * @throws ORMException
680
     */
681 12
    public function refresh($entity)
682
    {
683 12
        if (! is_object($entity)) {
684 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()', $entity);
685
        }
686
687 11
        $this->errorIfClosed();
688
689 11
        $this->unitOfWork->refresh($entity);
690 11
    }
691
692
    /**
693
     * {@inheritDoc}
694
     */
695 2
    public function lock($entity, $lockMode, $lockVersion = null)
696
    {
697 2
        $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
698 1
    }
699
700
    /**
701
     * Gets the repository for an entity class.
702
     *
703
     * @param string $entityName The name of the entity.
704
     *
705
     * @return \Doctrine\Common\Persistence\ObjectRepository|\Doctrine\ORM\EntityRepository The repository class.
706
     */
707 131
    public function getRepository($entityName)
708
    {
709 131
        return $this->repositoryFactory->getRepository($this, $entityName);
710
    }
711
712
    /**
713
     * Determines whether an entity instance is managed in this EntityManager.
714
     *
715
     * @param object $entity
716
     *
717
     * @return bool TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
718
     */
719 15
    public function contains($entity)
720
    {
721 15
        return $this->unitOfWork->isScheduledForInsert($entity)
722 15
            || ($this->unitOfWork->isInIdentityMap($entity) && ! $this->unitOfWork->isScheduledForDelete($entity));
723
    }
724
725
    /**
726
     * {@inheritDoc}
727
     */
728 2076
    public function getEventManager()
729
    {
730 2076
        return $this->eventManager;
731
    }
732
733
    /**
734
     * {@inheritDoc}
735
     */
736 2076
    public function getConfiguration()
737
    {
738 2076
        return $this->config;
739
    }
740
741
    /**
742
     * Throws an exception if the EntityManager is closed or currently not active.
743
     *
744
     *
745
     * @throws ORMException If the EntityManager is closed.
746
     */
747 936
    private function errorIfClosed()
748
    {
749 936
        if ($this->closed) {
750
            throw ORMException::entityManagerClosed();
751
        }
752 936
    }
753
754
    /**
755
     * {@inheritDoc}
756
     */
757 2
    public function isOpen()
758
    {
759 2
        return ! $this->closed;
760
    }
761
762
    /**
763
     * {@inheritDoc}
764
     */
765 1247
    public function getUnitOfWork()
766
    {
767 1247
        return $this->unitOfWork;
768
    }
769
770
    /**
771
     * {@inheritDoc}
772
     */
773
    public function getHydrator($hydrationMode)
774
    {
775
        return $this->newHydrator($hydrationMode);
776
    }
777
778
    /**
779
     * {@inheritDoc}
780
     */
781 829
    public function newHydrator($hydrationMode)
782
    {
783 829
        switch ($hydrationMode) {
784
            case Query::HYDRATE_OBJECT:
785 577
                return new Internal\Hydration\ObjectHydrator($this);
786
787
            case Query::HYDRATE_ARRAY:
788 41
                return new Internal\Hydration\ArrayHydrator($this);
789
790
            case Query::HYDRATE_SCALAR:
791 85
                return new Internal\Hydration\ScalarHydrator($this);
792
793
            case Query::HYDRATE_SINGLE_SCALAR:
794 10
                return new Internal\Hydration\SingleScalarHydrator($this);
795
796
            case Query::HYDRATE_SIMPLEOBJECT:
797 387
                return new Internal\Hydration\SimpleObjectHydrator($this);
798
799
            default:
800 1
                $class = $this->config->getCustomHydrationMode($hydrationMode);
801 1
                if ($class !== null) {
802 1
                    return new $class($this);
803
                }
804
        }
805
806
        throw ORMException::invalidHydrationMode($hydrationMode);
807
    }
808
809
    /**
810
     * {@inheritDoc}
811
     */
812 156
    public function getProxyFactory()
813
    {
814 156
        return $this->proxyFactory;
815
    }
816
817
    /**
818
     * {@inheritDoc}
819
     */
820
    public function initializeObject($obj)
821
    {
822
        $this->unitOfWork->initializeObject($obj);
823
    }
824
825
    /**
826
     * Factory method to create EntityManager instances.
827
     *
828
     * @param Connection|mixed[] $connection   An array with the connection parameters or an existing Connection instance.
829
     * @param Configuration      $config       The Configuration instance to use.
830
     * @param EventManager       $eventManager The EventManager instance to use.
831
     *
832
     * @return EntityManager The created EntityManager.
833
     *
834
     * @throws \InvalidArgumentException
835
     * @throws ORMException
836
     */
837 2076
    public static function create($connection, Configuration $config, ?EventManager $eventManager = null)
838
    {
839 2076
        if (! $config->getMetadataDriverImpl()) {
840
            throw ORMException::missingMappingDriverImpl();
841
        }
842
843 2076
        $connection = static::createConnection($connection, $config, $eventManager);
844
845 2076
        return new EntityManager($connection, $config, $connection->getEventManager());
846
    }
847
848
    /**
849
     * Factory method to create Connection instances.
850
     *
851
     * @param Connection|mixed[] $connection   An array with the connection parameters or an existing Connection instance.
852
     * @param Configuration      $config       The Configuration instance to use.
853
     * @param EventManager       $eventManager The EventManager instance to use.
854
     *
855
     * @return Connection
856
     *
857
     * @throws \InvalidArgumentException
858
     * @throws ORMException
859
     */
860 2076
    protected static function createConnection($connection, Configuration $config, ?EventManager $eventManager = null)
861
    {
862 2076
        if (is_array($connection)) {
863
            return DriverManager::getConnection($connection, $config, $eventManager ?: new EventManager());
864
        }
865
866 2076
        if (! $connection instanceof Connection) {
867 1
            throw new \InvalidArgumentException(
868 1
                sprintf(
869 1
                    'Invalid $connection argument of type %s given%s.',
870 1
                    is_object($connection) ? get_class($connection) : gettype($connection),
871 1
                    is_object($connection) ? '' : ': "' . $connection . '"'
872
                )
873
            );
874
        }
875
876 2076
        if ($eventManager !== null && $connection->getEventManager() !== $eventManager) {
877
            throw ORMException::mismatchedEventManager();
878
        }
879
880 2076
        return $connection;
881
    }
882
883
    /**
884
     * {@inheritDoc}
885
     */
886 555
    public function getFilters()
887
    {
888 555
        if ($this->filterCollection === null) {
889 555
            $this->filterCollection = new FilterCollection($this);
890
        }
891
892 555
        return $this->filterCollection;
893
    }
894
895
    /**
896
     * {@inheritDoc}
897
     */
898 35
    public function isFiltersStateClean()
899
    {
900 35
        return $this->filterCollection === null || $this->filterCollection->isClean();
901
    }
902
903
    /**
904
     * {@inheritDoc}
905
     */
906 708
    public function hasFilters()
907
    {
908 708
        return $this->filterCollection !== null;
909
    }
910
}
911