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.
Contents
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
|
[
'kind' => <to/cc/bcc>,
'address' => <e-mail>,
'name' => <recipient_name>,
'mail' => $mail,
]
|
$mail is the instance of \Cx\Core\MailTemplate\Model\Entity\Mail on which the recipient is being added
|
Catch recipient before email is dispatched. |
DataSource | preDistantEntityLoad
|
[
'targetEntityClassName' => <entity>,
'targetId' => <id>,
]
|
- | 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
|
[
'content' => &$string,
'template' => $sigma,
]
|
$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
|
[
'content' => &$val,
'template' => $sigma,
]
|
$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
|
[
'componentName' => <name>,
'component' => <component>,
'hook' => <hook>,
]
|
<hook> will be one of the available Component Hooks.
|
Use to inject code before the executing of other components' hooks. |
postComponent
|
Use to inject code after the executing of other components' hooks. |
Active Events
Trigger the following events to perform certain operations.
Component | Event | Argument Definition | Purpose |
---|---|---|---|
SysLog | SysLog/Add
|
[
'severity' => '<type>',
'message' => '<log message>',
'data' => <data>,
]
|
Use to add a System Log entry. |
Cache | clearEsiCache
|
[
'Widget',
[ <widget>, ...],
]
|
Use to flush the cache of one or multiple ESI-Widget at once. |
Event | model/prePersist
|
See Model Events | Use to manually trigger a model event on a model. |
model/postPersist
| |||
model/preUpdate
| |||
model/postUpdate
| |||
model/preRemove
| |||
model/postRemove
| |||
model/onFlush
| |||
model/postFlush
|
Internal Events
The following events are internal and do therefore not provide any external purpose.
Component | Event |
---|---|
ContentManager | wysiwygCssReload
|
Model Events
The following pre-defined events are being triggered (in the listed order, from top to bottom) on all entities that are instances of \Cx\Model\Base\EntityBase
in the event of flushing the entity manager[1]:
# | Event | Point in time | Listener Invocations | DB Transaction State |
---|---|---|---|---|
↓ | model/prePersist
|
When $this->cx->getDb()->getEntityManager()->persist($entity) is being called to persist a newly created 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[0]->getEntity() .
|
None |
model/preRemove
|
When $this->cx->getDb()->getEntityManager()->remove($entity) is being called to delete the 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[0]->getEntity() .
| ||
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. | |||
BEGIN
| ||||
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[0]->getEntity() .
|
Active | |
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[0]->getEntity() .
| ||
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[0]->getEntity() .
| ||
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[0]->getEntity() .
| ||
COMMIT
| ||||
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. | None |
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 directly[3]- Footnotes
- ↑ The entity manager can be flushed as follows:
$this->cx->getDb()->getEntityManager()->flush();
- ↑ Listening directly on a Doctrine event is not advised. However it can be done as follows:
$this->cx->getDb()->getEntityManager()->getEventManager()->addEventListener( $event, // see lib/doctrine/Doctrine/ORM/Events.php for possible values new \Cx\Modules\MyComponent\Model\Event\MyEventListener() );
- ↑ Listening directly to the Doctrine event
model/preFlush
is not advised. However it can be done as follows:$this->cx->getDb()->getEntityManager()->getEventManager()->addEventListener( \Doctrine\ORM\Events::preFlush, new \Cx\Modules\MyComponent\Model\Event\MyEventListener() );
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:
$eventManager = $this->cx->getEvents();
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:
$this->cx->getEvents()->addEvent('MyComponent:myEvent');
According to the guidelines all events should get registered in the component hook registerEvents
.
Therefore, do extend your ComponentController
as follows:
/**
* @{inheritdoc}
*/
public function registerEvents() {
$this->cx->getEvents()->addEvent('MyComponent:myEvent');
}
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:
<?php
namespace \Cx\Modules\MyComponent\Model\Event;
class MyComponentEventListener extends \Cx\Core\Event\Model\Entity\DefaultEventListener {
public function myComponentMyEvent($args) {
// add your code here
}
}
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
- Set method name based on the event to listen to. The scheme of an event (
<component>[.<entity>]:<action>
) gets converted to its corresponding method name as follows:<lcfirst:component>[<ucfirst:entity>]<ucfirst:action>
Examples:Event name Corresponding method name MyComponent:myEvent
myComponentMyEvent()
MyComponent.MyModel:myEvent
myComponentMyModelMyEvent()
- Method must accept one single argument
- Set method scope to
- Example:
protected function myComponentMyEvent($eventArgs) { // add your code here }
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
|
\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: public function onEvent($eventName, array $eventArgs) {
// insert your code here
}
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:
/**
* @{inheritdoc}
*/
public function registerEventListeners() {
$myEventListener = new \Cx\Modules\MyComponent\Model\Event\MyComponentEventListener($this->cx);
$this->cx->getEvents()->addEventListener(
'MyComponent:myEvent',
$myEventListener
);
}
Model Listeners
In order to listen to a model state change event, add an event listener as follows:
/**
* @{inheritdoc}
*/
public function registerEventListeners() {
$myEventListener = new \Cx\Modules\MyComponent\Model\Event\MyComponentEventListener($this->cx);
$this->cx->getEvents()->addModelListener(
// One of the available model events
'model/prePersist',
// FQCN of an EntityBase model with escaped backslashes
'Cx\\Core\\ContentManager\\Model\\Entity\\Page',
$myEventListener
);
}
Trigger Event
To trigger an event, simply do as follows:
$this->cx->getEvents()->triggerEvent(
'MyComponent:myEvent',
[$myEventArguments]
);
$myEventArguments
must be enclosed as an array element. If $myEventArguments
is already an array, it must still be enclosed as an array element.