Event Handler
One commonly used technique for manipulating existing processes or adding features in a custom module is the implementation of event handlers.
The most common core events used to manipulate existing features are described in the following guide.
Please refer to the Yii Events Guide for general information about the usage of events. Also check the Events Concept section for information about implementing own events.
Event handler configuration
Event handlers in HumHub modules are registered within the events
section of the config.php file.
It is recommended to implement the handler functions within a dedicated Events.php
file in the module root.
Some modules may use the Module.php
class for event handler implementations, this should only be considered for
simple and few event handlers in order to keep a clean module structure.
Example handler configuration
// config.php
use my\example\Events;
use my\example\modles\Example;
return [
//...
'events' => [
[
'class' => Example::class,
'event' => Example::EVENT_SOME_EVENT,
'callback' => [Events::class, 'onSomeEvent']
],
//...
]
]
Key | Description |
---|---|
class | The namespaced class string of the class responsible for triggering the event. |
event | The event name, usually available as class const |
callback | Event handler callback class and function name |
When listening to a non core class event, use an actual string definition instead of an import with usage of ::class
to
prevent errors when the required module is not enabled.
Example handler implementation
// example/Events.php
public static function onSomeEvent($event)
{
$exampleModel = $event->sender;
//...
}
Event classes
Depending on the triggered event, there are different types of events provided as event handler argument. Some of the most common event classes are listed in the following table.
Key | Description |
---|---|
yii\base\Event | Base event class of Yii |
yii\base\ModelEvent | Supports additional $isValid flag |
yii\db\AfterSaveEvent | Event used for some ActiveRecord Events |
yii\base\ActionEvent | Controller/Action related events |
yii\base\WidgetEvent | Widget related events |
yii\web\UserEvent | User identity related events |
humhub\components\Event | HumHub base event with additional $result property |
humhub\modules\user\events\UserEvent | Used for user related events with additional $user property |
humhub\modules\user\events\FollowEvent | Events related to user following |
humhub\modules\friendship\FriendshipEvent | Events related to user friendship |
humhub\modules\space\MemberEvent | Events related to space memberships |
humhub\components\ModuleEvent | Module related event with getModule() function |
humhub\events\ActiveQueryEvent | ActiveQuery related events with additional $query property |
custom | Custom modules may implement own event types |
Application Events
Application events can be used to globally intercept requests and actions.
yii\base\Application provides the following events:
Event | Class | Description |
---|---|---|
Application::EVENT_BEFORE_ACTION | yii\base\ActionEvent | Raised before executing a controller action |
Application::EVENT_AFTER_ACTION | yii\base\ActionEvent | Raised after executing a controller action |
Application::EVENT_BEFORE_REQUEST | yii\base\Event | Raised before the application starts to handle a request |
Application::EVENT_AFTER_REQUEST | yii\base\Event | Raised after the application successfully handles a request (before the response is sent out) |
humhub\components\console\Application
additionally triggers the following event
Event | Class | Description |
---|---|---|
Application::EVENT_ON_INIT | yii\base\ActionEvent | Raised at the end of init() |
Module Events
ModuleManager
humhub\components\ModuleManager
events can be used to listen for enable and disable
events of modules. This can be useful in order to listen and react to lifecycle events of dependent modules.
Event | Class | Description |
---|---|---|
ModuleManager::EVENT_BEFORE_MODULE_ENABLE | humhub\components\ModuleEvent | Raised before a module is enabled |
ModuleManager::EVENT_AFTER_MODULE_ENABLE | humhub\components\ModuleEvent | Raised after a module is enabled |
ModuleManager::EVENT_BEFORE_MODULE_DISABLE | humhub\components\ModuleEvent | Raised before a module is disabled |
ModuleManager::EVENT_AFTER_MODULE_DISABLE | humhub\components\ModuleEvent | Raised after a module is disabled |
ModuleManager::EVENT_AFTER_FILTER_MODULES | humhub\components\ModuleEvent | Raised after filter modules |
The humhub\components\ModuleEvent
class provides the following additional properties and functions:
$moduleId
: The moduleId of the module -getModule()
: Can be used to return a module instance
In the following example we use the ModuleManager::EVENT_AFTER_MODULE_ENABLE
to set a module setting of another module
right after the module is enabled.
// config.php
use humhub\components\ModuleManager;
return [
//..
'events' => [
[
'class' => ModuleManager::class,
'event' => ModuleManager::EVENT_BEFORE_MODULE_ENABLE,
'callback' => [Event::class, 'onAfterModuleEnabled']
]
]
]
// Events.php
public static function onAfterModuleEnabled(ModuleEvent $event)
{
if($event->moduleId === 'specialModle') {
$event->getModule()->settings->set('someSetting', 'someSpecificValue');
}
}
OnlineModuleManager
humhub\modules\marketplace\components\OnlineModuleManager
provides events triggered before and after a module was updated
by the marketplace.
Event | Class | Description |
---|---|---|
OnlineModuleManager::EVENT_BEFORE_UPDATE | humhub\components\ModuleEvent | Raised before a module is updated |
OnlineModuleManager::EVENT_AFTER_UPDATE | humhub\components\ModuleEvent | Raised after a module is updated |
Controller Events
Controller events can be used to intercept requests of web or console controller actions and manipulate the controller result.
Event | Class | Description |
---|---|---|
Controller::EVENT_AFTER_ACTION | yii\base\ActionEvent | Raised right after executing a controller action |
Controller::EVENT_BEFORE_ACTION | yii\base\ActionEvent | Raised right before executing a controller action |
In the following example we listen to all web controller requests and redirect to a custom action in case some special condition is not met.
// config.php
use my\example\Events;
use humhub\components\Controller;
return [
//...
'events' => [
['class' => Controller::class, 'event' => Controller::EVENT_BEFORE_ACTION, 'callback' => [Events::class, 'onBeforeControllerAction']]
]
]
// Events.php
public static function onBeforeControllerAction(ActionEvent $event)
{
if(!static::checkSomeSpecialCondition($event)) {
// Do not continue running the action.
$event->isValid = false;
// Manipulate action result
$event->result = Yii::$app->response->redirect(['/example/special-condition/index']);
}
}
See Yii Controller Events for more information about the usage of Controller events.
CronController Events
Events of the humhub\commands\CronController
can be handled in order to implement scheduled tasks.
Event | Class | Description |
---|---|---|
CronController::EVENT_ON_HOURLY_RUN | yii\base\Event | Raised hourly |
CronController::EVENT_ON_DAILY_RUN | yii\base\Event | Raised daily |
Use the CronController::EVENT_BEFORE_ACTION
in case you want to implement a custom scheduling interval.
Response Events
Response events can be used to manipulate the server response.
Event | Class | Description |
---|---|---|
Response::EVENT_AFTER_PREPARE | yii\base\Event | Raised right after prepare() is called in send() |
Response::EVENT_AFTER_SEND | yii\base\Event | Raised at the end of send() |
Response::EVENT_BEFORE_SEND | yii\base\Event | at the beginning of send() |
See Yii Response Events for more information.
Model validation
The base Model class supports events useful to intercepting the validation of a model.
Event | Class | Description |
---|---|---|
Model::EVENT_BEFORE_VALIDATE | yii\base\Event | Raised at the beginning of validate() |
Model::EVENT_AFTER_VALIDATE | yii\base\ModelEvent | Raised at the end of validate() |
In the following example we implement a handler for the EVENT_BEFORE_VALIDATE
of the humhub\modules\user\models\Invite
model
in order to intercept the registration process.
// config.php
use humhub\modules\user\models\Invite;
return [
//..
'events' => [
[
'class' => Invite::class,
'event' => Invite::EVENT_BEFORE_VALIDATE,
'callback' => [Events::class, 'onInviteBeforeValidate']
]
]
]
// Events.php
public static function onInviteBeforeValidate($event)
{
$registrationForm = $event->sender;
$user = $registrationForm->models['User'];
if (self::autoEnable($user->email) {
$user->status = User::STATUS_ENABLED;
$registrationForm->enableUserApproval = false;
} else if (!self::isAllowed($user->email)) {
$user->status = User::STATUS_DISABLED;
$user->addError('email', Yii::t('EnterpriseModule.emailwhitelist', 'The given email address is not allowed for registration!'));
}
}
ActiveRecord (CRUD) Events
The ActiveRecord class supports additional events for intercepting CRUD related events. Those events are useful for manipulating model properties or synchronizing the creation/deletion of custom models with models of other modules.
Event | Class | Description |
---|---|---|
ActiveRecord::EVENT_AFTER_DELETE | yii\base\Event | Raised after a record is deleted |
ActiveRecord::EVENT_AFTER_FIND | yii\base\ModelEvent | Raised after the record is created and populated with query result |
ActiveRecord::EVENT_AFTER_INSERT | yii\db\AfterSaveEvent | Raised after a record is inserted |
ActiveRecord::EVENT_AFTER_REFRESH | yii\base\Event | Raised after a record is refreshed |
ActiveRecord::EVENT_AFTER_UPDATE | yii\db\AfterSaveEvent | Raised after a record is updated |
ActiveRecord::EVENT_BEFORE_INSERT | yii\base\ModelEvent | Raised before inserting a record |
ActiveRecord::EVENT_BEFORE_UPDATE | yii\base\ModelEvent | Raised before updating a record |
ActiveRecord::EVENT_INIT | yii\base\Event | Raised when the record is initialized via init() |
Example use cases:
- Listen for
EVENT_AFTER_INSERT
andEVENT_BEFORE_DELETE
events of a specific record type in order to synchronize the creation or deletion of custom model relations - Listen for
EVENT_BEFORE_SAVE
to manipulate the properties of a model prior to persisting it to the database - Listen for
EVENT_AFTER_FIND
to manipulate model properties right after model queries.
See Yii ActiveRecord Events for more information about the usage of ActiveRecord events.
User Events
User Model
The humhub\modules\user\models\User
model provides the following additional events:
Event | Class | Description |
---|---|---|
User::EVENT_CHECK_VISIBILITY | humhub\modules\user\events\UserEvent | Can be used to add conditions to User::isVisible() |
User::EVENT_BEFORE_SOFT_DELETE | humhub\modules\user\events\UserEvent | Raised after a soft deletion of a user model |
The following example adds an user visibility condition:
// config.php
use my\example\Events;
use humhub\modules\user\model\Use;
return [
//...
'events' => [
[
'class' => Use::class,
'event' => Use::EVENT_CHECK_VISIBILITY,
'callback' => [Events::class, 'onUserIsVisible']
]
]
]
// Events.php
public static function onUserIsVisible(UserEvent $event)
{
if($event->user->username === 'secretUser') {
$event->result['isVisible'] = false;
}
}
ActiveQueryUser Events
The humhub\modules\user\components\ActiveQueryUser
events may be used to add conditions
ActiveQueryUser::visible()
(in addition to Use::EVENT_CHECK_VISIBILITY
) and ActiveQueryUser::active()
.
This will manipulate the results of queries like:
User::find()->active()->visible()->all();
Event | Class | Description |
---|---|---|
ActiveQueryUser::EVENT_CHECK_VISIBILITY | humhub\events\ActiveQueryEvent | Raised within visible() user query |
ActiveQueryUser::EVENT_CHECK_ACTIVE | humhub\events\ActiveQueryEvent | Raised within active() user query |
In the following example we add an additional check to ActiveQueryUser::visible()
by checking a custom user
table field.
In this example the user.is_visible_in_crm
was added to the user table by our custom module.
// config.php
use my\example\Events;
use humhub\modules\user\components\ActiveQueryUser;
return [
//...
'events' => [
[
'class' => ActiveQueryUser::class,
'event' => ActiveQueryUser::EVENT_CHECK_VISIBILITY,
'callback' => [Events::class, 'onUserQueryVisible']
]
]
]
// Events.php
public static function onUserQueryVisible(ActiveQueryEvent $event)
{
$event->query->andWhere(['user.is_visible_in_crm' => 1]);
}
Registration Events
The humhub\modules\user\models\forms\Registration
class provides events raised within the registration process:
Event | Class | Description |
---|---|---|
Registration::EVENT_AFTER_REGISTRATION | yii\web\UserEvent | Raised after successful registration |
The following example shows how to synchronize the registration process with an external crm service.
// config.php
use my\example\Events;
use humhub\modules\user\models\forms\Registration;
return [
//...
'events' => [
[
'class' => Registration::class,
'event' => Registration::EVENT_AFTER_REGISTRATION,
'callback' => [Events::class, 'onUserRegistration']
]
]
]
// Events.php
public static function onUserRegistration(UserEvent $event)
{
try {
$service = new CrmService();
$result = $service->createOrUpdateSubscriber($evt->identity);
// Check for errors or log result etc...
static::handleCrmServiceResult($result);
} catch(\Exception $e) {
Yii::error($e);
}
}
User Follow Events
User follow events are triggered once a user follows or unfollows a content, space or another user by the humhub\modules\user\models\Follow
class.
Event | Class | Description |
---|---|---|
Follow::EVENT_FOLLOWING_CREATED | humhub\modules\user\events\FollowEvent | Raised when a user follows a content/space/user |
Follow::EVENT_FOLLOWING_REMOVED | humhub\modules\user\events\FollowEvent | Raised when a user unfollows a content/space/user |
The following example sends out a custom FollowAchievementNotification
notification once the user reaches a certain amount of followers.
The notification is removed in case the follower decreases to lower thant 5.
// config.php
use my\example\Events;
use humhub\modules\user\models\Follow;
return [
//...
'events' => [
[
'class' => Follow::class,
'event' => Follow::EVENT_FOLLOWING_CREATED,
'callback' => [Events::class, 'onUserFollow']
],
[
'class' => Follow::class,
'event' => Follow::EVENT_FOLLOWING_REMOVED,
'callback' => [Events::class, 'onUserUnfollow']
],
]
]
// Events.php
public static function onUserFollow(FollowEvent $event)
{
if($event->target instanceof User) {
if($event->target->getFollowerCount() === 5) {
FollowAchievementNotification::instance()->send($event->target);
}
}
}
public static function onUserUnfollow(FollowEvent $event)
{
if($event->target instanceof User) {
if($event->target->getFollowerCount() < 5) {
FollowAchievementNotification::instance()->delete($event->target);
}
}
}
User Friendship Events
Similar to the follow events, the friendship module triggers an events once a user friendship relation is created or
removed. The events are triggered by the humhub\modules\friendship\models\Friendship
model.
Event | Class | Description |
---|---|---|
Friendship::EVENT_FRIENDSHIP_CREATED | humhub\modules\friendship\FriendshipEvent | Raised when a user makes a new friend |
Friendship::EVENT_FRIENDSHIP_REMOVED | humhub\modules\friendship\FriendshipEvent | Raised when a user removes a friendship |
The humhub\modules\friendship\FriendshipEvent
class provides the following additional properties:
$user1
: The user initiating the friendship -$user2
: The user who received the friendship request
Space Membership
Space membership events are triggered by the humhub\modules\space\models\Membership
model and can be used to trace the
creation or removal of space membership relations.
Event | Class | Description |
---|---|---|
Membership::EVENT_MEMBER_ADDED | humhub\modules\space\MemberEvent | Raised when a user joins a space or was added |
Membership::EVENT_MEMBER_REMOVED | humhub\modules\space\MemberEvent | Raised when a user leaves a space or was removed |
The humhub\modules\space\models\Membership
class provides the following additional properties:
$space
: Thehumhub\modules\space\models\Space
model of the space -$user
: The respective user model of the membership relation
Widget Events
Widget events can be used to extend the output of a widget or even overwrite widget classes.
Event | Class | Description |
---|---|---|
Widget::EVENT_INIT | yii\base\Event | Raised when the widget is initialized via init() |
Widget::EVENT_BEFORE_RUN | yii\base\WidgetEvent | Raised right before executing a widget |
Widget::EVENT_AFTER_RUN | yii\base\WidgetEvent | Raised right after executing a widget |
humhub\components\Widget::EVENT_CREATE | humhub\libs\WidgetCreateEvent | Raised before Yii::createObject() |
Extend widget output
The Widget::EVENT_AFTER_RUN
can be used to extend the output of a widget, as in the following example:
// config.php
use my\example\Events;
use humhub\modules\content\widgets\richtext\ProsemirrorRichTextEditor;
return [
//...
'events' => [
[
'class' => ProsemirrorRichTextEditor::class,
'event' => ProsemirrorRichTextEditor::EVENT_AFTER_RUN,
'callback' => [Events::class, 'onRichTextEditorFieldCreate']
]
]
]
// Events.php
public static function onRichTextEditorFieldCreate(WidgetEvent $event)
{
$event->result .= '<div>Powered by example Module</div>';
}
Prevent widget from rendering
The Widget::EVENT_BEFORE_RUN
can be used prevent widgets from rendering:
// config.php
use my\example\Events;
use humhub\components\Widget;
return [
//...
'events' => [
[
'class' => 'some\module\widget\SpecialWidget',
'event' => Widget::EVENT_BEFORE_RUN,
'callback' => [Events::class, 'onSpecialWidgetBeforeRun']]
]
]
// Events.php
public static function onSpecialWidgetBeforeRun(WidgetEvent $event)
{
if(static::someSpecialCondition($event)) {
$event->isValid = false;
}
}
Overwrite a widget class
The humhub\components\Widget::EVENT_CREATE
can be used to overwrite the widget class.
// config.php
use my\example\Events;
use humhub\components\Widget;
return [
//...
'events' => [
[
'class' => 'some\module\widget\SpecialWidget',
'event' => Widget::EVENT_CREATE,
'callback' => [Events::class, 'onSpecialWidgetCreate']]
]
]
// Events.php
public static function onSpecialWidgetCreate(WidgetCreateEvent $event)
{
$event->config['class'] = MyCustomSpecialWidget::class;
}
Since the widget is created by a call to Yii::createObject()
the new widget class has to be compatible with the overwritten one,
which means it has to support all possible properties of the original widget class. This could be achieved by extending the original
widget.