Failed Conditions
Push — master ( ee4e26...e98654 )
by Marco
13:06
created

EntityManager::createNativeQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
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 2249
    protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
132
    {
133 2249
        $this->conn         = $conn;
134 2249
        $this->config       = $config;
135 2249
        $this->eventManager = $eventManager;
136
137 2249
        $metadataFactoryClassName = $config->getClassMetadataFactoryName();
138
139 2249
        $this->metadataFactory = new $metadataFactoryClassName;
140
141 2249
        $this->metadataFactory->setEntityManager($this);
142 2249
        $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
143
144 2249
        $this->repositoryFactory   = $config->getRepositoryFactory();
145 2249
        $this->unitOfWork          = new UnitOfWork($this);
146 2249
        $this->proxyFactory        = new StaticProxyFactory($this, $this->config->buildGhostObjectFactory());
147 2249
        $this->identifierFlattener = new IdentifierFlattener($this->unitOfWork, $this->metadataFactory);
148
149 2249
        if ($config->isSecondLevelCacheEnabled()) {
150 279
            $cacheConfig  = $config->getSecondLevelCacheConfiguration();
151 279
            $cacheFactory = $cacheConfig->getCacheFactory();
152 279
            $this->cache  = $cacheFactory->createCache($this);
153
        }
154 2249
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159 1784
    public function getConnection()
160
    {
161 1784
        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 811
    public function getMetadataFactory()
170
    {
171 811
        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 1090
    public function getIdentifierFlattener() : IdentifierFlattener
187
    {
188 1090
        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 211
    public function getCache()
203
    {
204 211
        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 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 1896
    public function getClassMetadata($className) : Mapping\ClassMetadata
265
    {
266 1896
        return $this->metadataFactory->getMetadataFor($className);
267
    }
268
269
    /**
270
     * {@inheritDoc}
271
     */
272 949
    public function createQuery($dql = '')
273
    {
274 949
        $query = new Query($this);
275
276 949
        if (! empty($dql)) {
277 944
            $query->setDQL($dql);
278
        }
279
280 949
        return $query;
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     */
286 22
    public function createNativeQuery($sql, ResultSetMapping $rsm)
287
    {
288 22
        $query = new NativeQuery($this);
289
290 22
        $query->setSQL($sql);
291 22
        $query->setResultSetMapping($rsm);
292
293 22
        return $query;
294
    }
295
296
    /**
297
     * {@inheritDoc}
298
     */
299 1
    public function createNamedNativeQuery($name)
300
    {
301 1
        list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
302
303 1
        return $this->createNativeQuery($sql, $rsm);
304
    }
305
306
    /**
307
     * {@inheritDoc}
308
     */
309 126
    public function createQueryBuilder()
310
    {
311 126
        return new QueryBuilder($this);
312
    }
313
314
    /**
315
     * {@inheritDoc}
316
     *
317
     * @deprecated
318
     */
319
    public function merge($object)
320
    {
321
        throw new \BadMethodCallException('@TODO method disabled - will be removed in 3.0 with a release of doctrine/common');
322
    }
323
324
    /**
325
     * {@inheritDoc}
326
     *
327
     * @deprecated
328
     */
329
    public function detach($object)
330
    {
331
        throw new \BadMethodCallException('@TODO method disabled - will be removed in 3.0 with a release of doctrine/common');
332
    }
333
334
    /**
335
     * Flushes all changes to objects that have been queued up to now to the database.
336
     * This effectively synchronizes the in-memory state of managed objects with the
337
     * database.
338
     *
339
     * If an entity is explicitly passed to this method only this entity and
340
     * the cascade-persist semantics + scheduled inserts/removals are synchronized.
341
     *
342
     *
343
     * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
344
     *         makes use of optimistic locking fails.
345
     * @throws ORMException
346
     */
347 1001
    public function flush()
348
    {
349 1001
        $this->errorIfClosed();
350
351 1000
        $this->unitOfWork->commit();
352 990
    }
353
354
    /**
355
     * Finds an Entity by its identifier.
356
     *
357
     * @param string   $entityName  The class name of the entity to find.
358
     * @param mixed    $id          The identity of the entity to find.
359
     * @param int|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
360
     *                              or NULL if no specific lock mode should be used
361
     *                              during the search.
362
     * @param int|null $lockVersion The version of the entity to find when using
363
     *                              optimistic locking.
364
     *
365
     * @return object|null The entity instance or NULL if the entity can not be found.
366
     *
367
     * @throws OptimisticLockException
368
     * @throws ORMInvalidArgumentException
369
     * @throws TransactionRequiredException
370
     * @throws ORMException
371
     */
372 397
    public function find($entityName, $id, $lockMode = null, $lockVersion = null)
373
    {
374 397
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
375 397
        $className = $class->getClassName();
376
377 397
        if (! is_array($id)) {
378 367
            if ($class->isIdentifierComposite()) {
379
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
380
            }
381
382 367
            $id = [$class->identifier[0] => $id];
383
        }
384
385 397
        foreach ($id as $i => $value) {
386 397
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
387 7
                $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
388
389 7
                if ($id[$i] === null) {
390 397
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
391
                }
392
            }
393
        }
394
395 396
        $sortedId = [];
396
397 396
        foreach ($class->identifier as $identifier) {
398 396
            if (! isset($id[$identifier])) {
399 1
                throw ORMException::missingIdentifierField($className, $identifier);
400
            }
401
402 395
            $sortedId[$identifier] = $id[$identifier];
403 395
            unset($id[$identifier]);
404
        }
405
406 395
        if ($id) {
407 1
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($id));
408
        }
409
410 394
        $unitOfWork = $this->getUnitOfWork();
411
412
        // Check identity map first
413 394
        $entity = $unitOfWork->tryGetById($sortedId, $class->getRootClassName());
414 394
        if ($entity !== false) {
415 42
            if (! ($entity instanceof $className)) {
416 1
                return null;
417
            }
418
419
            switch (true) {
420 41
                case $lockMode === LockMode::OPTIMISTIC:
421 1
                    $this->lock($entity, $lockMode, $lockVersion);
422
                    break;
423
424 41
                case $lockMode === LockMode::NONE:
425 41
                case $lockMode === LockMode::PESSIMISTIC_READ:
426 41
                case $lockMode === LockMode::PESSIMISTIC_WRITE:
427
                    $persister = $unitOfWork->getEntityPersister($className);
428
                    $persister->refresh($sortedId, $entity, $lockMode);
429
                    break;
430
            }
431
432 41
            return $entity; // Hit!
433
        }
434
435 376
        $persister = $unitOfWork->getEntityPersister($className);
436
437
        switch (true) {
438 376
            case $lockMode === LockMode::OPTIMISTIC:
439 1
                if (! $class->isVersioned()) {
440 1
                    throw OptimisticLockException::notVersioned($className);
441
                }
442
443
                $entity = $persister->load($sortedId);
444
445
                $unitOfWork->lock($entity, $lockMode, $lockVersion);
446
447
                return $entity;
448
449 375
            case $lockMode === LockMode::PESSIMISTIC_READ:
450 374
            case $lockMode === LockMode::PESSIMISTIC_WRITE:
451 2
                if (! $this->getConnection()->isTransactionActive()) {
452 2
                    throw TransactionRequiredException::transactionRequired();
453
                }
454
455
                return $persister->load($sortedId, null, null, [], $lockMode);
456
457
            default:
458 373
                return $persister->loadById($sortedId);
459
        }
460
    }
461
462
    /**
463
     * {@inheritDoc}
464
     */
465 90
    public function getReference($entityName, $id)
466
    {
467 90
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
468 90
        $className = $class->getClassName();
469
470 90
        if (! is_array($id)) {
471 39
            if ($class->isIdentifierComposite()) {
472
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
473
            }
474
475 39
            $id = [$class->identifier[0] => $id];
476
        }
477
478 90
        $scalarId = [];
479
480 90
        foreach ($id as $i => $value) {
481 90
            $scalarId[$i] = $value;
482
483 90
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
484 2
                $scalarId[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
485
486 2
                if ($scalarId[$i] === null) {
487 90
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
488
                }
489
            }
490
        }
491
492 90
        $sortedId = [];
493
494 90
        foreach ($class->identifier as $identifier) {
495 90
            if (! isset($scalarId[$identifier])) {
496
                throw ORMException::missingIdentifierField($className, $identifier);
497
            }
498
499 90
            $sortedId[$identifier] = $scalarId[$identifier];
500 90
            unset($scalarId[$identifier]);
501
        }
502
503 90
        if ($scalarId) {
504 1
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($scalarId));
505
        }
506
507
        // Check identity map first, if its already in there just return it.
508 89
        $entity = $this->unitOfWork->tryGetById($sortedId, $class->getRootClassName());
509 89
        if ($entity !== false) {
510 29
            return ($entity instanceof $className) ? $entity : null;
511
        }
512
513 84
        if ($class->getSubClasses()) {
514 2
            return $this->find($entityName, $sortedId);
515
        }
516
517 84
        $entity = $this->proxyFactory->getProxy($class, $id);
518
519 84
        $this->unitOfWork->registerManaged($entity, $sortedId, []);
520
521 84
        if ($entity instanceof EntityManagerAware) {
522 3
            $entity->injectEntityManager($this, $class);
523
        }
524
525 84
        return $entity;
526
    }
527
528
    /**
529
     * {@inheritDoc}
530
     */
531 4
    public function getPartialReference($entityName, $id)
532
    {
533 4
        $class     = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
534 4
        $className = $class->getClassName();
535
536 4
        if (! is_array($id)) {
537 4
            if ($class->isIdentifierComposite()) {
538
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
539
            }
540
541 4
            $id = [$class->identifier[0] => $id];
542
        }
543
544 4
        foreach ($id as $i => $value) {
545 4
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(StaticClassNameConverter::getClass($value))) {
546
                $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
547
548
                if ($id[$i] === null) {
549 4
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
550
                }
551
            }
552
        }
553
554 4
        $sortedId = [];
555
556 4
        foreach ($class->identifier as $identifier) {
557 4
            if (! isset($id[$identifier])) {
558
                throw ORMException::missingIdentifierField($className, $identifier);
559
            }
560
561 4
            $sortedId[$identifier] = $id[$identifier];
562 4
            unset($id[$identifier]);
563
        }
564
565 4
        if ($id) {
566
            throw ORMException::unrecognizedIdentifierFields($className, array_keys($id));
567
        }
568
569
        // Check identity map first, if its already in there just return it.
570 4
        $entity = $this->unitOfWork->tryGetById($sortedId, $class->getRootClassName());
571 4
        if ($entity !== false) {
572 1
            return ($entity instanceof $className) ? $entity : null;
573
        }
574
575 3
        $persister = $this->unitOfWork->getEntityPersister($class->getClassName());
576 3
        $entity    = $this->unitOfWork->newInstance($class);
577
578 3
        $persister->setIdentifier($entity, $sortedId);
579
580 3
        $this->unitOfWork->registerManaged($entity, $sortedId, []);
581 3
        $this->unitOfWork->markReadOnly($entity);
582
583 3
        return $entity;
584
    }
585
586
    /**
587
     * Clears the EntityManager. All entities that are currently managed
588
     * by this EntityManager become detached.
589
     *
590
     * @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...
591
     *
592
     */
593 1198
    public function clear($entityName = null)
594
    {
595 1198
        $this->unitOfWork->clear();
596
597 1198
        $this->unitOfWork = new UnitOfWork($this);
598
599 1198
        if ($this->eventManager->hasListeners(Events::onClear)) {
600 9
            $this->eventManager->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this));
601
        }
602 1198
    }
