Event Management
Cloudrexx provides an event system which allows the execution of code in the event of predefined state changes. Every component is permitted to register any number of events to which any component is permitted to listen to and run code on.
Note
This article covers service side events (PHP). For client-side events seee JavaScript Framework Events.
Introduction
The event system is managed by a single instance of \Cx\Core\Event\Controller\EventManager
(one per instance of \Cx\Core\Core\Controller\Cx
) and provides the following functionality:
- Interface to register events
- Interface to register listeners on (previously) registered events
- Execution of predefined events on model state changes
- Interface for triggering (previously) registered events
List of Events
Passive Events
Listen to those events to inject custom code.
Component | Event | Event Data | Notes | Known Triggers |
---|---|---|---|---|
Search | SearchFindContent |
[$search] |
$search is an instance of \Cx\Core_Modules\Search\Controller\Search |
Implement Full-Text search |
MediaBrowser | MediaBrowser.Plugin:initialize |
- | - | Add view to MediaBrowser |
MailTemplate | MailTemplate.Mail:addAddress |
[ |
$mail is the instance of \Cx\Core\MailTemplate\Model\Entity\Mail on which the recipient is being added |
Catch recipient before email is dispatched. |
NetManager | NetManager:getSenderDomains |
[ |
If $usages is set to true , then the event listener must return usages according to the format specific to the sender domain validation. |
Collect used email sender domains. |
DataSource | preDistantEntityLoad |
[ |
- | Allows to interfere the loading process of associated entities when fetching over the RESTful API. |
MediaSource | mediasource.load |
[$mediaSourceManager] |
$mediaSourceManager is the instance of \Cx\Core\MediaSource\Model\Entity\MediaSourceManager that triggered the event |
Add a MediaSource |
Html | Html.ViewGenerator:initialize |
['options' => &$options] |
$options are the ViewGenerator options on initialization |
Allows for customizing of Autogenerated Views. |
View | View.Sigma:loadContent Deprecated |
[ |
$sigma is the instance of \Cx\Core\Html\Sigma that triggered the event. |
Allows to modify the content of a Template Block before being processed. |
View | View.Sigma:setVariable Deprecated |
[ |
$sigma is the instance of \Cx\Core\Html\Sigma that triggered the event. |
Allows to modify the value of a Template Placeholder on assignement. |
View | View.Sigma:loadFile Deprecated |
['filepath' => &$filepath] |
$filepath is the path to the template file to be loaded. |
Allows to modify the path to a Template File before being loaded. |
Core | preComponent |
[ |
<hook> will be one of the available Component Hooks. |
Use to inject code before the executing of other components' hooks. |
Core | postComponent |
[ |
<hook> will be one of the available Component Hooks. |
Use to inject code after the executing of other components' hooks. |
News | News::rssFeedWritten |
[ |
The event is triggered for each locale separately. <newsList> will be a list of news entries. These are simple lists of properties. |
Use to push a news feed to a third-party. |
Cache | Cache.Cachefile:outdateIndex |
[ |
The event is triggered for each expired entry when fetching data from the Data cache. <cacheFile> is an instance of Cx\Core_Modules\Listing\Model\Entity\DataSet holding the whole Data cache the expired entry belongs to. <index> is a string representation of the identifier of the expired entry. |
Use to extend expired Data cache entries by returning a new DateTime object (that points to a future date) to prevent removal of the expired entry. Returned structure must be as folows: [ |
Active Events
Trigger the following events to perform certain operations.
Component | Event | Argument Definition | Purpose |
---|---|---|---|
SysLog | SysLog/Add |
[ |
Use to add a System Log entry. |
Cache | clearEsiCache |
[ |
Use to flush the cache of one or multiple ESI-Widget at once. |
Event | model/prePersist model/postPersist model/preUpdate model/postUpdate model/preRemove model/postRemove model/onFlush model/postFlush |
See Model Events | Use to manually trigger a model event on a model. |
Internal Events
The following events are internal and do therefore not provide any external purpose.
Component | Event |
---|---|
ContentManager | wysiwygCssReload |
Model Events
In the event of flushing the entity manager1, the following pre-defined events are being triggered (in the listed order) on all affected entities that are instances of \Cx\Model\Base\EntityBase
:
Event | Point in time | Listener Invocations2 | Event Arguments |
---|---|---|---|
model/prePersist |
On new entities that have been persisted using $this->cx->getDb()->getEntityManager()->persist($entity) . Note: This event is also being triggered on entities that are subject to a cascade persist operation. |
Once for every newly added entity. Fetch the newly added entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\LifecycleEventArgs |
model/preRemove |
On entities that have been removed using $this->cx->getDb()->getEntityManager()->remove($entity) . Note: This event is also being triggered on entities that are subject to a cascade remove operation. |
Once for every deleted entity. Fetch the deleted entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\LifecycleEventArgs |
model/onFlush |
Only once per model. If multiple entities of a certain model are being flushed, then the registered event listeners are only being called once. | \Doctrine\ORM\Event\OnFlushEventArgs |
|
model/postPersist |
After the newly added entity has been added in the database. | Once for every newly added entity. Fetch the newly added entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\LifecycleEventArgs |
model/preUpdate |
Before the changes of the modified entity are being sent to the database. | Once for every updated entity. Fetch the updated entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\PreUpdateEventArgs |
model/postUpdate |
After the changes of the modified entity have been sent to the database. | Once for every updated entity. Fetch the updated entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\LifecycleEventArgs |
model/postRemove |
After the deleted entity has been removed from the database. | Once for every deleted entity. Fetch the deleted entity in the event listener through $eventArgs->getEntity() . |
\Doctrine\ORM\Event\LifecycleEventArgs |
model/postFlush |
After the database transaction has been committed successfully. Note: This event is never being triggered in case of an issue/exception that happens during the active DB-transaction state. Instead a ROLLBACK command will be sent to the database. |
Only once per model. If multiple entities of a certain model have been flushed, then the registered event listeners are only being called once. | \Doctrine\ORM\Event\PostFlushEventArgs |
Note
The model event system of Cloudrexx differs in the behaviour from the underlying event system of Doctrine in such way, that the above listed model events do only trigger the registered event listeners in case of an actual change on the target model. Whereas a listener that has been registered directly on a Doctrine event3 will always be called, independently of the target model.
Note
The Doctrine model event model/preFlush
is not supported/implemented as a Cloudrexx model event as it can not be bound to a specific model. There are currently no intentions to implement it. However it is possible to listen to the Doctrine event directly4
Entity Modification During Flush
At some degree it is possible to perform entity operations within the execution of a model event. For restrictions and implementation please refer to the Doctrine ORM Event documentation.
Integration
The instance of the EventManager can be fetched as follows:
Register Event
In order to be able to trigger and register a listener to an event, the event first has to be registered as follows:
Note
Please refer to the Naming Conventions on how to properly name your events.
According to the guidelines all events should get registered in the component hook registerEvents
. Therefore, do extend your ComponentController
as follows:
Register Listener
In order to listen to an event, you first need to implement a new class that will act as your event listener as follows:
Implementation details:
- The class must extend
\Cx\Core\Event\Model\Entity\DefaultEventListener
- If you use a separate file for your new class, then it must be located in the folder
/Event
of your component - For each event you want to listen to, you need to implement a method as follows:
- Set method scope to
protected
- Method must accept one single argument
- Set method name according to Listener method naming
- Set method scope to
When an event (your event listener is listening to) is triggered, the associated method (in our case myComponentMyEvent()
) will be called and the argument from the triggerEvent-call (in our case $myEventArguments
) will be passed along.
By extending from \Cx\Core\Event\Model\Entity\DefaultEventListener
your event listener automatically also provides the following handy shortcuts:
Shortcut | Notes |
---|---|
$this->getComponent($name) |
Fetch any component by $name |
$this->cx |
Fetch current instance of \Cx\Core\Core\Controller\Cx |
Finally, your event listener must be registered as such. According to the guidelines this should be done in the component hook registerEventListeners
. Therefore, do extend your ComponentController
as follows:
Note
One and the same instance of an Event Listener can be used to listen to multiple events.
Listener method naming
Listener method names are derived from their associated event names. The conversion occurs from the event name scheme (<component>[.<entity>]:<action>
) the method name <lcfirst:component>[<ucfirst:entity>]<ucfirst:action>
. Examples:
Event name | Corresponding method name |
---|---|
MyComponent:myEvent |
myComponentMyEvent() |
MyComponent.MyModel:myEvent |
myComponentMyModelMyEvent() |
Model Listeners
In order to listen to a model state change event, add an event listener as follows:
Note
See Model Events for a list of available model events.
From Scratch
Alternatively, you could also write your event listener from scratch by implementing the interface \Cx\Core\Event\Model\Entity\EventListener
instead of extending from \Cx\Core\Event\Model\Entity\DefaultEventListener
. In such case you'll have to implement a public
method onEvent()
that accepts two arguments as follows:
Warning
The actual event data is accesible through $eventArgs[0]
.
Trigger Event
To trigger an event, simply do as follows:
Warning
$myEventArguments
must be enclosed as an array element. If $myEventArguments
is already an array, it must still be enclosed as an array element.
Note
Model Events are being triggered automatically.
-
The entity manager can be flushed as follows:
↩ -
This only applies when extending
\Cx\Core\Event\Model\Entity\DefaultEventListener
. When implementing a listener from scratch then this depends on your implementation of theonEvent()
method. ↩ -
Listening directly on a Doctrine event is not advised. However it can be done as follows:
↩ -
Listening directly to the Doctrine event
model/preFlush
is not advised. However it can be done as follows:↩