Failed Conditions
Push — master ( bbe005...633c84 )
by Marco
136:20 queued 127:11
created

lib/Doctrine/ORM/EntityManager.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM;
21
22
use Exception;
23
use Doctrine\Common\EventManager;
24
use Doctrine\DBAL\Connection;
25
use Doctrine\DBAL\DriverManager;
26
use Doctrine\DBAL\LockMode;
27
use Doctrine\ORM\Query\ResultSetMapping;
28
use Doctrine\ORM\Proxy\ProxyFactory;
29
use Doctrine\ORM\Query\FilterCollection;
30
use Doctrine\Common\Util\ClassUtils;
31
32
/**
33
 * The EntityManager is the central access point to ORM functionality.
34
 *
35
 * It is a facade to all different ORM subsystems such as UnitOfWork,
36
 * Query Language and Repository API. Instantiation is done through
37
 * the static create() method. The quickest way to obtain a fully
38
 * configured EntityManager is:
39
 *
40
 *     use Doctrine\ORM\Tools\Setup;
41
 *     use Doctrine\ORM\EntityManager;
42
 *
43
 *     $paths = array('/path/to/entity/mapping/files');
44
 *
45
 *     $config = Setup::createAnnotationMetadataConfiguration($paths);
46
 *     $dbParams = array('driver' => 'pdo_sqlite', 'memory' => true);
47
 *     $entityManager = EntityManager::create($dbParams, $config);
48
 *
49
 * For more information see
50
 * {@link http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html}
51
 *
52
 * You should never attempt to inherit from the EntityManager: Inheritance
53
 * is not a valid extension point for the EntityManager. Instead you
54
 * should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator}
55
 * and wrap your entity manager in a decorator.
56
 *
57
 * @since   2.0
58
 * @author  Benjamin Eberlei <[email protected]>
59
 * @author  Guilherme Blanco <[email protected]>
60
 * @author  Jonathan Wage <[email protected]>
61
 * @author  Roman Borschel <[email protected]>
62
 */
