source: pro-violet-viettel/sourcecode/application/libraries/Doctrine/ORM/EntityManager.php @ 345

Last change on this file since 345 was 345, checked in by quyenla, 11 years ago

collaborator page

File size: 24.5 KB
Line 
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 LGPL. For more information, see
17 * <http://www.doctrine-project.org>.
18 */
19
20namespace Doctrine\ORM;
21
22use Closure, Exception,
23    Doctrine\Common\EventManager,
24    Doctrine\Common\Persistence\ObjectManager,
25    Doctrine\DBAL\Connection,
26    Doctrine\DBAL\LockMode,
27    Doctrine\ORM\Mapping\ClassMetadata,
28    Doctrine\ORM\Mapping\ClassMetadataFactory,
29    Doctrine\ORM\Query\ResultSetMapping,
30    Doctrine\ORM\Proxy\ProxyFactory,
31    Doctrine\ORM\Query\FilterCollection;
32
33/**
34 * The EntityManager is the central access point to ORM functionality.
35 *
36 * @since   2.0
37 * @author  Benjamin Eberlei <kontakt@beberlei.de>
38 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
39 * @author  Jonathan Wage <jonwage@gmail.com>
40 * @author  Roman Borschel <roman@code-factory.org>
41 */
42class EntityManager implements ObjectManager
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 EntityRepository instances.
67     *
68     * @var array
69     */
70    private $repositories = array();
71
72    /**
73     * The UnitOfWork used to coordinate object-level transactions.
74     *
75     * @var \Doctrine\ORM\UnitOfWork
76     */
77    private $unitOfWork;
78
79    /**
80     * The event manager that is the central point of the event system.
81     *
82     * @var \Doctrine\Common\EventManager
83     */
84    private $eventManager;
85
86    /**
87     * The maintained (cached) hydrators. One instance per type.
88     *
89     * @var array
90     */
91    private $hydrators = array();
92
93    /**
94     * The proxy factory used to create dynamic proxies.
95     *
96     * @var \Doctrine\ORM\Proxy\ProxyFactory
97     */
98    private $proxyFactory;
99
100    /**
101     * The expression builder instance used to generate query expressions.
102     *
103     * @var \Doctrine\ORM\Query\Expr
104     */
105    private $expressionBuilder;
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     * Creates a new EntityManager that operates on the given database connection
123     * and uses the given Configuration and EventManager implementations.
124     *
125     * @param \Doctrine\DBAL\Connection $conn
126     * @param \Doctrine\ORM\Configuration $config
127     * @param \Doctrine\Common\EventManager $eventManager
128     */
129    protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
130    {
131        $this->conn = $conn;
132        $this->config = $config;
133        $this->eventManager = $eventManager;
134
135        $metadataFactoryClassName = $config->getClassMetadataFactoryName();
136        $this->metadataFactory = new $metadataFactoryClassName;
137        $this->metadataFactory->setEntityManager($this);
138        $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
139
140        $this->unitOfWork = new UnitOfWork($this);
141        $this->proxyFactory = new ProxyFactory(
142            $this,
143            $config->getProxyDir(),
144            $config->getProxyNamespace(),
145            $config->getAutoGenerateProxyClasses()
146        );
147    }
148
149    /**
150     * Gets the database connection object used by the EntityManager.
151     *
152     * @return \Doctrine\DBAL\Connection
153     */
154    public function getConnection()
155    {
156        return $this->conn;
157    }
158
159    /**
160     * Gets the metadata factory used to gather the metadata of classes.
161     *
162     * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
163     */
164    public function getMetadataFactory()
165    {
166        return $this->metadataFactory;
167    }
168
169    /**
170     * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
171     *
172     * Example:
173     *
174     * <code>
175     *     $qb = $em->createQueryBuilder();
176     *     $expr = $em->getExpressionBuilder();
177     *     $qb->select('u')->from('User', 'u')
178     *         ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
179     * </code>
180     *
181     * @return \Doctrine\ORM\Query\Expr
182     */
183    public function getExpressionBuilder()
184    {
185        if ($this->expressionBuilder === null) {
186            $this->expressionBuilder = new Query\Expr;
187        }
188
189        return $this->expressionBuilder;
190    }
191
192    /**
193     * Starts a transaction on the underlying database connection.
194     *
195     * @deprecated Use {@link getConnection}.beginTransaction().
196     */
197    public function beginTransaction()
198    {
199        $this->conn->beginTransaction();
200    }
201
202    /**
203     * Executes a function in a transaction.
204     *
205     * The function gets passed this EntityManager instance as an (optional) parameter.
206     *
207     * {@link flush} is invoked prior to transaction commit.
208     *
209     * If an exception occurs during execution of the function or flushing or transaction commit,
210     * the transaction is rolled back, the EntityManager closed and the exception re-thrown.
211     *
212     * @param Closure $func The function to execute transactionally.
213     * @return mixed Returns the non-empty value returned from the closure or true instead
214     */
215    public function transactional(Closure $func)
216    {
217        $this->conn->beginTransaction();
218
219        try {
220            $return = $func($this);
221
222            $this->flush();
223            $this->conn->commit();
224
225            return $return ?: true;
226        } catch (Exception $e) {
227            $this->close();
228            $this->conn->rollback();
229
230            throw $e;
231        }
232    }
233
234    /**
235     * Commits a transaction on the underlying database connection.
236     *
237     * @deprecated Use {@link getConnection}.commit().
238     */
239    public function commit()
240    {
241        $this->conn->commit();
242    }
243
244    /**
245     * Performs a rollback on the underlying database connection.
246     *
247     * @deprecated Use {@link getConnection}.rollback().
248     */
249    public function rollback()
250    {
251        $this->conn->rollback();
252    }
253
254    /**
255     * Returns the ORM metadata descriptor for a class.
256     *
257     * The class name must be the fully-qualified class name without a leading backslash
258     * (as it is returned by get_class($obj)) or an aliased class name.
259     *
260     * Examples:
261     * MyProject\Domain\User
262     * sales:PriceRequest
263     *
264     * @return \Doctrine\ORM\Mapping\ClassMetadata
265     * @internal Performance-sensitive method.
266     */
267    public function getClassMetadata($className)
268    {
269        return $this->metadataFactory->getMetadataFor($className);
270    }
271
272    /**
273     * Creates a new Query object.
274     *
275     * @param string  The DQL string.
276     * @return \Doctrine\ORM\Query
277     */
278    public function createQuery($dql = "")
279    {
280        $query = new Query($this);
281
282        if ( ! empty($dql)) {
283            $query->setDql($dql);
284        }
285
286        return $query;
287    }
288
289    /**
290     * Creates a Query from a named query.
291     *
292     * @param string $name
293     * @return \Doctrine\ORM\Query
294     */
295    public function createNamedQuery($name)
296    {
297        return $this->createQuery($this->config->getNamedQuery($name));
298    }
299
300    /**
301     * Creates a native SQL query.
302     *
303     * @param string $sql
304     * @param ResultSetMapping $rsm The ResultSetMapping to use.
305     * @return NativeQuery
306     */
307    public function createNativeQuery($sql, ResultSetMapping $rsm)
308    {
309        $query = new NativeQuery($this);
310        $query->setSql($sql);
311        $query->setResultSetMapping($rsm);
312
313        return $query;
314    }
315
316    /**
317     * Creates a NativeQuery from a named native query.
318     *
319     * @param string $name
320     * @return \Doctrine\ORM\NativeQuery
321     */
322    public function createNamedNativeQuery($name)
323    {
324        list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
325
326        return $this->createNativeQuery($sql, $rsm);
327    }
328
329    /**
330     * Create a QueryBuilder instance
331     *
332     * @return QueryBuilder $qb
333     */
334    public function createQueryBuilder()
335    {
336        return new QueryBuilder($this);
337    }
338
339    /**
340     * Flushes all changes to objects that have been queued up to now to the database.
341     * This effectively synchronizes the in-memory state of managed objects with the
342     * database.
343     *
344     * If an entity is explicitly passed to this method only this entity and
345     * the cascade-persist semantics + scheduled inserts/removals are synchronized.
346     *
347     * @param object $entity
348     * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
349     *         makes use of optimistic locking fails.
350     */
351    public function flush($entity = null)
352    {
353        $this->errorIfClosed();
354
355        $this->unitOfWork->commit($entity);
356    }
357
358    /**
359     * Finds an Entity by its identifier.
360     *
361     * This is just a convenient shortcut for getRepository($entityName)->find($id).
362     *
363     * @param string $entityName
364     * @param mixed $identifier
365     * @param int $lockMode
366     * @param int $lockVersion
367     * @return object
368     */
369    public function find($entityName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
370    {
371        return $this->getRepository($entityName)->find($identifier, $lockMode, $lockVersion);
372    }
373
374    /**
375     * Gets a reference to the entity identified by the given type and identifier
376     * without actually loading it, if the entity is not yet loaded.
377     *
378     * @param string $entityName The name of the entity type.
379     * @param mixed $id The entity identifier.
380     * @return object The entity reference.
381     */
382    public function getReference($entityName, $id)
383    {
384        $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
385        if ( ! is_array($id)) {
386            $id = array($class->identifier[0] => $id);
387        }
388        $sortedId = array();
389        foreach ($class->identifier as $identifier) {
390            if (!isset($id[$identifier])) {
391                throw ORMException::missingIdentifierField($class->name, $identifier);
392            }
393            $sortedId[$identifier] = $id[$identifier];
394        }
395
396        // Check identity map first, if its already in there just return it.
397        if ($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) {
398            return ($entity instanceof $class->name) ? $entity : null;
399        }
400
401        if ($class->subClasses) {
402            return $this->find($entityName, $sortedId);
403        }
404
405        if ( ! is_array($sortedId)) {
406            $sortedId = array($class->identifier[0] => $sortedId);
407        }
408
409        $entity = $this->proxyFactory->getProxy($class->name, $sortedId);
410        $this->unitOfWork->registerManaged($entity, $sortedId, array());
411
412        return $entity;
413    }
414
415    /**
416     * Gets a partial reference to the entity identified by the given type and identifier
417     * without actually loading it, if the entity is not yet loaded.
418     *
419     * The returned reference may be a partial object if the entity is not yet loaded/managed.
420     * If it is a partial object it will not initialize the rest of the entity state on access.
421     * Thus you can only ever safely access the identifier of an entity obtained through
422     * this method.
423     *
424     * The use-cases for partial references involve maintaining bidirectional associations
425     * without loading one side of the association or to update an entity without loading it.
426     * Note, however, that in the latter case the original (persistent) entity data will
427     * never be visible to the application (especially not event listeners) as it will
428     * never be loaded in the first place.
429     *
430     * @param string $entityName The name of the entity type.
431     * @param mixed $identifier The entity identifier.
432     * @return object The (partial) entity reference.
433     */
434    public function getPartialReference($entityName, $identifier)
435    {
436        $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
437
438        // Check identity map first, if its already in there just return it.
439        if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) {
440            return ($entity instanceof $class->name) ? $entity : null;
441        }
442
443        if ( ! is_array($identifier)) {
444            $identifier = array($class->identifier[0] => $identifier);
445        }
446
447        $entity = $class->newInstance();
448        $class->setIdentifierValues($entity, $identifier);
449        $this->unitOfWork->registerManaged($entity, $identifier, array());
450        $this->unitOfWork->markReadOnly($entity);
451
452        return $entity;
453    }
454
455    /**
456     * Clears the EntityManager. All entities that are currently managed
457     * by this EntityManager become detached.
458     *
459     * @param string $entityName if given, only entities of this type will get detached
460     */
461    public function clear($entityName = null)
462    {
463        $this->unitOfWork->clear($entityName);
464    }
465
466    /**
467     * Closes the EntityManager. All entities that are currently managed
468     * by this EntityManager become detached. The EntityManager may no longer
469     * be used after it is closed.
470     */
471    public function close()
472    {
473        $this->clear();
474        $this->closed = true;
475    }
476
477    /**
478     * Tells the EntityManager to make an instance managed and persistent.
479     *
480     * The entity will be entered into the database at or before transaction
481     * commit or as a result of the flush operation.
482     *
483     * NOTE: The persist operation always considers entities that are not yet known to
484     * this EntityManager as NEW. Do not pass detached entities to the persist operation.
485     *
486     * @param object $object The instance to make managed and persistent.
487     */
488    public function persist($entity)
489    {
490        if ( ! is_object($entity)) {
491            throw new \InvalidArgumentException(gettype($entity));
492        }
493
494        $this->errorIfClosed();
495
496        $this->unitOfWork->persist($entity);
497    }
498
499    /**
500     * Removes an entity instance.
501     *
502     * A removed entity will be removed from the database at or before transaction commit
503     * or as a result of the flush operation.
504     *
505     * @param object $entity The entity instance to remove.
506     */
507    public function remove($entity)
508    {
509        if ( ! is_object($entity)) {
510            throw new \InvalidArgumentException(gettype($entity));
511        }
512
513        $this->errorIfClosed();
514
515        $this->unitOfWork->remove($entity);
516    }
517
518    /**
519     * Refreshes the persistent state of an entity from the database,
520     * overriding any local changes that have not yet been persisted.
521     *
522     * @param object $entity The entity to refresh.
523     */
524    public function refresh($entity)
525    {
526        if ( ! is_object($entity)) {
527            throw new \InvalidArgumentException(gettype($entity));
528        }
529
530        $this->errorIfClosed();
531
532        $this->unitOfWork->refresh($entity);
533    }
534
535    /**
536     * Detaches an entity from the EntityManager, causing a managed entity to
537     * become detached.  Unflushed changes made to the entity if any
538     * (including removal of the entity), will not be synchronized to the database.
539     * Entities which previously referenced the detached entity will continue to
540     * reference it.
541     *
542     * @param object $entity The entity to detach.
543     */
544    public function detach($entity)
545    {
546        if ( ! is_object($entity)) {
547            throw new \InvalidArgumentException(gettype($entity));
548        }
549
550        $this->unitOfWork->detach($entity);
551    }
552
553    /**
554     * Merges the state of a detached entity into the persistence context
555     * of this EntityManager and returns the managed copy of the entity.
556     * The entity passed to merge will not become associated/managed with this EntityManager.
557     *
558     * @param object $entity The detached entity to merge into the persistence context.
559     * @return object The managed copy of the entity.
560     */
561    public function merge($entity)
562    {
563        if ( ! is_object($entity)) {
564            throw new \InvalidArgumentException(gettype($entity));
565        }
566
567        $this->errorIfClosed();
568
569        return $this->unitOfWork->merge($entity);
570    }
571
572    /**
573     * Creates a copy of the given entity. Can create a shallow or a deep copy.
574     *
575     * @param object $entity  The entity to copy.
576     * @return object  The new entity.
577     * @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
578     * Fatal error: Maximum function nesting level of '100' reached, aborting!
579     */
580    public function copy($entity, $deep = false)
581    {
582        throw new \BadMethodCallException("Not implemented.");
583    }
584
585    /**
586     * Acquire a lock on the given entity.
587     *
588     * @param object $entity
589     * @param int $lockMode
590     * @param int $lockVersion
591     * @throws OptimisticLockException
592     * @throws PessimisticLockException
593     */
594    public function lock($entity, $lockMode, $lockVersion = null)
595    {
596        $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
597    }
598
599    /**
600     * Gets the repository for an entity class.
601     *
602     * @param string $entityName The name of the entity.
603     * @return EntityRepository The repository class.
604     */
605    public function getRepository($entityName)
606    {
607        $entityName = ltrim($entityName, '\\');
608
609        if (isset($this->repositories[$entityName])) {
610            return $this->repositories[$entityName];
611        }
612
613        $metadata = $this->getClassMetadata($entityName);
614        $repositoryClassName = $metadata->customRepositoryClassName;
615
616        if ($repositoryClassName === null) {
617            $repositoryClassName = $this->config->getDefaultRepositoryClassName();
618        }
619
620        $repository = new $repositoryClassName($this, $metadata);
621
622        $this->repositories[$entityName] = $repository;
623
624        return $repository;
625    }
626
627    /**
628     * Determines whether an entity instance is managed in this EntityManager.
629     *
630     * @param object $entity
631     * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
632     */
633    public function contains($entity)
634    {
635        return $this->unitOfWork->isScheduledForInsert($entity)
636            || $this->unitOfWork->isInIdentityMap($entity)
637            && ! $this->unitOfWork->isScheduledForDelete($entity);
638    }
639
640    /**
641     * Gets the EventManager used by the EntityManager.
642     *
643     * @return \Doctrine\Common\EventManager
644     */
645    public function getEventManager()
646    {
647        return $this->eventManager;
648    }
649
650    /**
651     * Gets the Configuration used by the EntityManager.
652     *
653     * @return \Doctrine\ORM\Configuration
654     */
655    public function getConfiguration()
656    {
657        return $this->config;
658    }
659
660    /**
661     * Throws an exception if the EntityManager is closed or currently not active.
662     *
663     * @throws ORMException If the EntityManager is closed.
664     */
665    private function errorIfClosed()
666    {
667        if ($this->closed) {
668            throw ORMException::entityManagerClosed();
669        }
670    }
671
672    /**
673     * Check if the Entity manager is open or closed.
674     *
675     * @return bool
676     */
677    public function isOpen()
678    {
679        return (!$this->closed);
680    }
681
682    /**
683     * Gets the UnitOfWork used by the EntityManager to coordinate operations.
684     *
685     * @return \Doctrine\ORM\UnitOfWork
686     */
687    public function getUnitOfWork()
688    {
689        return $this->unitOfWork;
690    }
691
692    /**
693     * Gets a hydrator for the given hydration mode.
694     *
695     * This method caches the hydrator instances which is used for all queries that don't
696     * selectively iterate over the result.
697     *
698     * @param int $hydrationMode
699     * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
700     */
701    public function getHydrator($hydrationMode)
702    {
703        if ( ! isset($this->hydrators[$hydrationMode])) {
704            $this->hydrators[$hydrationMode] = $this->newHydrator($hydrationMode);
705        }
706
707        return $this->hydrators[$hydrationMode];
708    }
709
710    /**
711     * Create a new instance for the given hydration mode.
712     *
713     * @param  int $hydrationMode
714     * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
715     */
716    public function newHydrator($hydrationMode)
717    {
718        switch ($hydrationMode) {
719            case Query::HYDRATE_OBJECT:
720                return new Internal\Hydration\ObjectHydrator($this);
721
722            case Query::HYDRATE_ARRAY:
723                return new Internal\Hydration\ArrayHydrator($this);
724
725            case Query::HYDRATE_SCALAR:
726                return new Internal\Hydration\ScalarHydrator($this);
727
728            case Query::HYDRATE_SINGLE_SCALAR:
729                return new Internal\Hydration\SingleScalarHydrator($this);
730
731            case Query::HYDRATE_SIMPLEOBJECT:
732                return new Internal\Hydration\SimpleObjectHydrator($this);
733
734            default:
735                if ($class = $this->config->getCustomHydrationMode($hydrationMode)) {
736                    return new $class($this);
737                }
738        }
739
740        throw ORMException::invalidHydrationMode($hydrationMode);
741    }
742
743    /**
744     * Gets the proxy factory used by the EntityManager to create entity proxies.
745     *
746     * @return ProxyFactory
747     */
748    public function getProxyFactory()
749    {
750        return $this->proxyFactory;
751    }
752
753    /**
754     * Helper method to initialize a lazy loading proxy or persistent collection.
755     *
756     * This method is a no-op for other objects
757     *
758     * @param object $obj
759     */
760    public function initializeObject($obj)
761    {
762        $this->unitOfWork->initializeObject($obj);
763    }
764
765    /**
766     * Factory method to create EntityManager instances.
767     *
768     * @param mixed $conn An array with the connection parameters or an existing
769     *      Connection instance.
770     * @param Configuration $config The Configuration instance to use.
771     * @param EventManager $eventManager The EventManager instance to use.
772     * @return EntityManager The created EntityManager.
773     */
774    public static function create($conn, Configuration $config, EventManager $eventManager = null)
775    {
776        if ( ! $config->getMetadataDriverImpl()) {
777            throw ORMException::missingMappingDriverImpl();
778        }
779
780        switch (true) {
781            case (is_array($conn)):
782                $conn = \Doctrine\DBAL\DriverManager::getConnection(
783                    $conn, $config, ($eventManager ?: new EventManager())
784                );
785                break;
786
787            case ($conn instanceof Connection):
788                if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
789                     throw ORMException::mismatchedEventManager();
790                }
791                break;
792
793            default:
794                throw new \InvalidArgumentException("Invalid argument: " . $conn);
795        }
796
797        return new EntityManager($conn, $config, $conn->getEventManager());
798    }
799
800    /**
801     * Gets the enabled filters.
802     *
803     * @return FilterCollection The active filter collection.
804     */
805    public function getFilters()
806    {
807        if (null === $this->filterCollection) {
808            $this->filterCollection = new FilterCollection($this);
809        }
810
811        return $this->filterCollection;
812    }
813
814    /**
815     * Checks whether the state of the filter collection is clean.
816     *
817     * @return boolean True, if the filter collection is clean.
818     */
819    public function isFiltersStateClean()
820    {
821        return null === $this->filterCollection
822           || $this->filterCollection->isClean();
823    }
824
825    /**
826     * Checks whether the Entity Manager has filters.
827     *
828     * @return True, if the EM has a filter collection.
829     */
830    public function hasFilters()
831    {
832        return null !== $this->filterCollection;
833    }
834}
Note: See TracBrowser for help on using the repository browser.