603
604
    /**
605
     * {@inheritDoc}
606
     */
607 18
    public function close()
608
    {
609 18
        $this->clear();
610
611 18
        $this->closed = true;
612 18
    }
613
614
    /**
615
     * Tells the EntityManager to make an instance managed and persistent.
616
     *
617
     * The entity will be entered into the database at or before transaction
618
     * commit or as a result of the flush operation.
619
     *
620
     * NOTE: The persist operation always considers entities that are not yet known to
621
     * this EntityManager as NEW. Do not pass detached entities to the persist operation.
622
     *
623
     * @param object $entity The instance to make managed and persistent.
624
     *
625
     *
626
     * @throws ORMInvalidArgumentException
627
     * @throws ORMException
628
     */
629 995
    public function persist($entity)
630
    {
631 995
        if (! is_object($entity)) {
632 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()', $entity);
633
        }
634
635 994
        $this->errorIfClosed();
636
637 993
        $this->unitOfWork->persist($entity);
638 992
    }
639
640
    /**
641
     * Removes an entity instance.
642
     *
643
     * A removed entity will be removed from the database at or before transaction commit
644
     * or as a result of the flush operation.
645
     *
646
     * @param object $entity The entity instance to remove.
647
     *
648
     *
649
     * @throws ORMInvalidArgumentException
650
     * @throws ORMException
651
     */