63
/* final */class EntityManager implements EntityManagerInterface
64
{
65
    /**
66
     * The used Configuration.
67
     *
68
     * @var \Doctrine\ORM\Configuration
69
     */
70
    private $config;
71
72
    /**
73
     * The database connection used by the EntityManager.
74
     *
75
     * @var \Doctrine\DBAL\Connection
76
     */
77
    private $conn;
78
79
    /**
80
     * The metadata factory, used to retrieve the ORM metadata of entity classes.
81
     *
82
     * @var \Doctrine\ORM\Mapping\ClassMetadataFactory
83
     */
84
    private $metadataFactory;
85
86
    /**
87
     * The UnitOfWork used to coordinate object-level transactions.
88
     *
89
     * @var \Doctrine\ORM\UnitOfWork
90
     */
91
    private $unitOfWork;
92
93
    /**
94
     * The event manager that is the central point of the event system.
95
     *
96
     * @var \Doctrine\Common\EventManager
97
     */
98
    private $eventManager;
99
100
    /**
101
     * The proxy factory used to create dynamic proxies.
102
     *
103
     * @var \Doctrine\ORM\Proxy\ProxyFactory
104
     */
105
    private $proxyFactory;
106
107
    /**
108
     * The repository factory used to create dynamic repositories.
109
     *
110
     * @var \Doctrine\ORM\Repository\RepositoryFactory
111
     */
112
    private $repositoryFactory;
113
114
    /**
115
     * The expression builder instance used to generate query expressions.
116
     *
117
     * @var \Doctrine\ORM\Query\Expr
118
     */
119
    private $expressionBuilder;
120
121
    /**
122
     * Whether the EntityManager is closed or not.
123
     *
124
     * @var bool
125
     */
126
    private $closed = false;
127
128
    /**
129
     * Collection of query filters.
130
     *
131
     * @var \Doctrine\ORM\Query\FilterCollection
132
     */
133
    private $filterCollection;
134
135
    /**
136
     * @var \Doctrine\ORM\Cache The second level cache regions API.
137
     */
138
    private $cache;
139
140
    /**
141
     * Creates a new EntityManager that operates on the given database connection
142
     * and uses the given Configuration and EventManager implementations.
143
     *
144
     * @param \Doctrine\DBAL\Connection     $conn
145
     * @param \Doctrine\ORM\Configuration   $config
146
     * @param \Doctrine\Common\EventManager $eventManager
147
     */
148 2395
    protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
149
    {
150 2395
        $this->conn              = $conn;
151 2395
        $this->config            = $config;
152 2395
        $this->eventManager      = $eventManager;
153
154 2395
        $metadataFactoryClassName = $config->getClassMetadataFactoryName();
155
156 2395
        $this->metadataFactory = new $metadataFactoryClassName;
157 2395
        $this->metadataFactory->setEntityManager($this);
158 2395
        $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
159
160 2395
        $this->repositoryFactory = $config->getRepositoryFactory();
161 2395
        $this->unitOfWork        = new UnitOfWork($this);
162 2395
        $this->proxyFactory      = new ProxyFactory(
163 2395
            $this,
164 2395
            $config->getProxyDir(),
165 2395
            $config->getProxyNamespace(),
166 2395
            $config->getAutoGenerateProxyClasses()
167
        );
168
169 2395
        if ($config->isSecondLevelCacheEnabled()) {
170 283
            $cacheConfig    = $config->getSecondLevelCacheConfiguration();
171 283
            $cacheFactory   = $cacheConfig->getCacheFactory();
172 283
            $this->cache    = $cacheFactory->createCache($this);
173
        }
174 2395
    }
175
176
    /**
177
     * {@inheritDoc}
178
     */
179 1880
    public function getConnection()
180
    {
181 1880
        return $this->conn;
182
    }
183
184
    /**
185
     * Gets the metadata factory used to gather the metadata of classes.
186
     *
187
     * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
188
     */
189 2395
    public function getMetadataFactory()
190
    {
191 2395
        return $this->metadataFactory;
192
    }
193
194
    /**
195
     * {@inheritDoc}
196
     */
197 17
    public function getExpressionBuilder()
198
    {
199 17
        if ($this->expressionBuilder === null) {
200 17
            $this->expressionBuilder = new Query\Expr;
201
        }
202
203 17
        return $this->expressionBuilder;
204
    }
205
206
    /**
207
     * {@inheritDoc}
208
     */
209 1
    public function beginTransaction()
210
    {
211 1
        $this->conn->beginTransaction();
212 1
    }
213
214
    /**
215
     * {@inheritDoc}
216
     */
217 216
    public function getCache()
218
    {
219 216
        return $this->cache;
220
    }
221
222
    /**
223
     * {@inheritDoc}
224
     */
225 4
    public function transactional($func)
226
    {
227 4
        if (!is_callable($func)) {
228 1
            throw new \InvalidArgumentException('Expected argument of type "callable", got "' . gettype($func) . '"');
229
        }
230
231 3
        $this->conn->beginTransaction();
232
233
        try {
234 3
            $return = call_user_func($func, $this);
235
236 3
            $this->flush();
237 3
            $this->conn->commit();
238
239 3
            return $return ?: true;
240
        } catch (Exception $e) {
241
            $this->close();
242
            $this->conn->rollBack();
243
244
            throw $e;
245
        }
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     */
251 1
    public function commit()
252
    {
253 1
        $this->conn->commit();
254 1
    }
255
256
    /**
257
     * {@inheritDoc}
258
     */
259
    public function rollback()
260
    {
261
        $this->conn->rollBack();
262
    }
263
264
    /**
265
     * Returns the ORM metadata descriptor for a class.
266
     *
267
     * The class name must be the fully-qualified class name without a leading backslash
268
     * (as it is returned by get_class($obj)) or an aliased class name.
269
     *
270
     * Examples:
271
     * MyProject\Domain\User
272
     * sales:PriceRequest
273
     *
274
     * Internal note: Performance-sensitive method.
275
     *
276
     * @param string $className
277
     *
278
     * @return \Doctrine\ORM\Mapping\ClassMetadata
279
     */
280 1940
    public function getClassMetadata($className)
281
    {
282 1940
        return $this->metadataFactory->getMetadataFor($className);
283
    }
284
285
    /**
286
     * {@inheritDoc}
287
     */
288 939
    public function createQuery($dql = '')
289
    {
290 939
        $query = new Query($this);
291
292 939
        if ( ! empty($dql)) {
293 934
            $query->setDQL($dql);
294
        }
295
296 939
        return $query;
297
    }
298
299
    /**
300
     * {@inheritDoc}
301
     */
302 1
    public function createNamedQuery($name)
303
    {
304 1
        return $this->createQuery($this->config->getNamedQuery($name));
305
    }
306
307
    /**
308
     * {@inheritDoc}
309
     */
310 21
    public function createNativeQuery($sql, ResultSetMapping $rsm)
311
    {
312 21
        $query = new NativeQuery($this);
313
314 21
        $query->setSQL($sql);
315 21
        $query->setResultSetMapping($rsm);
316
317 21
        return $query;
318
    }
319
320
    /**
321
     * {@inheritDoc}
322
     */
323 1
    public function createNamedNativeQuery($name)
324
    {
325 1
        list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
326
327 1
        return $this->createNativeQuery($sql, $rsm);
328
    }
329
330
    /**
331
     * {@inheritDoc}
332
     */
333 117
    public function createQueryBuilder()
334
    {
335 117
        return new QueryBuilder($this);
336
    }
337
338
    /**
339
     * Flushes all changes to objects that have been queued up to now to the database.
340
     * This effectively synchronizes the in-memory state of managed objects with the
341
     * database.
342
     *
343
     * If an entity is explicitly passed to this method only this entity and
344
     * the cascade-persist semantics + scheduled inserts/removals are synchronized.
345
     *
346
     * @param null|object|array $entity
347
     *
348
     * @return void
349
     *
350
     * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
351
     *         makes use of optimistic locking fails.
352
     * @throws ORMException
353
     */
354 1035
    public function flush($entity = null)
355
    {
356 1035
        $this->errorIfClosed();
357
358 1034
        $this->unitOfWork->commit($entity);
359 1025
    }
360
361
    /**
362
     * Finds an Entity by its identifier.
363
     *
364
     * @param string       $entityName  The class name of the entity to find.
365
     * @param mixed        $id          The identity of the entity to find.
366
     * @param integer|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
367
     *                                  or NULL if no specific lock mode should be used
368
     *                                  during the search.
369
     * @param integer|null $lockVersion The version of the entity to find when using
370
     *                                  optimistic locking.
371
     *
372
     * @return object|null The entity instance or NULL if the entity can not be found.
373
     *
374
     * @throws OptimisticLockException
375
     * @throws ORMInvalidArgumentException
376
     * @throws TransactionRequiredException
377
     * @throws ORMException
378
     */
379 429
    public function find($entityName, $id, $lockMode = null, $lockVersion = null)
380
    {
381 429
        $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
382
383 429
        if ( ! is_array($id)) {
384 383
            if ($class->isIdentifierComposite) {
385
                throw ORMInvalidArgumentException::invalidCompositeIdentifier();
386
            }
387
388 383
            $id = [$class->identifier[0] => $id];
389
        }
390
391 429
        foreach ($id as $i => $value) {
392 429 View Code Duplication
            if (is_object($value) && $this->metadataFactory->hasMetadataFor(ClassUtils::getClass($value))) {
393 7
                $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
394
395 7
                if ($id[$i] === null) {
396 429
                    throw ORMInvalidArgumentException::invalidIdentifierBindingEntity();
397
                }
398
            }
399
        }
400
401 428
        $sortedId = [];
402
403 428 View Code Duplication
        foreach ($class->identifier as $identifier) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404 428
            if ( ! isset($id[$identifier])) {
405 1
                throw ORMException::missingIdentifierField($class->name, $identifier);
406
            }
407
408 427
            $sortedId[$identifier] = $id[$identifier];
409 427
            unset($id[$identifier]);
410
        }
411
412 427
        if ($id) {
413 1
            throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id));
414
        }
