Events

Overview

Elgg has an event system that can be used to replace or extend core functionality.

Plugins influence the system by creating handlers (callables such as functions and methods) and registering them to handle the events.

When an event is triggered, a set of handlers is executed in order of priority. Each handler is passed arguments and has a chance to influence the process. After execution, the „trigger“ function returns a value based on the behavior of the handlers.

Elgg Events

Elgg Events are triggered when an Elgg object is created, updated, or deleted; and at important milestones while the Elgg framework is loading. Examples: a blog post being created or a user logging in.

These events are mostly used to notify the rest of the system that something has happened.

There are also events that are used to influence output, configuration or behaviour of the system.

Each Elgg event has a name and a type (system, user, object, relationship name, annotation, group) describing the type of object passed to the handlers.

Before and After Events

Some events are split into „before“ and „after“. This avoids confusion around the state of the system while in flux. E.g. Is the user logged in during the [login, user] event?

Before Events have names ending in „:before“ and are triggered before something happens. Handlers can cancel the event by returning false. When false is returned by a handler, following handlers will not be called.

After Events, with names ending in „:after“, are triggered after something happened. Handlers cannot cancel these events; all handlers will always be called.

Where before and after events are available, developers are encouraged to transition to them, though older events will be supported for backwards compatibility.

Elgg Event Handlers

Elgg event handlers are callables:

<?php

/**
 * @param \Elgg\Event $event The event object
 *
 * @return bool if false, the handler is requesting to cancel the event
 */
function event_handler(\Elgg\Event $event) {
    ...
}

In event_handler, the Event object has various methods for getting the name, object type, and object of the event. See the Elgg\Event class for details.

Register to handle an Elgg Event

Register your handler to an event using elgg_register_event_handler:

<?php

elgg_register_event_handler($event, $type, $handler, $priority);

Parameters:

  • $event The event name.

  • $type The event type (e.g. „user“ or „object“) or ‚all‘ for all types on which the event is fired.

  • $handler The callback of the handler function.

  • $priority The priority - 0 is first and the default is 500.

Example:

<?php

// Register the function myPlugin_handle_create_object() to handle the
// create object event with priority 400.
elgg_register_event_handler('create:after', 'object', 'myPlugin_handle_create_object', 400);

Warnung

If you handle the „update“ event on an object, avoid calling save() in your event handler. For one it’s probably not necessary as the object is saved after the event completes, but also because save() calls another „update“ event and makes $object->getOriginalAttributes() no longer available.

Invokable classes as handlers

You may use a class with an __invoke() method as a handler. Just register the class name and it will be instantiated (with no arguments) for the lifetime of the event.

<?php

namespace MyPlugin;

class UpdateObjectHandler {
    public function __invoke(\Elgg\Event $event) {

    }
}

// in init, system
elgg_register_event_handler('update', 'object', MyPlugin\UpdateObjectHandler::class);

Trigger an Elgg Event

You can trigger a custom Elgg event using elgg_trigger_event:

<?php

if (elgg_trigger_event($event, $object_type, $object)) {
    // Proceed with doing something.
} else {
    // Event was cancelled. Roll back any progress made before the event.
}

For events with ambiguous states, like logging in a user, you should use Before and After Events by calling elgg_trigger_before_event or elgg_trigger_after_event. This makes it clear for the event handler what state to expect and which events can be cancelled.

<?php

// handlers for the user, login:before event know the user isn't logged in yet.
if (!elgg_trigger_before_event('login', 'user', $user)) {
    return false;
}

// handlers for the user, login:after event know the user is logged in.
elgg_trigger_after_event('login', 'user', $user);

Parameters:

  • $event The event name.

  • $object_type The object type (e.g. „user“ or „object“).

  • $object The object (e.g. an instance of ElggUser or ElggGroup)

The function will return false if any of the selected handlers returned false and the event is stoppable, otherwise it will return true.

Trigger an Event with results

Events with results provide a way for plugins to collaboratively determine or alter a value. For example, to decide whether a user has permission to edit an entity or to add additional configuration options to a plugin.

An event has a value passed into the trigger function, and each handler has an opportunity to alter the value before it’s passed to the next handler. After the last handler has completed, the final value is returned by the trigger.

You can trigger a custom event using elgg_trigger_event_results:

<?php

// filter $value through the handlers
$value = elgg_trigger_event_results($name, $type, $params, $value);

Parameters:

  • $name The name of the event.

  • $type The type of the event or ‚all‘ for all types.

  • $params Arbitrary data passed from the trigger to the handlers.

  • $value The initial value of the event.

Trigger an Elgg Event sequence

Instead of triggering the :before and :after event manually, it’s possible to trigger an event sequence. This will trigger the :before event, then the actual event and finally the :after event.

elgg()->events->triggerSequence($event, $type, $object, $callable);

// or if you wish to have a result sequence
$result = elgg->events->triggerResultsSequence($name, $type, $params, $value, $callable);

When called with for example 'cache:clear', 'system' the following three events are triggered

  • 'cache:clear:before', 'system'

  • 'cache:clear', 'system'

  • 'cache:clear:after', 'system'

Parameters:

  • $event The event name.

  • $object_type The object type (e.g. „user“ or „object“).

  • $object The object (e.g. an instance of ElggUser or ElggGroup)

  • $callable Callable to run on successful event, before event:after

Bemerkung

As of Elgg 6.0 the :after event will no longer be triggered if the result of the callable is false. This was done in order to prevent the system from thinking something was done which wasn’t successful. For example the 'delete', 'user' event sequence. If the callback (which handles the actual removal from the database) wasn’t successful the :after event implied that the user was deleted. Now this is only triggered when the user is actually removed from the database.

Unregister Event Handlers

The functions elgg_unregister_event_handler can be used to remove handlers already registered by another plugin or Elgg core. The parameters are in the same order as the registration functions, except there’s no priority parameter.

<?php

elgg_unregister_event_handler('login', 'user', 'myPlugin_handle_login');

Anonymous functions or invokable objects cannot be unregistered, but dynamic method callbacks can be unregistered by giving the static version of the callback:

<?php

$obj = new MyPlugin\Handlers();
elgg_register_event_handler('foo', 'bar', [$obj, 'handleFoo']);

// ... elsewhere

elgg_unregister_event_handler('foo', 'bar', 'MyPlugin\Handlers::handleFoo');

Even though the event handler references a dynamic method call, the code above will successfully remove the handler.

Handler Calling Order

Handlers are called first in order of priority, then registration order.

Bemerkung

Before Elgg 2.0, registering with the all keywords caused handlers to be called later, even if they were registered with lower priorities.