652 49
    public function remove($entity)
653
    {
654 49
        if (! is_object($entity)) {
655 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()', $entity);
656
        }
657
658 48
        $this->errorIfClosed();
659
660 47
        $this->unitOfWork->remove($entity);
661 47
    }
662
663
    /**
664
     * Refreshes the persistent state of an entity from the database,
665
     * overriding any local changes that have not yet been persisted.
666
     *
667
     * @param object $entity The entity to refresh.
668
     *
669
     *
670
     * @throws ORMInvalidArgumentException
671
     * @throws ORMException
672
     */
673 17
    public function refresh($entity)
674
    {
675 17
        if (! is_object($entity)) {
676 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()', $entity);
677
        }
678
679 16
        $this->errorIfClosed();
680
681 15
        $this->unitOfWork->refresh($entity);
682 15
    }
683
684
    /**
685
     * {@inheritDoc}
686
     */
687 9
    public function lock($entity, $lockMode, $lockVersion = null)
688
    {
689 9
        $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
690 2
    }
691
692
    /**
693
     * Gets the repository for an entity class.
694
     *
695
     * @param string $entityName The name of the entity.
696
     *
697
     * @return \Doctrine\Common\Persistence\ObjectRepository|\Doctrine\ORM\EntityRepository The repository class.
698
     */