415
416 426
        $unitOfWork = $this->getUnitOfWork();
417
418
        // Check identity map first
419 426
        if (($entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) {
420 46
            if ( ! ($entity instanceof $class->name)) {
421 1
                return null;
422
            }
423
424
            switch (true) {
425 45
                case LockMode::OPTIMISTIC === $lockMode:
426 1
                    $this->lock($entity, $lockMode, $lockVersion);
427
                    break;
428
429 45
                case LockMode::NONE === $lockMode:
430 45
                case LockMode::PESSIMISTIC_READ === $lockMode:
431 45
                case LockMode::PESSIMISTIC_WRITE === $lockMode:
432
                    $persister = $unitOfWork->getEntityPersister($class->name);
433
                    $persister->refresh($sortedId, $entity, $lockMode);
434
                    break;
435
            }
436
437 45
            return $entity; // Hit!
438
        }
439
440 407
        $persister = $unitOfWork->getEntityPersister($class->name);
441
442
        switch (true) {
443 407
            case LockMode::OPTIMISTIC === $lockMode:
444 1
                if ( ! $class->isVersioned) {
445 1
                    throw OptimisticLockException::notVersioned($class->name);
446
                }
447
448
                $entity = $persister->load($sortedId);
449
450
                $unitOfWork->lock($entity, $lockMode, $lockVersion);
451
452
                return $entity;
453
454 406
            case LockMode::PESSIMISTIC_READ === $lockMode:
455 405
            case LockMode::PESSIMISTIC_WRITE === $lockMode:
456 2
                if ( ! $this->getConnection()->isTransactionActive()) {
457 2
                    throw TransactionRequiredException::transactionRequired();
458
                }
459
460
                return $persister->load($sortedId, null, null, [], $lockMode);
461
462
            default:
463 404
                return $persister->loadById($sortedId);
464
        }
465
    }
