Merge pull request #423 from FabioBatSilva/DDC-1955
DDC-1955 - @EntityListeners
This commit is contained in:
commit
71a68a5c6f
@ -196,9 +196,7 @@ listeners:
|
||||
|
||||
|
||||
- Lifecycle Callbacks are methods on the entity classes that are
|
||||
called when the event is triggered. They receive absolutely no
|
||||
arguments and are specifically designed to allow changes inside the
|
||||
entity classes state.
|
||||
called when the event is triggered. They receives some kind of ``EventArgs``.
|
||||
- Lifecycle Event Listeners are classes with specific callback
|
||||
methods that receives some kind of ``EventArgs`` instance which
|
||||
give access to the entity, EntityManager or other relevant data.
|
||||
@ -336,6 +334,31 @@ The ``key`` of the lifecycleCallbacks is the name of the method and
|
||||
the value is the event type. The allowed event types are the ones
|
||||
listed in the previous Lifecycle Events section.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Lifecycle Callbacks Event Argument
|
||||
-----------------------------------
|
||||
|
||||
Since 2.4 the triggered event is given to the lifecycle-callback.
|
||||
|
||||
With the additional argument you have access to the
|
||||
``EntityManager`` and ``UnitOfWork`` APIs inside these callback methods.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
// ...
|
||||
|
||||
class User
|
||||
{
|
||||
public function preUpdate(PreUpdateEventArgs $event)
|
||||
{
|
||||
if ($event->hasChangedField('username')) {
|
||||
// Do something when the username is changed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Listening to Lifecycle Events
|
||||
-----------------------------
|
||||
|
||||
@ -626,6 +649,207 @@ postLoad
|
||||
This event is called after an entity is constructed by the
|
||||
EntityManager.
|
||||
|
||||
Entity listeners
|
||||
----------------
|
||||
|
||||
An entity listeners is a lifecycle listener classes used for an entity.
|
||||
|
||||
- The entity listeners mapping may be applied to an entity class or mapped superclass.
|
||||
- An entity listener is defined by mapping the entity class with the corresponding mapping.
|
||||
|
||||
.. configuration-block::
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
namespace MyProject\Entity;
|
||||
|
||||
/** @Entity @EntityListeners({"UserListener"}) */
|
||||
class User
|
||||
{
|
||||
// ....
|
||||
}
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping>
|
||||
<entity name="MyProject\Entity\User">
|
||||
<entity-listeners>
|
||||
<entity-listener class="UserListener"/>
|
||||
</entity-listeners>
|
||||
<!-- .... -->
|
||||
</entity>
|
||||
</doctrine-mapping>
|
||||
.. code-block:: yaml
|
||||
|
||||
MyProject\Entity\User:
|
||||
type: entity
|
||||
entityListeners:
|
||||
UserListener:
|
||||
# ....
|
||||
|
||||
.. _reference-entity-listeners:
|
||||
|
||||
Entity listeners class
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An ``Entity Listener`` could be any class, by default it should be a class with a no-arg constructor.
|
||||
|
||||
- Different from :ref:`reference-events-implementing-listeners` an ``Entity Listener`` is invoked just to the specified entity
|
||||
- An entity listener method receives two arguments, the entity instance and the lifecycle event.
|
||||
- A callback method could be defined by naming convention or specifying a method mapping.
|
||||
- When the listener mapping is not given the parser will lookup for methods that match with the naming convention.
|
||||
- When the listener mapping is given the parser won't lookup for any naming convention.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class UserListener
|
||||
{
|
||||
public function preUpdate(User $user, PreUpdateEventArgs $event)
|
||||
{
|
||||
// Do something on pre update.
|
||||
}
|
||||
}
|
||||
|
||||
To define a specific event listener method
|
||||
you should map the listener method using the event type mapping.
|
||||
|
||||
.. configuration-block::
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class UserListener
|
||||
{
|
||||
/** @PrePersist */
|
||||
public function prePersistHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
|
||||
/** @PostPersist */
|
||||
public function postPersistHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
|
||||
/** @PreUpdate */
|
||||
public function preUpdateHandler(User $user, PreUpdateEventArgs $event) { // ... }
|
||||
|
||||
/** @PostUpdate */
|
||||
public function postUpdateHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
|
||||
/** @PostRemove */
|
||||
public function postRemoveHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
|
||||
/** @PreRemove */
|
||||
public function preRemoveHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
|
||||
/** @PreFlush */
|
||||
public function preFlushHandler(User $user, PreFlushEventArgs $event) { // ... }
|
||||
|
||||
/** @PostLoad */
|
||||
public function postLoadHandler(User $user, LifecycleEventArgs $event) { // ... }
|
||||
}
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping>
|
||||
<entity name="MyProject\Entity\User">
|
||||
<entity-listeners>
|
||||
<entity-listener class="UserListener">
|
||||
<lifecycle-callback type="preFlush" method="preFlushHandler"/>
|
||||
<lifecycle-callback type="postLoad" method="postLoadHandler"/>
|
||||
|
||||
<lifecycle-callback type="postPersist" method="postPersistHandler"/>
|
||||
<lifecycle-callback type="prePersist" method="prePersistHandler"/>
|
||||
|
||||
<lifecycle-callback type="postUpdate" method="postUpdateHandler"/>
|
||||
<lifecycle-callback type="preUpdate" method="preUpdateHandler"/>
|
||||
|
||||
<lifecycle-callback type="postRemove" method="postRemoveHandler"/>
|
||||
<lifecycle-callback type="preRemove" method="preRemoveHandler"/>
|
||||
</entity-listener>
|
||||
</entity-listeners>
|
||||
<!-- .... -->
|
||||
</entity>
|
||||
</doctrine-mapping>
|
||||
.. code-block:: yaml
|
||||
|
||||
MyProject\Entity\User:
|
||||
type: entity
|
||||
entityListeners:
|
||||
UserListener:
|
||||
preFlush: [preFlushHandler]
|
||||
postLoad: [postLoadHandler]
|
||||
|
||||
postPersist: [postPersistHandler]
|
||||
prePersist: [prePersistHandler]
|
||||
|
||||
postUpdate: [postUpdateHandler]
|
||||
preUpdate: [preUpdateHandler]
|
||||
|
||||
postRemove: [postRemoveHandler]
|
||||
preRemove: [preRemoveHandler]
|
||||
# ....
|
||||
|
||||
|
||||
|
||||
Entity listeners resolver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Doctrine invoke the listener resolver to get the listener instance.
|
||||
|
||||
- An resolver allows you register a specific ``Entity Listener`` instance.
|
||||
- You can also implement your own resolver by extending ``Doctrine\ORM\Mapping\DefaultEntityListenerResolver`` or implementing ``Doctrine\ORM\Mapping\EntityListenerResolver``
|
||||
|
||||
Specifying an entity listener instance :
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
// User.php
|
||||
|
||||
/** @Entity @EntityListeners({"UserListener"}) */
|
||||
class User
|
||||
{
|
||||
// ....
|
||||
}
|
||||
|
||||
// UserListener.php
|
||||
class UserListener
|
||||
{
|
||||
public function __construct(MyService $service)
|
||||
{
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
public function preUpdate(User $user, PreUpdateEventArgs $event)
|
||||
{
|
||||
$this->service->doSomething($user);
|
||||
}
|
||||
}
|
||||
|
||||
// register a entity listener.
|
||||
$listener = $container->get('user_listener');
|
||||
$em->getConfiguration()->getEntityListenerResolver()->register($listener);
|
||||
|
||||
Implementing your own resolver :
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class MyEntityListenerResolver extends \Doctrine\ORM\Mapping\DefaultEntityListenerResolver
|
||||
{
|
||||
public function __construct($container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function resolve($className)
|
||||
{
|
||||
// resolve the service id by the given class name;
|
||||
$id = 'user_listener';
|
||||
|
||||
return $this->container->get($id);
|
||||
}
|
||||
}
|
||||
|
||||
// configure the listener resolver.
|
||||
$em->getConfiguration()->setEntityListenerResolver($container->get('my_resolver'));
|
||||
|
||||
Load ClassMetadata Event
|
||||
------------------------
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
<xs:enumeration value="preRemove"/>
|
||||
<xs:enumeration value="postRemove"/>
|
||||
<xs:enumeration value="postLoad"/>
|
||||
<xs:enumeration value="preFlush"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
@ -98,6 +99,20 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-listener">
|
||||
<xs:sequence>
|
||||
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="class" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-listeners">
|
||||
<xs:sequence>
|
||||
<xs:element name="entity-listener" type="orm:entity-listener" minOccurs="1" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="column-result">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
@ -137,6 +152,7 @@
|
||||
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
|
||||
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
|
||||
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="entity-listeners" type="orm:entity-listeners" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="named-native-queries" type="orm:named-native-queries" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
@ -29,6 +29,8 @@ use Doctrine\ORM\Mapping\QuoteStrategy;
|
||||
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
|
||||
use Doctrine\ORM\Mapping\NamingStrategy;
|
||||
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
|
||||
use Doctrine\ORM\Mapping\EntityListenerResolver;
|
||||
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
|
||||
use Doctrine\Common\Annotations\SimpleAnnotationReader;
|
||||
use Doctrine\Common\Annotations\CachedReader;
|
||||
|
||||
@ -763,4 +765,30 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
return $this->_attributes['quoteStrategy'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entity listener resolver.
|
||||
*
|
||||
* @since 2.4
|
||||
* @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver
|
||||
*/
|
||||
public function setEntityListenerResolver(EntityListenerResolver $resolver)
|
||||
{
|
||||
$this->_attributes['entityListenerResolver'] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity listener resolver.
|
||||
*
|
||||
* @since 2.4
|
||||
* @return \Doctrine\ORM\Mapping\EntityListenerResolver
|
||||
*/
|
||||
public function getEntityListenerResolver()
|
||||
{
|
||||
if ( ! isset($this->_attributes['entityListenerResolver'])) {
|
||||
$this->_attributes['entityListenerResolver'] = new DefaultEntityListenerResolver();
|
||||
}
|
||||
|
||||
return $this->_attributes['entityListenerResolver'];
|
||||
}
|
||||
}
|
||||
|
120
lib/Doctrine/ORM/Event/ListenersInvoker.php
Normal file
120
lib/Doctrine/ORM/Event/ListenersInvoker.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\Common\EventArgs;
|
||||
|
||||
/**
|
||||
* A method invoker based on entity lifecycle.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.4
|
||||
*/
|
||||
class ListenersInvoker
|
||||
{
|
||||
const INVOKE_NONE = 0;
|
||||
const INVOKE_LISTENERS = 1;
|
||||
const INVOKE_CALLBACKS = 2;
|
||||
const INVOKE_MANAGER = 4;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver.
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
/**
|
||||
* The EventManager used for dispatching events.
|
||||
*
|
||||
* @var \Doctrine\Common\EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
/**
|
||||
* Initializes a new ListenersInvoker instance.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->eventManager = $em->getEventManager();
|
||||
$this->resolver = $em->getConfiguration()->getEntityListenerResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subscribed event systems
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata.
|
||||
* @param string $eventName The entity lifecycle event.
|
||||
*
|
||||
* @return integer Bitmask of subscribed event systems.
|
||||
*/
|
||||
public function getSubscribedSystems(ClassMetadata $metadata, $eventName)
|
||||
{
|
||||
$invoke = self::INVOKE_NONE;
|
||||
|
||||
if (isset($metadata->lifecycleCallbacks[$eventName])) {
|
||||
$invoke |= self::INVOKE_CALLBACKS;
|
||||
}
|
||||
|
||||
if (isset($metadata->entityListeners[$eventName])) {
|
||||
$invoke |= self::INVOKE_LISTENERS;
|
||||
}
|
||||
|
||||
if ($this->eventManager->hasListeners($eventName)) {
|
||||
$invoke |= self::INVOKE_MANAGER;
|
||||
}
|
||||
|
||||
return $invoke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the lifecycle event of the given entity.
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata.
|
||||
* @param string $eventName The entity lifecycle event.
|
||||
* @param object $entity The Entity on which the event occured.
|
||||
* @param \Doctrine\Common\EventArgs $event The Event args.
|
||||
* @param integer $invoke Bitmask to invoke listeners.
|
||||
*/
|
||||
public function invoke(ClassMetadata $metadata, $eventName, $entity, EventArgs $event, $invoke)
|
||||
{
|
||||
if($invoke & self::INVOKE_CALLBACKS) {
|
||||
foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) {
|
||||
$entity->$callback($event);
|
||||
}
|
||||
}
|
||||
|
||||
if($invoke & self::INVOKE_LISTENERS) {
|
||||
foreach ($metadata->entityListeners[$eventName] as $listener) {
|
||||
$class = $listener['class'];
|
||||
$method = $listener['method'];
|
||||
$instance = $this->resolver->resolve($class);
|
||||
|
||||
$instance->$method($entity, $event);
|
||||
}
|
||||
}
|
||||
|
||||
if($invoke & self::INVOKE_MANAGER) {
|
||||
$this->eventManager->dispatchEvent($eventName, $event);
|
||||
}
|
||||
}
|
||||
}
|
72
lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php
Normal file
72
lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
/**
|
||||
* Builder for entity listeners.
|
||||
*
|
||||
* @since 2.4
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
class EntityListenerBuilder
|
||||
{
|
||||
/**
|
||||
* @var array Hash-map to handle event names.
|
||||
*/
|
||||
static private $events = array(
|
||||
Events::preRemove => true,
|
||||
Events::postRemove => true,
|
||||
Events::prePersist => true,
|
||||
Events::postPersist => true,
|
||||
Events::preUpdate => true,
|
||||
Events::postUpdate => true,
|
||||
Events::postLoad => true,
|
||||
Events::preFlush => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Lookup the entity class to find methods that match to event lifecycle names
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata.
|
||||
* @param string $className The listener class name.
|
||||
*
|
||||
* @throws \Doctrine\ORM\Mapping\MappingException When the listener class not found.
|
||||
*/
|
||||
static public function bindEntityListener(ClassMetadata $metadata, $className)
|
||||
{
|
||||
$class = $metadata->fullyQualifiedClassName($className);
|
||||
|
||||
if ( ! class_exists($class)) {
|
||||
throw MappingException::entityListenerClassNotFound($class, $className);
|
||||
}
|
||||
|
||||
foreach (get_class_methods($class) as $method) {
|
||||
if ( ! isset(self::$events[$method])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata->addEntityListener($method, $class, $method);
|
||||
}
|
||||
}
|
||||
}
|
@ -156,6 +156,10 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
$this->addInheritedSqlResultSetMappings($class, $parent);
|
||||
}
|
||||
|
||||
if ($parent && !empty($parent->entityListeners) && empty($class->entityListeners)) {
|
||||
$class->entityListeners = $parent->entityListeners;
|
||||
}
|
||||
|
||||
$class->setParentClasses($nonSuperclassParents);
|
||||
|
||||
if ( $class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) {
|
||||
@ -458,7 +462,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
|
||||
}
|
||||
|
||||
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === "bigint")
|
||||
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint')
|
||||
? new BigIntegerIdentityGenerator($sequenceName)
|
||||
: new IdentityGenerator($sequenceName);
|
||||
|
||||
|
@ -26,6 +26,7 @@ use Doctrine\DBAL\Types\Type;
|
||||
use ReflectionClass;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Common\ClassLoader;
|
||||
use Doctrine\Common\EventArgs;
|
||||
|
||||
/**
|
||||
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata
|
||||
@ -436,6 +437,13 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public $lifecycleCallbacks = array();
|
||||
|
||||
/**
|
||||
* READ-ONLY: The registered entity listeners.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $entityListeners = array();
|
||||
|
||||
/**
|
||||
* READ-ONLY: The association mappings of this class.
|
||||
*
|
||||
@ -1313,10 +1321,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
$mapping['sourceEntity'] = $this->name;
|
||||
|
||||
if (isset($mapping['targetEntity'])) {
|
||||
if (strlen($this->namespace) > 0 && strpos($mapping['targetEntity'], '\\') === false) {
|
||||
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
|
||||
}
|
||||
|
||||
$mapping['targetEntity'] = $this->fullyQualifiedClassName($mapping['targetEntity']);
|
||||
$mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\');
|
||||
}
|
||||
|
||||
@ -1904,11 +1909,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
public function setSubclasses(array $subclasses)
|
||||
{
|
||||
foreach ($subclasses as $subclass) {
|
||||
if (strpos($subclass, '\\') === false && strlen($this->namespace)) {
|
||||
$this->subClasses[] = $this->namespace . '\\' . $subclass;
|
||||
} else {
|
||||
$this->subClasses[] = $subclass;
|
||||
}
|
||||
$this->subClasses[] = $this->fullyQualifiedClassName($subclass);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2261,11 +2262,9 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
|
||||
$queryMapping['isSelfClass'] = true;
|
||||
$queryMapping['resultClass'] = $this->name;
|
||||
|
||||
} else if (strlen($this->namespace) > 0 && strpos($queryMapping['resultClass'], '\\') === false) {
|
||||
$queryMapping['resultClass'] = $this->namespace . '\\' . $queryMapping['resultClass'];
|
||||
}
|
||||
|
||||
$queryMapping['resultClass'] = $this->fullyQualifiedClassName($queryMapping['resultClass']);
|
||||
$queryMapping['resultClass'] = ltrim($queryMapping['resultClass'], '\\');
|
||||
}
|
||||
|
||||
@ -2304,10 +2303,10 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
$entityResult['isSelfClass'] = true;
|
||||
$entityResult['entityClass'] = $this->name;
|
||||
|
||||
} else if (strlen($this->namespace) > 0 && strpos($entityResult['entityClass'], '\\') === false) {
|
||||
$entityResult['entityClass'] = $this->namespace . '\\' . $entityResult['entityClass'];
|
||||
}
|
||||
|
||||
$entityResult['entityClass'] = $this->fullyQualifiedClassName($entityResult['entityClass']);
|
||||
|
||||
$resultMapping['entities'][$key]['entityClass'] = ltrim($entityResult['entityClass'], '\\');
|
||||
$resultMapping['entities'][$key]['isSelfClass'] = $entityResult['isSelfClass'];
|
||||
|
||||
@ -2419,17 +2418,15 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function setCustomRepositoryClass($repositoryClassName)
|
||||
{
|
||||
if ($repositoryClassName !== null && strpos($repositoryClassName, '\\') === false
|
||||
&& strlen($this->namespace) > 0) {
|
||||
$repositoryClassName = $this->namespace . '\\' . $repositoryClassName;
|
||||
}
|
||||
$this->customRepositoryClassName = $repositoryClassName;
|
||||
$this->customRepositoryClassName = $this->fullyQualifiedClassName($repositoryClassName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the lifecycle event of the given entity to the registered
|
||||
* lifecycle callbacks and lifecycle listeners.
|
||||
*
|
||||
* @deprecated Deprecated since version 2.4 in favor of \Doctrine\ORM\Event\ListenersInvoker
|
||||
*
|
||||
* @param string $lifecycleEvent The lifecycle event.
|
||||
* @param object $entity The Entity on which the event occured.
|
||||
*
|
||||
@ -2492,6 +2489,33 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
$this->lifecycleCallbacks = $callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a entity listener for entities of this class.
|
||||
*
|
||||
* @param string $eventName The entity lifecycle event.
|
||||
* @param string $class The listener class.
|
||||
* @param string $method The listener callback method.
|
||||
*
|
||||
* @throws \Doctrine\ORM\Mapping\MappingException
|
||||
*/
|
||||
public function addEntityListener($eventName, $class, $method)
|
||||
{
|
||||
$class = $this->fullyQualifiedClassName($class);
|
||||
|
||||
if ( ! class_exists($class)) {
|
||||
throw MappingException::entityListenerClassNotFound($class, $this->name);
|
||||
}
|
||||
|
||||
if ( ! method_exists($class, $method)) {
|
||||
throw MappingException::entityListenerMethodNotFound($class, $method, $this->name);
|
||||
}
|
||||
|
||||
$this->entityListeners[$eventName][] = array(
|
||||
'class' => $class,
|
||||
'method' => $method
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the discriminator column definition.
|
||||
*
|
||||
@ -2557,10 +2581,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function addDiscriminatorMapClass($name, $className)
|
||||
{
|
||||
if (strlen($this->namespace) > 0 && strpos($className, '\\') === false) {
|
||||
$className = $this->namespace . '\\' . $className;
|
||||
}
|
||||
|
||||
$className = $this->fullyQualifiedClassName($className);
|
||||
$className = ltrim($className, '\\');
|
||||
$this->discriminatorMap[$name] = $className;
|
||||
|
||||
@ -2982,4 +3003,17 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
}
|
||||
return $relations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
public function fullyQualifiedClassName($className)
|
||||
{
|
||||
if ($className !== null && strpos($className, '\\') === false && strlen($this->namespace) > 0) {
|
||||
return $this->namespace . '\\' . $className;
|
||||
}
|
||||
|
||||
return $className;
|
||||
}
|
||||
}
|
||||
|
75
lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php
Normal file
75
lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* The default DefaultEntityListene
|
||||
*
|
||||
* @since 2.4
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
class DefaultEntityListenerResolver implements EntityListenerResolver
|
||||
{
|
||||
/**
|
||||
* @var array Map to store entity listener instances.
|
||||
*/
|
||||
private $instances = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clear($className = null)
|
||||
{
|
||||
if ($className === null) {
|
||||
$this->instances = array();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->instances[$className = trim($className, '\\')])) {
|
||||
unset($this->instances[$className]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register($object)
|
||||
{
|
||||
if ( ! is_object($object)) {
|
||||
throw new \InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object)));
|
||||
}
|
||||
|
||||
$this->instances[get_class($object)] = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve($className)
|
||||
{
|
||||
if (isset($this->instances[$className = trim($className, '\\')])) {
|
||||
return $this->instances[$className];
|
||||
}
|
||||
|
||||
return $this->instances[$className] = new $className();
|
||||
}
|
||||
}
|
@ -23,8 +23,10 @@ use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\ORM\Mapping\JoinColumn;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
/**
|
||||
* The AnnotationDriver reads the mapping metadata from docblock annotations.
|
||||
@ -384,9 +386,8 @@ class AnnotationDriver extends AbstractAnnotationDriver
|
||||
|
||||
// Check for JoinTable annotations
|
||||
if ($associationOverride->joinTable) {
|
||||
$joinTable = null;
|
||||
$joinTableAnnot = $associationOverride->joinTable;
|
||||
$joinTable = array(
|
||||
$joinTable = array(
|
||||
'name' => $joinTableAnnot->name,
|
||||
'schema' => $joinTableAnnot->schema
|
||||
);
|
||||
@ -415,54 +416,47 @@ class AnnotationDriver extends AbstractAnnotationDriver
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate EntityListeners annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\EntityListeners'])) {
|
||||
$entityListenersAnnot = $classAnnotations['Doctrine\ORM\Mapping\EntityListeners'];
|
||||
|
||||
foreach ($entityListenersAnnot->value as $item) {
|
||||
$listenerClassName = $metadata->fullyQualifiedClassName($item);
|
||||
|
||||
if ( ! class_exists($listenerClassName)) {
|
||||
throw MappingException::entityListenerClassNotFound($listenerClassName, $className);
|
||||
}
|
||||
|
||||
$hasMapping = false;
|
||||
$listenerClass = new \ReflectionClass($listenerClassName);
|
||||
/* @var $method \ReflectionMethod */
|
||||
foreach ($listenerClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
// find method callbacks.
|
||||
$callbacks = $this->getMethodCallbacks($method);
|
||||
$hasMapping = $hasMapping ?: ( ! empty($callbacks));
|
||||
|
||||
foreach ($callbacks as $value) {
|
||||
$metadata->addEntityListener($value[1], $listenerClassName, $value[0]);
|
||||
}
|
||||
}
|
||||
// Evaluate the listener using naming convention.
|
||||
if ( ! $hasMapping ) {
|
||||
EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate @HasLifecycleCallbacks annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
|
||||
/* @var $method \ReflectionMethod */
|
||||
foreach ($class->getMethods() as $method) {
|
||||
foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
// filter for the declaring class only, callbacks from parents will already be registered.
|
||||
if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
|
||||
$annotations = $this->reader->getMethodAnnotations($method);
|
||||
if ($method->getDeclaringClass()->name !== $class->name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($annotations) {
|
||||
foreach ($annotations as $key => $annot) {
|
||||
if ( ! is_numeric($key)) {
|
||||
continue;
|
||||
}
|
||||
$annotations[get_class($annot)] = $annot;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostPersist'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postPersist);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PreUpdate'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preUpdate);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostUpdate'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postUpdate);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PreRemove'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preRemove);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostRemove'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postRemove);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
|
||||
}
|
||||
foreach ($this->getMethodCallbacks($method) as $value) {
|
||||
$metadata->addLifecycleCallback($value[0], $value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -488,9 +482,56 @@ class AnnotationDriver extends AbstractAnnotationDriver
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given JoinColumn as array.
|
||||
* Parses the given method.
|
||||
*
|
||||
* @param JoinColumn $joinColumn
|
||||
* @param \ReflectionMethod $method
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getMethodCallbacks(\ReflectionMethod $method)
|
||||
{
|
||||
$callbacks = array();
|
||||
$annotations = $this->reader->getMethodAnnotations($method);
|
||||
|
||||
foreach ($annotations as $annot) {
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PrePersist) {
|
||||
$callbacks[] = array($method->name, Events::prePersist);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PostPersist) {
|
||||
$callbacks[] = array($method->name, Events::postPersist);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PreUpdate) {
|
||||
$callbacks[] = array($method->name, Events::preUpdate);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PostUpdate) {
|
||||
$callbacks[] = array($method->name, Events::postUpdate);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PreRemove) {
|
||||
$callbacks[] = array($method->name, Events::preRemove);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PostRemove) {
|
||||
$callbacks[] = array($method->name, Events::postRemove);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PostLoad) {
|
||||
$callbacks[] = array($method->name, Events::postLoad);
|
||||
}
|
||||
|
||||
if ($annot instanceof \Doctrine\ORM\Mapping\PreFlush) {
|
||||
$callbacks[] = array($method->name, Events::preFlush);
|
||||
}
|
||||
}
|
||||
|
||||
return $callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given JoinColumn as array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -64,3 +64,4 @@ require_once __DIR__.'/../AssociationOverride.php';
|
||||
require_once __DIR__.'/../AssociationOverrides.php';
|
||||
require_once __DIR__.'/../AttributeOverride.php';
|
||||
require_once __DIR__.'/../AttributeOverrides.php';
|
||||
require_once __DIR__.'/../EntityListeners.php';
|
@ -19,10 +19,11 @@
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use SimpleXMLElement,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
|
||||
Doctrine\Common\Persistence\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
use SimpleXMLElement;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
|
||||
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
/**
|
||||
* XmlDriver is a metadata driver that enables mapping through XML files.
|
||||
@ -556,6 +557,26 @@ class XmlDriver extends FileDriver
|
||||
$metadata->addLifecycleCallback((string)$lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string)$lifecycleCallback['type']));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate entity listener
|
||||
if (isset($xmlRoot->{'entity-listeners'})) {
|
||||
foreach ($xmlRoot->{'entity-listeners'}->{'entity-listener'} as $listenerElement) {
|
||||
$className = (string) $listenerElement['class'];
|
||||
// Evaluate the listener using naming convention.
|
||||
if($listenerElement->count() === 0) {
|
||||
EntityListenerBuilder::bindEntityListener($metadata, $className);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($listenerElement as $callbackElement) {
|
||||
$eventName = (string) $callbackElement['type'];
|
||||
$methodName = (string) $callbackElement['method'];
|
||||
|
||||
$metadata->addEntityListener($eventName, $className, $methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
@ -572,6 +573,24 @@ class YamlDriver extends FileDriver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate entityListeners
|
||||
if (isset($element['entityListeners'])) {
|
||||
foreach ($element['entityListeners'] as $className => $entityListener) {
|
||||
// Evaluate the listener using naming convention.
|
||||
if (empty($entityListener)) {
|
||||
EntityListenerBuilder::bindEntityListener($metadata, $className);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($entityListener as $eventName => $callbackElement){
|
||||
foreach ($callbackElement as $methodName){
|
||||
$metadata->addEntityListener($eventName, $className, $methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
55
lib/Doctrine/ORM/Mapping/EntityListenerResolver.php
Normal file
55
lib/Doctrine/ORM/Mapping/EntityListenerResolver.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* A resolver is used to instantiate an entity listener.
|
||||
*
|
||||
* @since 2.4
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
interface EntityListenerResolver
|
||||
{
|
||||
/**
|
||||
* Clear all instances from the set, or a specific class when given.
|
||||
*
|
||||
* @param string $className The fully-qualified class name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function clear($className = null);
|
||||
|
||||
/**
|
||||
* Returns a entity listener instance for the given class name.
|
||||
*
|
||||
* @param string $className The fully-qualified class name
|
||||
*
|
||||
* @return object An entity listener
|
||||
*/
|
||||
function resolve($className);
|
||||
|
||||
/**
|
||||
* Register a entity listener instance.
|
||||
*
|
||||
* @return object An entity listener
|
||||
*/
|
||||
function register($object);
|
||||
}
|
41
lib/Doctrine/ORM/Mapping/EntityListeners.php
Normal file
41
lib/Doctrine/ORM/Mapping/EntityListeners.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* The EntityListeners annotation specifies the callback listener classes to be used for an entity or mapped superclass.
|
||||
* The EntityListeners annotation may be applied to an entity class or mapped superclass.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.4
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class EntityListeners implements Annotation
|
||||
{
|
||||
/**
|
||||
* Specifies the names of the entity listeners.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
public $value = array();
|
||||
}
|
@ -684,6 +684,29 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
*
|
||||
* @return \Doctrine\ORM\Mapping\MappingException
|
||||
*/
|
||||
public static function entityListenerClassNotFound($listenerName, $className)
|
||||
{
|
||||
return new self(sprintf('Entity Listener "%s" declared on "%s" not found.', $listenerName, $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $listenerName
|
||||
* @param string $methodName
|
||||
* @param string $className
|
||||
*
|
||||
* @return \Doctrine\ORM\Mapping\MappingException
|
||||
*/
|
||||
public static function entityListenerMethodNotFound($listenerName, $methodName, $className)
|
||||
{
|
||||
return new self(sprintf('Entity Listener "%s" declared on "%s" has no method "%s".', $listenerName, $className, $methodName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $annotation
|
||||
|
@ -22,15 +22,22 @@ namespace Doctrine\ORM;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\NotifyPropertyChanged;
|
||||
use Doctrine\Common\PropertyChangedListener;
|
||||
use Doctrine\Common\Persistence\ObjectManagerAware;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Proxy\Proxy;
|
||||
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
use Doctrine\ORM\Event\PreUpdateEventArgs;
|
||||
use Doctrine\ORM\Event\PreFlushEventArgs;
|
||||
use Doctrine\ORM\Event\OnFlushEventArgs;
|
||||
use Doctrine\ORM\Event\PostFlushEventArgs;
|
||||
use Doctrine\ORM\Event\ListenersInvoker;
|
||||
|
||||
/**
|
||||
* The UnitOfWork is responsible for tracking changes to objects during an
|
||||
* "object-level" transaction and for writing out changes to the database
|
||||
@ -212,6 +219,13 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private $evm;
|
||||
|
||||
/**
|
||||
* The ListenersInvoker used for dispatching events.
|
||||
*
|
||||
* @var \Doctrine\ORM\Event\ListenersInvoker
|
||||
*/
|
||||
private $listenersInvoker;
|
||||
|
||||
/**
|
||||
* Orphaned entities that are scheduled for removal.
|
||||
*
|
||||
@ -240,8 +254,9 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->evm = $em->getEventManager();
|
||||
$this->em = $em;
|
||||
$this->evm = $em->getEventManager();
|
||||
$this->listenersInvoker = new ListenersInvoker($em);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,7 +282,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
{
|
||||
// Raise preFlush
|
||||
if ($this->evm->hasListeners(Events::preFlush)) {
|
||||
$this->evm->dispatchEvent(Events::preFlush, new Event\PreFlushEventArgs($this->em));
|
||||
$this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em));
|
||||
}
|
||||
|
||||
// Compute changes done since last commit.
|
||||
@ -506,9 +521,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
}
|
||||
|
||||
// Fire PreFlush lifecycle callbacks
|
||||
if (isset($class->lifecycleCallbacks[Events::preFlush])) {
|
||||
$class->invokeLifecycleCallbacks(Events::preFlush, $entity);
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush);
|
||||
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
|
||||
$actualData = array();
|
||||
@ -798,21 +814,18 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMetadata $class
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param object $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function persistNew($class, $entity)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
$oid = spl_object_hash($entity);
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::prePersist);
|
||||
|
||||
if (isset($class->lifecycleCallbacks[Events::prePersist])) {
|
||||
$class->invokeLifecycleCallbacks(Events::prePersist, $entity);
|
||||
}
|
||||
|
||||
if ($this->evm->hasListeners(Events::prePersist)) {
|
||||
$this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entity, $this->em));
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::prePersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
|
||||
$idGen = $class->idGenerator;
|
||||
@ -908,12 +921,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function executeInserts($class)
|
||||
{
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
$entities = array();
|
||||
|
||||
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postPersist]);
|
||||
$hasListeners = $this->evm->hasListeners(Events::postPersist);
|
||||
$entities = array();
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist);
|
||||
|
||||
foreach ($this->entityInsertions as $oid => $entity) {
|
||||
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
|
||||
@ -924,7 +935,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
unset($this->entityInsertions[$oid]);
|
||||
|
||||
if ($hasLifecycleCallbacks || $hasListeners) {
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$entities[] = $entity;
|
||||
}
|
||||
}
|
||||
@ -948,13 +959,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
foreach ($entities as $entity) {
|
||||
if ($hasLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::postPersist, $entity);
|
||||
}
|
||||
|
||||
if ($hasListeners) {
|
||||
$this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($entity, $this->em));
|
||||
}
|
||||
$this->listenersInvoker->invoke($class, Events::postPersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,45 +972,29 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function executeUpdates($class)
|
||||
{
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
|
||||
$hasPreUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::preUpdate]);
|
||||
$hasPreUpdateListeners = $this->evm->hasListeners(Events::preUpdate);
|
||||
|
||||
$hasPostUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postUpdate]);
|
||||
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
$preUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preUpdate);
|
||||
$postUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postUpdate);
|
||||
|
||||
foreach ($this->entityUpdates as $oid => $entity) {
|
||||
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($hasPreUpdateLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
|
||||
|
||||
if ($preUpdateInvoke != ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::preUpdate, $entity, new PreUpdateEventArgs($entity, $this->em, $this->entityChangeSets[$oid]), $preUpdateInvoke);
|
||||
$this->recomputeSingleEntityChangeSet($class, $entity);
|
||||
}
|
||||
|
||||
if ($hasPreUpdateListeners) {
|
||||
$this->evm->dispatchEvent(
|
||||
Events::preUpdate,
|
||||
new Event\PreUpdateEventArgs($entity, $this->em, $this->entityChangeSets[$oid])
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($this->entityChangeSets[$oid])) {
|
||||
if ( ! empty($this->entityChangeSets[$oid])) {
|
||||
$persister->update($entity);
|
||||
}
|
||||
|
||||
unset($this->entityUpdates[$oid]);
|
||||
|
||||
if ($hasPostUpdateLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::postUpdate, $entity);
|
||||
}
|
||||
|
||||
if ($hasPostUpdateListeners) {
|
||||
$this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($entity, $this->em));
|
||||
if ($postUpdateInvoke != ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::postUpdate, $entity, new LifecycleEventArgs($entity, $this->em), $postUpdateInvoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1019,11 +1008,9 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function executeDeletions($class)
|
||||
{
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
|
||||
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postRemove]);
|
||||
$hasListeners = $this->evm->hasListeners(Events::postRemove);
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postRemove);
|
||||
|
||||
foreach ($this->entityDeletions as $oid => $entity) {
|
||||
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
|
||||
@ -1046,12 +1033,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class->reflFields[$class->identifier[0]]->setValue($entity, null);
|
||||
}
|
||||
|
||||
if ($hasLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::postRemove, $entity);
|
||||
}
|
||||
|
||||
if ($hasListeners) {
|
||||
$this->evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($entity, $this->em));
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::postRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1691,12 +1674,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
break;
|
||||
|
||||
case self::STATE_MANAGED:
|
||||
if (isset($class->lifecycleCallbacks[Events::preRemove])) {
|
||||
$class->invokeLifecycleCallbacks(Events::preRemove, $entity);
|
||||
}
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preRemove);
|
||||
|
||||
if ($this->evm->hasListeners(Events::preRemove)) {
|
||||
$this->evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($entity, $this->em));
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::preRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
|
||||
$this->scheduleForDelete($entity);
|
||||
@ -2695,13 +2676,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
if ($overrideLocalValues) {
|
||||
if (isset($class->lifecycleCallbacks[Events::postLoad])) {
|
||||
$class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
||||
}
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad);
|
||||
|
||||
|
||||
if ($this->evm->hasListeners(Events::postLoad)) {
|
||||
$this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em));
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::postLoad, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3177,14 +3155,14 @@ class UnitOfWork implements PropertyChangedListener
|
||||
private function dispatchOnFlushEvent()
|
||||
{
|
||||
if ($this->evm->hasListeners(Events::onFlush)) {
|
||||
$this->evm->dispatchEvent(Events::onFlush, new Event\OnFlushEventArgs($this->em));
|
||||
$this->evm->dispatchEvent(Events::onFlush, new OnFlushEventArgs($this->em));
|
||||
}
|
||||
}
|
||||
|
||||
private function dispatchPostFlushEvent()
|
||||
{
|
||||
if ($this->evm->hasListeners(Events::postFlush)) {
|
||||
$this->evm->dispatchEvent(Events::postFlush, new Event\PostFlushEventArgs($this->em));
|
||||
$this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ namespace Doctrine\Tests\Models\CMS;
|
||||
* )
|
||||
* })
|
||||
*
|
||||
* @EntityListeners({"CmsAddressListener"})
|
||||
*/
|
||||
class CmsAddress
|
||||
{
|
||||
@ -127,6 +128,28 @@ class CmsAddress
|
||||
'name' => 'company_person',
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'id' => true,
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'fieldName' => 'zip',
|
||||
'length' => 50,
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'fieldName' => 'city',
|
||||
'length' => 50,
|
||||
));
|
||||
|
||||
$metadata->mapOneToOne(array(
|
||||
'fieldName' => 'user',
|
||||
'targetEntity' => 'CmsUser',
|
||||
'joinColumns' => array(array('referencedColumnName' => 'id'))
|
||||
));
|
||||
|
||||
$metadata->addNamedNativeQuery(array (
|
||||
'name' => 'find-all',
|
||||
'query' => 'SELECT id, country, city FROM cms_addresses',
|
||||
@ -145,7 +168,6 @@ class CmsAddress
|
||||
'resultSetMapping' => 'mapping-count',
|
||||
));
|
||||
|
||||
|
||||
$metadata->addSqlResultSetMapping(array (
|
||||
'name' => 'mapping-find-all',
|
||||
'columns' => array(),
|
||||
@ -187,5 +209,17 @@ class CmsAddress
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CmsAddressListener', 'postPersist');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CmsAddressListener', 'prePersist');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CmsAddressListener', 'postUpdate');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CmsAddressListener', 'preUpdate');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CmsAddressListener', 'postRemove');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CmsAddressListener', 'preRemove');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CmsAddressListener', 'preFlush');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CmsAddressListener', 'postLoad');
|
||||
}
|
||||
}
|
58
tests/Doctrine/Tests/Models/CMS/CmsAddressListener.php
Normal file
58
tests/Doctrine/Tests/Models/CMS/CmsAddressListener.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\CMS;
|
||||
|
||||
class CmsAddressListener
|
||||
{
|
||||
public $calls;
|
||||
|
||||
public function prePersist()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function postPersist()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function preUpdate()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function postUpdate()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function preRemove()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function postRemove()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function postLoad()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
public function preFlush()
|
||||
{
|
||||
$this->calls[__FUNCTION__][] = func_get_args();
|
||||
}
|
||||
|
||||
protected function postPersistHandler()
|
||||
{
|
||||
throw new \BadMethodCallException("This is not a valid callback");
|
||||
}
|
||||
|
||||
protected function prePersistHandler()
|
||||
{
|
||||
throw new \BadMethodCallException("This is not a valid callback");
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Doctrine\Tests\Models\Company;
|
||||
* @Table(name="company_contracts")
|
||||
* @InheritanceType("SINGLE_TABLE")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @EntityListeners({"CompanyContractListener"})
|
||||
* @DiscriminatorMap({
|
||||
* "fix" = "CompanyFixContract",
|
||||
* "flexible" = "CompanyFlexContract",
|
||||
@ -128,4 +129,44 @@ abstract class CompanyContract
|
||||
}
|
||||
|
||||
abstract public function calculatePrice();
|
||||
|
||||
static public function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
$metadata->setInheritanceType(\Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_JOINED);
|
||||
$metadata->setTableName( 'company_contracts');
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => 'discr',
|
||||
'type' => 'string',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'id' => true,
|
||||
'name' => 'id',
|
||||
'fieldName' => 'id',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'boolean',
|
||||
'name' => 'completed',
|
||||
'fieldName' => 'completed',
|
||||
));
|
||||
|
||||
$metadata->setDiscriminatorMap(array(
|
||||
"fix" => "CompanyFixContract",
|
||||
"flexible" => "CompanyFlexContract",
|
||||
"flexultra" => "CompanyFlexUltraContract"
|
||||
));
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CompanyContractListener', 'postPersistHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyContractListener', 'prePersistHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CompanyContractListener', 'postUpdateHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CompanyContractListener', 'preUpdateHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CompanyContractListener', 'postRemoveHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CompanyContractListener', 'preRemoveHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CompanyContractListener', 'preFlushHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CompanyContractListener', 'postLoadHandler');
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Company;
|
||||
|
||||
class CompanyContractListener
|
||||
{
|
||||
public $postPersistCalls;
|
||||
public $prePersistCalls;
|
||||
|
||||
public $postUpdateCalls;
|
||||
public $preUpdateCalls;
|
||||
|
||||
public $postRemoveCalls;
|
||||
public $preRemoveCalls;
|
||||
|
||||
public $preFlushCalls;
|
||||
|
||||
public $postLoadCalls;
|
||||
|
||||
/**
|
||||
* @PostPersist
|
||||
*/
|
||||
public function postPersistHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->postPersistCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PrePersist
|
||||
*/
|
||||
public function prePersistHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->prePersistCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostUpdate
|
||||
*/
|
||||
public function postUpdateHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->postUpdateCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreUpdate
|
||||
*/
|
||||
public function preUpdateHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->preUpdateCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostRemove
|
||||
*/
|
||||
public function postRemoveHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->postRemoveCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreRemove
|
||||
*/
|
||||
public function preRemoveHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->preRemoveCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreFlush
|
||||
*/
|
||||
public function preFlushHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->preFlushCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostLoad
|
||||
*/
|
||||
public function postLoadHandler(CompanyContract $contract)
|
||||
{
|
||||
$this->postLoadCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
}
|
@ -27,4 +27,13 @@ class CompanyFixContract extends CompanyContract
|
||||
{
|
||||
$this->fixPrice = $fixPrice;
|
||||
}
|
||||
|
||||
static public function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'fixPrice',
|
||||
'fieldName' => 'fixPrice',
|
||||
));
|
||||
}
|
||||
}
|
@ -107,4 +107,19 @@ class CompanyFlexContract extends CompanyContract
|
||||
{
|
||||
$this->managers->removeElement($manager);
|
||||
}
|
||||
|
||||
static public function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'hoursWorked',
|
||||
'fieldName' => 'hoursWorked',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'pricePerHour',
|
||||
'fieldName' => 'pricePerHour',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace Doctrine\Tests\Models\Company;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @EntityListeners({"CompanyContractListener","CompanyFlexUltraContractListener"})
|
||||
*/
|
||||
class CompanyFlexUltraContract extends CompanyFlexContract
|
||||
{
|
||||
@ -27,4 +28,27 @@ class CompanyFlexUltraContract extends CompanyFlexContract
|
||||
{
|
||||
$this->maxPrice = $maxPrice;
|
||||
}
|
||||
|
||||
static public function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'maxPrice',
|
||||
'fieldName' => 'maxPrice',
|
||||
));
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CompanyContractListener', 'postPersistHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyContractListener', 'prePersistHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CompanyContractListener', 'postUpdateHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CompanyContractListener', 'preUpdateHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CompanyContractListener', 'postRemoveHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CompanyContractListener', 'preRemoveHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CompanyContractListener', 'preFlushHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CompanyContractListener', 'postLoadHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyFlexUltraContractListener', 'prePersistHandler1');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyFlexUltraContractListener', 'prePersistHandler2');
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Company;
|
||||
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
class CompanyFlexUltraContractListener
|
||||
{
|
||||
public $prePersistCalls;
|
||||
|
||||
/**
|
||||
* @PrePersist
|
||||
*/
|
||||
public function prePersistHandler1(CompanyContract $contract, LifecycleEventArgs $args)
|
||||
{
|
||||
$this->prePersistCalls[] = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PrePersist
|
||||
*/
|
||||
public function prePersistHandler2(CompanyContract $contract, LifecycleEventArgs $args)
|
||||
{
|
||||
$this->prePersistCalls[] = func_get_args();
|
||||
}
|
||||
}
|
@ -260,6 +260,18 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
|
||||
$this->configuration->setQuoteStrategy($quoteStrategy);
|
||||
$this->assertSame($quoteStrategy, $this->configuration->getQuoteStrategy());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
public function testSetGetEntityListenerResolver()
|
||||
{
|
||||
$this->assertInstanceOf('Doctrine\ORM\Mapping\EntityListenerResolver', $this->configuration->getEntityListenerResolver());
|
||||
$this->assertInstanceOf('Doctrine\ORM\Mapping\DefaultEntityListenerResolver', $this->configuration->getEntityListenerResolver());
|
||||
$resolver = $this->getMock('Doctrine\ORM\Mapping\EntityListenerResolver');
|
||||
$this->configuration->setEntityListenerResolver($resolver);
|
||||
$this->assertSame($resolver, $this->configuration->getEntityListenerResolver());
|
||||
}
|
||||
}
|
||||
|
||||
class ConfigurationTestAnnotationReaderChecker
|
||||
|
247
tests/Doctrine/Tests/ORM/Functional/EntityListenersTest.php
Normal file
247
tests/Doctrine/Tests/ORM/Functional/EntityListenersTest.php
Normal file
@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\Tests\Models\Company\CompanyFixContract;
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
class EntityListenersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Doctrine\Tests\Models\Company\CompanyContractListener
|
||||
*/
|
||||
private $listener;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('company');
|
||||
parent::setUp();
|
||||
|
||||
$this->listener = $this->_em->getConfiguration()
|
||||
->getEntityListenerResolver()
|
||||
->resolve('Doctrine\Tests\Models\Company\CompanyContractListener');
|
||||
}
|
||||
|
||||
public function testPreFlushListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->listener->preFlushCalls = array();
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->preFlushCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->preFlushCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->preFlushCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\PreFlushEventArgs',
|
||||
$this->listener->preFlushCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPostLoadListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->listener->postLoadCalls = array();
|
||||
|
||||
$dql = "SELECT f FROM Doctrine\Tests\Models\Company\CompanyFixContract f WHERE f.id = ?1";
|
||||
$fix = $this->_em->createQuery($dql)->setParameter(1, $fix->getId())->getSingleResult();
|
||||
|
||||
$this->assertCount(1,$this->listener->postLoadCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->postLoadCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->postLoadCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->postLoadCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPrePersistListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->listener->prePersistCalls = array();
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->prePersistCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->prePersistCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->prePersistCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->prePersistCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPostPersistListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->listener->postPersistCalls = array();
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->postPersistCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->postPersistCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->postPersistCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->postPersistCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPreUpdateListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(1000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->listener->preUpdateCalls = array();
|
||||
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->preUpdateCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->preUpdateCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->preUpdateCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\PreUpdateEventArgs',
|
||||
$this->listener->preUpdateCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPostUpdateListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(1000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->listener->postUpdateCalls = array();
|
||||
|
||||
$fix->setFixPrice(2000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->postUpdateCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->postUpdateCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->postUpdateCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->postUpdateCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPreRemoveListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(1000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->listener->preRemoveCalls = array();
|
||||
|
||||
$this->_em->remove($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->preRemoveCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->preRemoveCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->preRemoveCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->preRemoveCalls[0][1]
|
||||
);
|
||||
}
|
||||
|
||||
public function testPostRemoveListeners()
|
||||
{
|
||||
$fix = new CompanyFixContract();
|
||||
$fix->setFixPrice(1000);
|
||||
|
||||
$this->_em->persist($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->listener->postRemoveCalls = array();
|
||||
|
||||
$this->_em->remove($fix);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertCount(1,$this->listener->postRemoveCalls);
|
||||
|
||||
$this->assertSame($fix, $this->listener->postRemoveCalls[0][0]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\Tests\Models\Company\CompanyFixContract',
|
||||
$this->listener->postRemoveCalls[0][0]
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$this->listener->postRemoveCalls[0][1]
|
||||
);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ class LifecycleCallbackTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
parent::setUp();
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\LifecycleCallbackEventArgEntity'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\LifecycleCallbackTestUser'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\LifecycleCallbackCascader'),
|
||||
@ -182,6 +183,77 @@ class LifecycleCallbackTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->assertEquals('Bob', $bob->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
public function testLifecycleCallbackEventArgs()
|
||||
{
|
||||
$e = new LifecycleCallbackEventArgEntity;
|
||||
|
||||
$e->value = 'foo';
|
||||
$this->_em->persist($e);
|
||||
$this->_em->flush();
|
||||
|
||||
$e->value = 'var';
|
||||
$this->_em->persist($e);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->refresh($e);
|
||||
|
||||
$this->_em->remove($e);
|
||||
$this->_em->flush();
|
||||
|
||||
|
||||
$this->assertArrayHasKey('preFlushHandler', $e->calls);
|
||||
$this->assertArrayHasKey('postLoadHandler', $e->calls);
|
||||
$this->assertArrayHasKey('prePersistHandler', $e->calls);
|
||||
$this->assertArrayHasKey('postPersistHandler', $e->calls);
|
||||
$this->assertArrayHasKey('preUpdateHandler', $e->calls);
|
||||
$this->assertArrayHasKey('postUpdateHandler', $e->calls);
|
||||
$this->assertArrayHasKey('preRemoveHandler', $e->calls);
|
||||
$this->assertArrayHasKey('postRemoveHandler', $e->calls);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\PreFlushEventArgs',
|
||||
$e->calls['preFlushHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['postLoadHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['prePersistHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['postPersistHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\PreUpdateEventArgs',
|
||||
$e->calls['preUpdateHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['postUpdateHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['preRemoveHandler']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'Doctrine\ORM\Event\LifecycleEventArgs',
|
||||
$e->calls['postRemoveHandler']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity @HasLifecycleCallbacks */
|
||||
@ -309,3 +381,79 @@ class LifecycleListenerPreUpdate
|
||||
$eventArgs->setNewValue('name', 'Bob');
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity @HasLifecycleCallbacks */
|
||||
class LifecycleCallbackEventArgEntity
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
|
||||
/** @Column() */
|
||||
public $value;
|
||||
|
||||
public $calls = array();
|
||||
|
||||
/**
|
||||
* @PostPersist
|
||||
*/
|
||||
public function postPersistHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PrePersist
|
||||
*/
|
||||
public function prePersistHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostUpdate
|
||||
*/
|
||||
public function postUpdateHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreUpdate
|
||||
*/
|
||||
public function preUpdateHandler(\Doctrine\ORM\Event\PreUpdateEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostRemove
|
||||
*/
|
||||
public function postRemoveHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreRemove
|
||||
*/
|
||||
public function preRemoveHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreFlush
|
||||
*/
|
||||
public function preFlushHandler(\Doctrine\ORM\Event\PreFlushEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostLoad
|
||||
*/
|
||||
public function postLoadHandler(\Doctrine\ORM\Event\LifecycleEventArgs $event)
|
||||
{
|
||||
$this->calls[__FUNCTION__] = $event;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
/**
|
||||
* @group DDC-1707
|
||||
@ -25,9 +25,11 @@ class DDC1707Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testPostLoadOnChild()
|
||||
{
|
||||
$class = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1707Child');
|
||||
$class = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1707Child');
|
||||
$entity = new DDC1707Child();
|
||||
$class->invokeLifecycleCallbacks(\Doctrine\ORM\Events::postLoad, $entity);
|
||||
$event = new LifecycleEventArgs($entity, $this->_em);
|
||||
|
||||
$class->invokeLifecycleCallbacks(\Doctrine\ORM\Events::postLoad, $entity, $event);
|
||||
|
||||
$this->assertTrue($entity->postLoad);
|
||||
}
|
||||
|
@ -2,10 +2,13 @@
|
||||
|
||||
namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\Driver\XmlDriver,
|
||||
Doctrine\ORM\Mapping\Driver\YamlDriver;
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
use Doctrine\Tests\Models\Company\CompanyFixContract;
|
||||
use Doctrine\Tests\Models\Company\CompanyFlexContract;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@ -748,6 +751,126 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertTrue($guestMetadata->fieldMappings['name']['unique']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
public function testEntityListeners()
|
||||
{
|
||||
$em = $this->_getTestEntityManager();
|
||||
$factory = $this->createClassMetadataFactory($em);
|
||||
$superClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyContract');
|
||||
$flexClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFixContract');
|
||||
$fixClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFlexContract');
|
||||
$ultraClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFlexUltraContract');
|
||||
|
||||
$this->assertArrayHasKey(Events::prePersist, $superClass->entityListeners);
|
||||
$this->assertArrayHasKey(Events::postPersist, $superClass->entityListeners);
|
||||
|
||||
$this->assertCount(1, $superClass->entityListeners[Events::prePersist]);
|
||||
$this->assertCount(1, $superClass->entityListeners[Events::postPersist]);
|
||||
|
||||
$postPersist = $superClass->entityListeners[Events::postPersist][0];
|
||||
$prePersist = $superClass->entityListeners[Events::prePersist][0];
|
||||
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContractListener', $postPersist['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContractListener', $prePersist['class']);
|
||||
$this->assertEquals('postPersistHandler', $postPersist['method']);
|
||||
$this->assertEquals('prePersistHandler', $prePersist['method']);
|
||||
|
||||
//Inherited listeners
|
||||
$this->assertEquals($fixClass->entityListeners, $superClass->entityListeners);
|
||||
$this->assertEquals($flexClass->entityListeners, $superClass->entityListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
public function testEntityListenersOverride()
|
||||
{
|
||||
$em = $this->_getTestEntityManager();
|
||||
$factory = $this->createClassMetadataFactory($em);
|
||||
$ultraClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFlexUltraContract');
|
||||
|
||||
//overrited listeners
|
||||
$this->assertArrayHasKey(Events::postPersist, $ultraClass->entityListeners);
|
||||
$this->assertArrayHasKey(Events::prePersist, $ultraClass->entityListeners);
|
||||
|
||||
$this->assertCount(1, $ultraClass->entityListeners[Events::postPersist]);
|
||||
$this->assertCount(3, $ultraClass->entityListeners[Events::prePersist]);
|
||||
|
||||
$postPersist = $ultraClass->entityListeners[Events::postPersist][0];
|
||||
$prePersist = $ultraClass->entityListeners[Events::prePersist][0];
|
||||
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContractListener', $postPersist['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyContractListener', $prePersist['class']);
|
||||
$this->assertEquals('postPersistHandler', $postPersist['method']);
|
||||
$this->assertEquals('prePersistHandler', $prePersist['method']);
|
||||
|
||||
$prePersist = $ultraClass->entityListeners[Events::prePersist][1];
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener', $prePersist['class']);
|
||||
$this->assertEquals('prePersistHandler1', $prePersist['method']);
|
||||
|
||||
$prePersist = $ultraClass->entityListeners[Events::prePersist][2];
|
||||
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener', $prePersist['class']);
|
||||
$this->assertEquals('prePersistHandler2', $prePersist['method']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
public function testEntityListenersNamingConvention()
|
||||
{
|
||||
$em = $this->_getTestEntityManager();
|
||||
$factory = $this->createClassMetadataFactory($em);
|
||||
$metadata = $factory->getMetadataFor('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
|
||||
$this->assertArrayHasKey(Events::postPersist, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::prePersist, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::postUpdate, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::preUpdate, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::postRemove, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::preRemove, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::postLoad, $metadata->entityListeners);
|
||||
$this->assertArrayHasKey(Events::preFlush, $metadata->entityListeners);
|
||||
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::postPersist]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::prePersist]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::postUpdate]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::preUpdate]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::postRemove]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::preRemove]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::postLoad]);
|
||||
$this->assertCount(1, $metadata->entityListeners[Events::preFlush]);
|
||||
|
||||
$postPersist = $metadata->entityListeners[Events::postPersist][0];
|
||||
$prePersist = $metadata->entityListeners[Events::prePersist][0];
|
||||
$postUpdate = $metadata->entityListeners[Events::postUpdate][0];
|
||||
$preUpdate = $metadata->entityListeners[Events::preUpdate][0];
|
||||
$postRemove = $metadata->entityListeners[Events::postRemove][0];
|
||||
$preRemove = $metadata->entityListeners[Events::preRemove][0];
|
||||
$postLoad = $metadata->entityListeners[Events::postLoad][0];
|
||||
$preFlush = $metadata->entityListeners[Events::preFlush][0];
|
||||
|
||||
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $postPersist['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $prePersist['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $postUpdate['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $preUpdate['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $postRemove['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $preRemove['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $postLoad['class']);
|
||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddressListener', $preFlush['class']);
|
||||
|
||||
$this->assertEquals(Events::postPersist, $postPersist['method']);
|
||||
$this->assertEquals(Events::prePersist, $prePersist['method']);
|
||||
$this->assertEquals(Events::postUpdate, $postUpdate['method']);
|
||||
$this->assertEquals(Events::preUpdate, $preUpdate['method']);
|
||||
$this->assertEquals(Events::postRemove, $postRemove['method']);
|
||||
$this->assertEquals(Events::preRemove, $preRemove['method']);
|
||||
$this->assertEquals(Events::postLoad, $postLoad['method']);
|
||||
$this->assertEquals(Events::preFlush, $preFlush['method']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -997,6 +997,34 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$cm->setAttributeOverride('name', array('type'=>'date'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*
|
||||
* @expectedException Doctrine\ORM\Mapping\MappingException
|
||||
* @expectedExceptionMessage Entity Listener "\InvalidClassName" declared on "Doctrine\Tests\Models\CMS\CmsUser" not found.
|
||||
*/
|
||||
public function testInvalidEntityListenerClassException()
|
||||
{
|
||||
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
|
||||
|
||||
$cm->addEntityListener(Events::postLoad, '\InvalidClassName', 'postLoadHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*
|
||||
* @expectedException Doctrine\ORM\Mapping\MappingException
|
||||
* @expectedExceptionMessage Entity Listener "\Doctrine\Tests\Models\Company\CompanyContractListener" declared on "Doctrine\Tests\Models\CMS\CmsUser" has no method "invalidMethod".
|
||||
*/
|
||||
public function testInvalidEntityListenerMethodException()
|
||||
{
|
||||
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
|
||||
|
||||
$cm->addEntityListener(Events::postLoad, '\Doctrine\Tests\Models\Company\CompanyContractListener', 'invalidMethod');
|
||||
}
|
||||
}
|
||||
|
||||
class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
|
||||
|
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
|
||||
|
||||
/**
|
||||
* @group DDC-1955
|
||||
*/
|
||||
class EntityListenerResolverTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Doctrine\ORM\Mapping\DefaultEntityListenerResolver
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->resolver = new DefaultEntityListenerResolver();
|
||||
}
|
||||
|
||||
public function testResolve()
|
||||
{
|
||||
$className = '\Doctrine\Tests\Models\Company\CompanyContractListener';
|
||||
$object = $this->resolver->resolve($className);
|
||||
|
||||
$this->assertInstanceOf($className, $object);
|
||||
$this->assertSame($object, $this->resolver->resolve($className));
|
||||
}
|
||||
|
||||
public function testRegisterAndResolve()
|
||||
{
|
||||
$className = '\Doctrine\Tests\Models\Company\CompanyContractListener';
|
||||
$object = new $className();
|
||||
|
||||
$this->resolver->register($object);
|
||||
|
||||
$this->assertSame($object, $this->resolver->resolve($className));
|
||||
}
|
||||
|
||||
public function testClearOne()
|
||||
{
|
||||
$className1 = '\Doctrine\Tests\Models\Company\CompanyContractListener';
|
||||
$className2 = '\Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener';
|
||||
|
||||
$obj1 = $this->resolver->resolve($className1);
|
||||
$obj2 = $this->resolver->resolve($className2);
|
||||
|
||||
$this->assertInstanceOf($className1, $obj1);
|
||||
$this->assertInstanceOf($className2, $obj2);
|
||||
|
||||
$this->assertSame($obj1, $this->resolver->resolve($className1));
|
||||
$this->assertSame($obj2, $this->resolver->resolve($className2));
|
||||
|
||||
$this->resolver->clear($className1);
|
||||
|
||||
$this->assertInstanceOf($className1, $this->resolver->resolve($className1));
|
||||
$this->assertInstanceOf($className2, $this->resolver->resolve($className2));
|
||||
|
||||
$this->assertNotSame($obj1, $this->resolver->resolve($className1));
|
||||
$this->assertSame($obj2, $this->resolver->resolve($className2));
|
||||
}
|
||||
|
||||
public function testClearAll()
|
||||
{
|
||||
$className1 = '\Doctrine\Tests\Models\Company\CompanyContractListener';
|
||||
$className2 = '\Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener';
|
||||
|
||||
$obj1 = $this->resolver->resolve($className1);
|
||||
$obj2 = $this->resolver->resolve($className2);
|
||||
|
||||
$this->assertInstanceOf($className1, $obj1);
|
||||
$this->assertInstanceOf($className2, $obj2);
|
||||
|
||||
$this->assertSame($obj1, $this->resolver->resolve($className1));
|
||||
$this->assertSame($obj2, $this->resolver->resolve($className2));
|
||||
|
||||
$this->resolver->clear();
|
||||
|
||||
$this->assertInstanceOf($className1, $this->resolver->resolve($className1));
|
||||
$this->assertInstanceOf($className2, $this->resolver->resolve($className2));
|
||||
|
||||
$this->assertNotSame($obj1, $this->resolver->resolve($className1));
|
||||
$this->assertNotSame($obj2, $this->resolver->resolve($className2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedExceptionMessage An object was expected, but got "string".
|
||||
*/
|
||||
public function testRegisterStringException()
|
||||
{
|
||||
$this->resolver->register('CompanyContractListener');
|
||||
}
|
||||
}
|
@ -6,6 +6,27 @@ $metadata->setPrimaryTable(array(
|
||||
'name' => 'company_person',
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'id' => true,
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'fieldName' => 'zip',
|
||||
'length' => 50,
|
||||
));
|
||||
|
||||
$metadata->mapField(array (
|
||||
'fieldName' => 'city',
|
||||
'length' => 50,
|
||||
));
|
||||
|
||||
$metadata->mapOneToOne(array(
|
||||
'fieldName' => 'user',
|
||||
'targetEntity' => 'CmsUser',
|
||||
'joinColumns' => array(array('referencedColumnName' => 'id'))
|
||||
));
|
||||
|
||||
$metadata->addNamedNativeQuery(array (
|
||||
'name' => 'find-all',
|
||||
@ -66,4 +87,16 @@ $metadata->addSqlResultSetMapping(array (
|
||||
'name' => 'count',
|
||||
),
|
||||
)
|
||||
));
|
||||
));
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CmsAddressListener', 'postPersist');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CmsAddressListener', 'prePersist');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CmsAddressListener', 'postUpdate');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CmsAddressListener', 'preUpdate');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CmsAddressListener', 'postRemove');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CmsAddressListener', 'preRemove');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CmsAddressListener', 'preFlush');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CmsAddressListener', 'postLoad');
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
$metadata->setInheritanceType(\Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_JOINED);
|
||||
$metadata->setTableName( 'company_contracts');
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => 'discr',
|
||||
'type' => 'string',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'id' => true,
|
||||
'name' => 'id',
|
||||
'fieldName' => 'id',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'boolean',
|
||||
'name' => 'completed',
|
||||
'fieldName' => 'completed',
|
||||
));
|
||||
|
||||
$metadata->setDiscriminatorMap(array(
|
||||
"fix" => "CompanyFixContract",
|
||||
"flexible" => "CompanyFlexContract",
|
||||
"flexultra" => "CompanyFlexUltraContract"
|
||||
));
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CompanyContractListener', 'postPersistHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyContractListener', 'prePersistHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CompanyContractListener', 'postUpdateHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CompanyContractListener', 'preUpdateHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CompanyContractListener', 'postRemoveHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CompanyContractListener', 'preRemoveHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CompanyContractListener', 'preFlushHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CompanyContractListener', 'postLoadHandler');
|
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'fixPrice',
|
||||
'fieldName' => 'fixPrice',
|
||||
));
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'hoursWorked',
|
||||
'fieldName' => 'hoursWorked',
|
||||
));
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'pricePerHour',
|
||||
'fieldName' => 'pricePerHour',
|
||||
));
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
$metadata->mapField(array(
|
||||
'type' => 'integer',
|
||||
'name' => 'maxPrice',
|
||||
'fieldName' => 'maxPrice',
|
||||
));
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CompanyContractListener', 'postPersistHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyContractListener', 'prePersistHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postUpdate, 'CompanyContractListener', 'postUpdateHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preUpdate, 'CompanyContractListener', 'preUpdateHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postRemove, 'CompanyContractListener', 'postRemoveHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preRemove, 'CompanyContractListener', 'preRemoveHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::preFlush, 'CompanyContractListener', 'preFlushHandler');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::postLoad, 'CompanyContractListener', 'postLoadHandler');
|
||||
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyFlexUltraContractListener', 'prePersistHandler1');
|
||||
$metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyFlexUltraContractListener', 'prePersistHandler2');
|
@ -7,6 +7,10 @@
|
||||
|
||||
<entity name="Doctrine\Tests\Models\CMS\CmsAddress" table="cms_users">
|
||||
|
||||
<entity-listeners>
|
||||
<entity-listener class="CmsAddressListener"/>
|
||||
</entity-listeners>
|
||||
|
||||
<named-native-queries>
|
||||
<named-native-query name="find-all" result-set-mapping="mapping-find-all">
|
||||
<query>SELECT id, country, city FROM cms_addresses</query>
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Doctrine\Tests\Models\Company\CompanyContract" table="company_contracts" inheritance-type="SINGLE_TABLE">
|
||||
|
||||
<discriminator-map>
|
||||
<discriminator-mapping value="fix" class="CompanyFixContract" />
|
||||
<discriminator-mapping value="flexible" class="CompanyFlexContract" />
|
||||
<discriminator-mapping value="flexultra" class="CompanyFlexUltraContract" />
|
||||
</discriminator-map>
|
||||
|
||||
<entity-listeners>
|
||||
<entity-listener class="CompanyContractListener">
|
||||
<lifecycle-callback type="preFlush" method="preFlushHandler"/>
|
||||
<lifecycle-callback type="postLoad" method="postLoadHandler"/>
|
||||
|
||||
<lifecycle-callback type="postPersist" method="postPersistHandler"/>
|
||||
<lifecycle-callback type="prePersist" method="prePersistHandler"/>
|
||||
|
||||
<lifecycle-callback type="postUpdate" method="postUpdateHandler"/>
|
||||
<lifecycle-callback type="preUpdate" method="preUpdateHandler"/>
|
||||
|
||||
<lifecycle-callback type="postRemove" method="postRemoveHandler"/>
|
||||
<lifecycle-callback type="preRemove" method="preRemoveHandler"/>
|
||||
</entity-listener>
|
||||
</entity-listeners>
|
||||
|
||||
<id name="id" type="integer" column="id">
|
||||
<generator strategy="AUTO"/>
|
||||
</id>
|
||||
|
||||
<field name="completed" column="completed" type="boolean"/>
|
||||
|
||||
<!-- Other mappings -->
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Doctrine\Tests\Models\Company\CompanyFixContract">
|
||||
|
||||
|
||||
<field name="fixPrice" column="fixPrice" type="integer"/>
|
||||
|
||||
<!-- Other mappings -->
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Doctrine\Tests\Models\Company\CompanyFlexContract">
|
||||
|
||||
<field name="hoursWorked" column="hoursWorked" type="integer"/>
|
||||
<field name="pricePerHour" column="pricePerHour" type="integer"/>
|
||||
|
||||
<!-- Other mappings -->
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Doctrine\Tests\Models\Company\CompanyFlexUltraContract">
|
||||
|
||||
<entity-listeners>
|
||||
<entity-listener class="CompanyContractListener">
|
||||
<lifecycle-callback type="preFlush" method="preFlushHandler"/>
|
||||
<lifecycle-callback type="postLoad" method="postLoadHandler"/>
|
||||
|
||||
<lifecycle-callback type="postPersist" method="postPersistHandler"/>
|
||||
<lifecycle-callback type="prePersist" method="prePersistHandler"/>
|
||||
|
||||
<lifecycle-callback type="postUpdate" method="postUpdateHandler"/>
|
||||
<lifecycle-callback type="preUpdate" method="preUpdateHandler"/>
|
||||
|
||||
<lifecycle-callback type="postRemove" method="postRemoveHandler"/>
|
||||
<lifecycle-callback type="preRemove" method="preRemoveHandler"/>
|
||||
</entity-listener>
|
||||
|
||||
<entity-listener class="CompanyFlexUltraContractListener">
|
||||
<lifecycle-callback type="prePersist" method="prePersistHandler1"/>
|
||||
<lifecycle-callback type="prePersist" method="prePersistHandler2"/>
|
||||
</entity-listener>
|
||||
</entity-listeners>
|
||||
|
||||
<field name="maxPrice" column="maxPrice" type="integer"/>
|
||||
|
||||
<!-- Other mappings -->
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
@ -1,6 +1,8 @@
|
||||
Doctrine\Tests\Models\CMS\CmsAddress:
|
||||
type: entity
|
||||
table: cms_address
|
||||
entityListeners:
|
||||
CmsAddressListener:
|
||||
namedNativeQueries:
|
||||
find-all:
|
||||
resultSetMapping: mapping-find-all
|
||||
@ -55,7 +57,7 @@ Doctrine\Tests\Models\CMS\CmsAddress:
|
||||
type: string
|
||||
length: 50
|
||||
oneToOne:
|
||||
address:
|
||||
user:
|
||||
targetEntity: CmsUser
|
||||
inversedBy: address
|
||||
joinColumn:
|
||||
|
@ -0,0 +1,32 @@
|
||||
Doctrine\Tests\Models\Company\CompanyContract:
|
||||
type: entity
|
||||
table: company_contracts
|
||||
inheritanceType: SINGLE_TABLE
|
||||
discriminatorMap:
|
||||
fix: CompanyFixContract
|
||||
flexible: CompanyFlexContract
|
||||
flexultra: CompanyFlexUltraContract
|
||||
|
||||
entityListeners:
|
||||
CompanyContractListener:
|
||||
|
||||
preFlush: [preFlushHandler]
|
||||
postLoad: [postLoadHandler]
|
||||
|
||||
postPersist: [postPersistHandler]
|
||||
prePersist: [prePersistHandler]
|
||||
|
||||
postUpdate: [postUpdateHandler]
|
||||
preUpdate: [preUpdateHandler]
|
||||
|
||||
postRemove: [postRemoveHandler]
|
||||
preRemove: [preRemoveHandler]
|
||||
|
||||
id:
|
||||
id:
|
||||
type: integer
|
||||
generator:
|
||||
strategy: AUTO
|
||||
fields:
|
||||
completed:
|
||||
type: boolean
|
@ -0,0 +1,5 @@
|
||||
Doctrine\Tests\Models\Company\CompanyFixContract:
|
||||
type: entity
|
||||
fields:
|
||||
fixPrice:
|
||||
type: integer
|
@ -0,0 +1,7 @@
|
||||
Doctrine\Tests\Models\Company\CompanyFlexContract:
|
||||
type: entity
|
||||
fields:
|
||||
hoursWorked:
|
||||
type: integer
|
||||
pricePerHour:
|
||||
type: integer
|
@ -0,0 +1,25 @@
|
||||
Doctrine\Tests\Models\Company\CompanyFlexUltraContract:
|
||||
type: entity
|
||||
|
||||
entityListeners:
|
||||
CompanyContractListener:
|
||||
|
||||
preFlush: [preFlushHandler]
|
||||
postLoad: [postLoadHandler]
|
||||
|
||||
postPersist: [postPersistHandler]
|
||||
prePersist: [prePersistHandler]
|
||||
|
||||
postUpdate: [postUpdateHandler]
|
||||
preUpdate: [preUpdateHandler]
|
||||
|
||||
postRemove: [postRemoveHandler]
|
||||
preRemove: [preRemoveHandler]
|
||||
|
||||
CompanyFlexUltraContractListener:
|
||||
|
||||
prePersist: [prePersistHandler1, prePersistHandler2]
|
||||
|
||||
fields:
|
||||
maxPrice:
|
||||
type: integer
|
Loading…
x
Reference in New Issue
Block a user