699 146
    public function getRepository($entityName)
700
    {
701 146
        return $this->repositoryFactory->getRepository($this, $entityName);
702
    }
703
704
    /**
705
     * Determines whether an entity instance is managed in this EntityManager.
706
     *
707
     * @param object $entity
708
     *
709
     * @return bool TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
710
     */
711 15
    public function contains($entity)
712
    {
713 15
        return $this->unitOfWork->isScheduledForInsert($entity)
714 15
            || ($this->unitOfWork->isInIdentityMap($entity) && ! $this->unitOfWork->isScheduledForDelete($entity));
715
    }
716
717
    /**
718
     * {@inheritDoc}
719
     */
720 2249
    public function getEventManager()
721
    {
722 2249
        return $this->eventManager;
723
    }
724
725
    /**
726
     * {@inheritDoc}
727
     */
728 2249
    public function getConfiguration()
729
    {
730 2249
        return $this->config;
731
    }
732
733
    /**
734
     * Throws an exception if the EntityManager is closed or currently not active.
735
     *
736
     *
737
     * @throws ORMException If the EntityManager is closed.
738
     */
739 1006
    private function errorIfClosed()
740
    {
741 1006
        if ($this->closed) {
742 4
            throw ORMException::entityManagerClosed();
743
        }
744 1002
    }
745
746
    /**
747
     * {@inheritDoc}
748
     */
749 2
    public function isOpen()
750
    {
751 2
        return ! $this->closed;
752
    }
753
754
    /**
755
     * {@inheritDoc}
756
     */
757 1349
    public function getUnitOfWork()
758
    {
759 1349
        return $this->unitOfWork;
760
    }
761
762
    /**
763
     * {@inheritDoc}
764
     */
765
    public function getHydrator($hydrationMode)
766
    {
767
        return $this->newHydrator($hydrationMode);
768
    }
769
770
    /**
771
     * {@inheritDoc}
772
     */
773 887
    public function newHydrator($hydrationMode)