466
467
    /**
468
     * {@inheritDoc}
469
     */
470 92
    public function getReference($entityName, $id)
471
    {
472 92
        $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
473
474 92
        if ( ! is_array($id)) {
475 49
            $id = [$class->identifier[0] => $id];
476
        }
477
478 92
        $sortedId = [];
479
480 92 View Code Duplication
        foreach ($class->identifier as $identifier) {
481 92
            if ( ! isset($id[$identifier])) {
482
                throw ORMException::missingIdentifierField($class->name, $identifier);
483
            }
484
485 92
            $sortedId[$identifier] = $id[$identifier];
486 92
            unset($id[$identifier]);
487
        }
488
489 92
        if ($id) {
490 1
            throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id));
491
        }
492
493
        // Check identity map first, if its already in there just return it.
494 91 View Code Duplication
        if (($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) {
495 27
            return ($entity instanceof $class->name) ? $entity : null;
496
        }
497
498 87
        if ($class->subClasses) {
499 2
            return $this->find($entityName, $sortedId);
500
        }
501
502 87
        $entity = $this->proxyFactory->getProxy($class->name, $sortedId);
503
504 87
        $this->unitOfWork->registerManaged($entity, $sortedId, []);
505
506 87
        return $entity;
507
    }
508
509
    /**
510
     * {@inheritDoc}
511
     */
512 4
    public function getPartialReference($entityName, $identifier)
513
    {
514 4
        $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
515
516
        // Check identity map first, if its already in there just return it.
517 4 View Code Duplication
        if (($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) !== false) {
518 1
            return ($entity instanceof $class->name) ? $entity : null;
519
        }
520
521 3
        if ( ! is_array($identifier)) {
522 3
            $identifier = [$class->identifier[0] => $identifier];
523
        }
524
525 3
        $entity = $class->newInstance();
526
527 3
        $class->setIdentifierValues($entity, $identifier);
528
529 3
        $this->unitOfWork->registerManaged($entity, $identifier, []);
530 3
        $this->unitOfWork->markReadOnly($entity);
531
532 3
        return $entity;
533
    }
534
535
    /**
536
     * Clears the EntityManager. All entities that are currently managed
537
     * by this EntityManager become detached.
538
     *
539
     * @param string|null $entityName if given, only entities of this type will get detached
540
     *
541
     * @return void
542
     *
543
     * @throws ORMInvalidArgumentException                           if a non-null non-string value is given
544
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException if a $entityName is given, but that entity is not
545
     *                                                               found in the mappings
546
     */
547 1254
    public function clear($entityName = null)
548
    {
549 1254
        if (null !== $entityName && ! is_string($entityName)) {
550 1
            throw ORMInvalidArgumentException::invalidEntityName($entityName);
551
        }
552
553 1253
        $this->unitOfWork->clear(
554 1253
            null === $entityName
555 1251
                ? null
556 1253
                : $this->metadataFactory->getMetadataFor($entityName)->getName()
557
        );
558 1252
    }
559
560
    /**
561
     * {@inheritDoc}
562
     */
563 19
    public function close()
564
    {
565 19
        $this->clear();
566
567 19
        $this->closed = true;
568 19
    }
569
570
    /**
571
     * Tells the EntityManager to make an instance managed and persistent.
572
     *
573
     * The entity will be entered into the database at or before transaction
574
     * commit or as a result of the flush operation.
575
     *
576
     * NOTE: The persist operation always considers entities that are not yet known to
577
     * this EntityManager as NEW. Do not pass detached entities to the persist operation.
578
     *
579
     * @param object $entity The instance to make managed and persistent.
580
     *
581
     * @return void
582
     *
583
     * @throws ORMInvalidArgumentException
584
     * @throws ORMException
585
     */
586 1031 View Code Duplication
    public function persist($entity)
587
    {
588 1031
        if ( ! is_object($entity)) {
589 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()', $entity);
590
        }
591
592 1030
        $this->errorIfClosed();
593
594 1029
        $this->unitOfWork->persist($entity);
595 1028
    }
596
597
    /**
598
     * Removes an entity instance.
599
     *
600
     * A removed entity will be removed from the database at or before transaction commit
601
     * or as a result of the flush operation.
602
     *
603
     * @param object $entity The entity instance to remove.
604
     *
605
     * @return void
606
     *
607
     * @throws ORMInvalidArgumentException
608
     * @throws ORMException
609
     */
610 51 View Code Duplication
    public function remove($entity)
611
    {
612 51
        if ( ! is_object($entity)) {
613 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()', $entity);
614
        }
615
616 50
        $this->errorIfClosed();
617
618 49
        $this->unitOfWork->remove($entity);
619 49
    }
620
621
    /**
622
     * Refreshes the persistent state of an entity from the database,
623
     * overriding any local changes that have not yet been persisted.
624
     *
625
     * @param object $entity The entity to refresh.
626
     *
627
     * @return void
628
     *
629
     * @throws ORMInvalidArgumentException
630
     * @throws ORMException
631
     */
632 19 View Code Duplication
    public function refresh($entity)
633
    {
634 19
        if ( ! is_object($entity)) {
635 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()', $entity);
636
        }
637
638 18
        $this->errorIfClosed();
639
640 17
        $this->unitOfWork->refresh($entity);
641 17
    }
642
643
    /**
644
     * Detaches an entity from the EntityManager, causing a managed entity to
645
     * become detached.  Unflushed changes made to the entity if any
646
     * (including removal of the entity), will not be synchronized to the database.
647
     * Entities which previously referenced the detached entity will continue to
648
     * reference it.
649
     *
650
     * @param object $entity The entity to detach.
651
     *
652
     * @return void
653
     *
654
     * @throws ORMInvalidArgumentException
655
     */
656 13
    public function detach($entity)