774
    {
775 887
        switch ($hydrationMode) {
776
            case Query::HYDRATE_OBJECT:
777 621
                return new Internal\Hydration\ObjectHydrator($this);
778
779
            case Query::HYDRATE_ARRAY:
780 44
                return new Internal\Hydration\ArrayHydrator($this);
781
782
            case Query::HYDRATE_SCALAR:
783 85
                return new Internal\Hydration\ScalarHydrator($this);
784
785
            case Query::HYDRATE_SINGLE_SCALAR:
786 13
                return new Internal\Hydration\SingleScalarHydrator($this);
787
788
            case Query::HYDRATE_SIMPLEOBJECT:
789 407
                return new Internal\Hydration\SimpleObjectHydrator($this);
790
791
            default:
792 1
                $class = $this->config->getCustomHydrationMode($hydrationMode);
793 1
                if ($class !== null) {
794 1
                    return new $class($this);
795
                }
796
        }
797
798
        throw ORMException::invalidHydrationMode($hydrationMode);
799
    }
800
801
    /**
802
     * {@inheritDoc}
803
     */
804 166
    public function getProxyFactory()
805
    {
806 166
        return $this->proxyFactory;
807
    }
808
809
    /**
810
     * {@inheritDoc}
811
     */
812
    public function initializeObject($obj)
813
    {
814
        $this->unitOfWork->initializeObject($obj);
815
    }
816
817
    /**
818
     * Factory method to create EntityManager instances.
819
     *
820
     * @param Connection|mixed[] $connection   An array with the connection parameters or an existing Connection instance.
821
     * @param Configuration      $config       The Configuration instance to use.
822
     * @param EventManager       $eventManager The EventManager instance to use.
823
     *
824
     * @return EntityManager The created EntityManager.
825
     *
826
     * @throws \InvalidArgumentException
827
     * @throws ORMException
828
     */
829 2249
    public static function create($connection, Configuration $config, ?EventManager $eventManager = null)
830
    {
831 2249
        if (! $config->getMetadataDriverImpl()) {
832
            throw ORMException::missingMappingDriverImpl();
833
        }
834
835 2249
        $connection = static::createConnection($connection, $config, $eventManager);
836
837 2249
        return new EntityManager($connection, $config, $connection->getEventManager());
838
    }
839
840
    /**
841
     * Factory method to create Connection instances.
842
     *
843
     * @param Connection|mixed[] $connection   An array with the connection parameters or an existing Connection instance.
844
     * @param Configuration      $config       The Configuration instance to use.
845
     * @param EventManager       $eventManager The EventManager instance to use.
846
     *
847
     * @return Connection
848
     *
849
     * @throws \InvalidArgumentException
850
     * @throws ORMException
851
     */
852 2249
    protected static function createConnection($connection, Configuration $config, ?EventManager $eventManager = null)
853
    {
854 2249
        if (is_array($connection)) {
855
            return DriverManager::getConnection($connection, $config, $eventManager ?: new EventManager());
856
        }
857
858 2249
        if (! $connection instanceof Connection) {
859 1
            throw new \InvalidArgumentException(
860 1
                sprintf(
861 1
                    'Invalid $connection argument of type %s given%s.',
862 1
                    is_object($connection) ? get_class($connection) : gettype($connection),
863 1
                    is_object($connection) ? '' : ': "' . $connection . '"'
864
                )
865
            );
866
        }
867
868 2249
        if ($eventManager !== null && $connection->getEventManager() !== $eventManager) {
869
            throw ORMException::mismatchedEventManager();
870
        }
871
872 2249
        return $connection;
873
    }
874
875
    /**
876
     * {@inheritDoc}
877
     */
878 589
    public function getFilters()
879
    {
880 589
        if ($this->filterCollection === null) {
881 589
            $this->filterCollection = new FilterCollection($this);
882
        }
883
884 589
        return $this->filterCollection;
885
    }
886
887
    /**
888
     * {@inheritDoc}
889
     */
890 40
    public function isFiltersStateClean()
891
    {
892 40
        return $this->filterCollection === null || $this->filterCollection->isClean();
893
    }
894
895
    /**
896
     * {@inheritDoc}
897
     */
898 763
    public function hasFilters()
899
    {
900 763
        return $this->filterCollection !== null;
901
    }
902
}
903