657
    {
658 13
        if ( ! is_object($entity)) {
659 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#detach()', $entity);
660
        }
661
662 12
        $this->unitOfWork->detach($entity);
663 12
    }
664
665
    /**
666
     * Merges the state of a detached entity into the persistence context
667
     * of this EntityManager and returns the managed copy of the entity.
668
     * The entity passed to merge will not become associated/managed with this EntityManager.
669
     *
670
     * @param object $entity The detached entity to merge into the persistence context.
671
     *
672
     * @return object The managed copy of the entity.
673
     *
674
     * @throws ORMInvalidArgumentException
675
     * @throws ORMException
676
     */
677 42 View Code Duplication
    public function merge($entity)
678
    {
679 42
        if ( ! is_object($entity)) {
680 1
            throw ORMInvalidArgumentException::invalidObject('EntityManager#merge()', $entity);
681
        }
682
683 41
        $this->errorIfClosed();
684
685 40
        return $this->unitOfWork->merge($entity);
686
    }
687
688
    /**
689
     * {@inheritDoc}
690
     *
691
     * @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
692
     * Fatal error: Maximum function nesting level of '100' reached, aborting!
693
     */
694
    public function copy($entity, $deep = false)
695
    {
696
        throw new \BadMethodCallException("Not implemented.");
697
    }
698
699
    /**
700
     * {@inheritDoc}
701
     */
702 9
    public function lock($entity, $lockMode, $lockVersion = null)
703
    {
704 9
        $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
705 2
    }
706
707
    /**
708
     * Gets the repository for an entity class.
709
     *
710
     * @param string $entityName The name of the entity.
711
     *
712
     * @return \Doctrine\ORM\EntityRepository The repository class.
713
     */
714 155
    public function getRepository($entityName)
715
    {
716 155
        return $this->repositoryFactory->getRepository($this, $entityName);
717
    }
718
719
    /**
720
     * Determines whether an entity instance is managed in this EntityManager.
721
     *
722
     * @param object $entity
723
     *
724
     * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
725
     */
726 24
    public function contains($entity)
727
    {
728 24
        return $this->unitOfWork->isScheduledForInsert($entity)
729 22
            || $this->unitOfWork->isInIdentityMap($entity)
730 24
            && ! $this->unitOfWork->isScheduledForDelete($entity);
731
    }
732
733
    /**
734
     * {@inheritDoc}
735
     */
736 2395
    public function getEventManager()
737
    {
738 2395
        return $this->eventManager;
739
    }
740
741
    /**
742
     * {@inheritDoc}
743
     */
744 2395
    public function getConfiguration()
745
    {
746 2395
        return $this->config;
747
    }
748
749
    /**
750
     * Throws an exception if the EntityManager is closed or currently not active.
751
     *
752
     * @return void
753
     *
754
     * @throws ORMException If the EntityManager is closed.
755
     */
756 1050
    private function errorIfClosed()
757
    {
758 1050
        if ($this->closed) {
759 5
            throw ORMException::entityManagerClosed();
760
        }
761 1045
    }
762
763
    /**
764
     * {@inheritDoc}
765
     */
766 1
    public function isOpen()
767
    {
768 1
        return (!$this->closed);
769
    }
770
771
    /**
772
     * {@inheritDoc}
773
     */
774 2395
    public function getUnitOfWork()
775
    {
776 2395
        return $this->unitOfWork;
777
    }
778
779
    /**
780
     * {@inheritDoc}
781
     */
782
    public function getHydrator($hydrationMode)
783
    {
784
        return $this->newHydrator($hydrationMode);
785
    }
786
787
    /**
788
     * {@inheritDoc}
789
     */
790 915
    public function newHydrator($hydrationMode)
791
    {
792
        switch ($hydrationMode) {
793 915
            case Query::HYDRATE_OBJECT:
794 632
                return new Internal\Hydration\ObjectHydrator($this);
795
796 562
            case Query::HYDRATE_ARRAY:
797 36
                return new Internal\Hydration\ArrayHydrator($this);
798
799 531
            case Query::HYDRATE_SCALAR:
800 85
                return new Internal\Hydration\ScalarHydrator($this);
801
802 448
            case Query::HYDRATE_SINGLE_SCALAR:
803 13
                return new Internal\Hydration\SingleScalarHydrator($this);
804
805 439
            case Query::HYDRATE_SIMPLEOBJECT:
806 438
                return new Internal\Hydration\SimpleObjectHydrator($this);
807
808
            default:
809 1
                if (($class = $this->config->getCustomHydrationMode($hydrationMode)) !== null) {
810 1
                    return new $class($this);
811
                }
812
        }
813
814
        throw ORMException::invalidHydrationMode($hydrationMode);
815
    }
816
817
    /**
818
     * {@inheritDoc}
819
     */
820 174
    public function getProxyFactory()
821
    {
822 174
        return $this->proxyFactory;
823
    }
824
825
    /**
826
     * {@inheritDoc}
827
     */
828
    public function initializeObject($obj)
829
    {
830
        $this->unitOfWork->initializeObject($obj);
831
    }
832
833
    /**
834
     * Factory method to create EntityManager instances.
835
     *
836
     * @param array|Connection $connection   An array with the connection parameters or an existing Connection instance.
837
     * @param Configuration    $config       The Configuration instance to use.
838
     * @param EventManager     $eventManager The EventManager instance to use.
839
     *
840
     * @return EntityManager The created EntityManager.
841
     *
842
     * @throws \InvalidArgumentException
843
     * @throws ORMException
844
     */
845 1257
    public static function create($connection, Configuration $config, EventManager $eventManager = null)
846
    {
847 1257
        if ( ! $config->getMetadataDriverImpl()) {
848
            throw ORMException::missingMappingDriverImpl();
849
        }
850
851 1257
        $connection = static::createConnection($connection, $config, $eventManager);
852
853 1256
        return new EntityManager($connection, $config, $connection->getEventManager());
854
    }
855
856
    /**
857
     * Factory method to create Connection instances.
858
     *
859
     * @param array|Connection $connection   An array with the connection parameters or an existing Connection instance.
860
     * @param Configuration    $config       The Configuration instance to use.
861
     * @param EventManager     $eventManager The EventManager instance to use.
862
     *
863
     * @return Connection
864
     *
865
     * @throws \InvalidArgumentException
866
     * @throws ORMException
867
     */
868 1257
    protected static function createConnection($connection, Configuration $config, EventManager $eventManager = null)
869
    {
870 1257
        if (is_array($connection)) {
871
            return DriverManager::getConnection($connection, $config, $eventManager ?: new EventManager());
872
        }
873
874 1257
        if ( ! $connection instanceof Connection) {
875 1
            throw new \InvalidArgumentException(
876 1
                sprintf(
877 1
                    'Invalid $connection argument of type %s given%s.',
878 1
                    is_object($connection) ? get_class($connection) : gettype($connection),
879 1
                    is_object($connection) ? '' : ': "' . $connection . '"'
880
                )
881
            );
882
        }
883
884 1256
        if ($eventManager !== null && $connection->getEventManager() !== $eventManager) {
885
            throw ORMException::mismatchedEventManager();
886
        }
887
888 1256
        return $connection;
889
    }
890
891
    /**
892
     * {@inheritDoc}
893
     */
894 631
    public function getFilters()
895
    {
896 631
        if (null === $this->filterCollection) {
897 631
            $this->filterCollection = new FilterCollection($this);
898
        }
899
900 631
        return $this->filterCollection;
901
    }
902
903
    /**
904
     * {@inheritDoc}
905
     */
906 40
    public function isFiltersStateClean()
907
    {
908 40
        return null === $this->filterCollection || $this->filterCollection->isClean();
909
    }
910
911
    /**
912
     * {@inheritDoc}
913
     */
914 750
    public function hasFilters()
915
    {
916 750
        return null !== $this->filterCollection;
917
    }
918
}
919