События

Обзор

Elgg имеет систему событий, которую можно использовать для замены или расширения базовой функциональности.

Плагины влияют на систему, создавая обработчики (callables, такие как функции и методы) и регистрируя их для обработки событий.

Когда событие запускается, набор обработчиков выполняется в порядке приоритета. Каждому обработчику передаются аргументы, и он имеет возможность повлиять на процесс. После выполнения функция «trigger» возвращает значение на основе поведения обработчиков.

События Elgg

События Elgg запускаются, когда объект Elgg создаётся, обновляется или удаляется; а также на важных этапах при загрузке фреймворка Elgg. Примеры: создание поста блога или вход пользователя в систему.

Эти события в основном используются для уведомления остальной части системы о том, что что-то произошло.

Также есть события, которые используются для влияния на вывод, конфигурацию или поведение системы.

Каждое событие Elgg имеет имя и тип (system, user, object, имя отношения, annotation, group), описывающий тип объекта, передаваемого обработчикам.

События Before и After

Некоторые события разделены на «before» и «after». Это позволяет избежать путаницы вокруг состояния системы во время изменений. Например, авторизован ли пользователь во время события [login, user]?

События Before имеют имена, оканчивающиеся на «:before», и запускаются до того, как что-то произойдёт. Обработчики могут отменить событие, вернув false. Когда обработчик возвращает false, последующие обработчики не будут вызваны.

События After, с именами, оканчивающимися на «:after», запускаются после того, как что-то произошло. Обработчики не могут отменить эти события; все обработчики всегда будут вызваны.

Там, где доступны события before и after, разработчикам рекомендуется переходить на них, хотя старые события будут поддерживаться для обратной совместимости.

Обработчики событий Elgg

Обработчики событий Elgg являются вызываемыми:

<?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) {
    ...
}

В event_handler объект Event имеет различные методы для получения имени, типа объекта и объекта события. См. класс Elgg\Event для получения подробной информации.

Регистрация для обработки события Elgg

Зарегистрируйте свой обработчик для события с помощью elgg_register_event_handler:

<?php

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

Параметры:

  • $event — имя события.

  • $type — тип события (например, «user» или «object») или „all“ для всех типов, на которых запускается событие.

  • $handler — обратный вызов функции обработчика.

  • $priority — приоритет: 0 — первый, по умолчанию — 500.

Пример:

<?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);

Предупреждение

Если вы обрабатываете событие «update» на объекте, избегайте вызова save() в вашем обработчике событий. Во-первых, это, вероятно, не нужно, так как объект сохраняется после завершения события, но также потому, что save() вызывает другое событие «update» и делает $object->getOriginalAttributes() недоступным.

Вызываемые классы как обработчики

Вы можете использовать класс с методом __invoke() в качестве обработчика. Просто зарегистрируйте имя класса, и он будет создан (без аргументов) на время жизни события.

<?php

namespace MyPlugin;

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

    }
}

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

Запуск события Elgg

Вы можете запустить пользовательское событие Elgg с помощью 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.
}

Для событий с неоднозначными состояниями, таких как вход пользователя в систему, вы должны использовать События Before и After, вызывая elgg_trigger_before_event или elgg_trigger_after_event. Это делает понятным для обработчика событий, какого состояния ожидать и какие события могут быть отменены.

<?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);

Параметры:

  • $event — имя события.

  • $object_type — тип объекта (например, «user» или «object»).

  • $object — объект (например, экземпляр ElggUser или ElggGroup)

Функция вернёт false, если какой-либо из выбранных обработчиков вернул false и событие может быть остановлено, в противном случае она вернёт true.

Запуск события с результатами

События с результатами предоставляют способ для плагинов совместно определять или изменять значение. Например, чтобы решить, имеет ли пользователь разрешение на редактирование сущности или добавить дополнительные параметры конфигурации в плагин.

Событие имеет значение, передаваемое в функцию запуска, и каждый обработчик имеет возможность изменить значение перед передачей следующему обработчику. После завершения последнего обработчика триггер возвращает окончательное значение.

Вы можете запустить пользовательское событие с помощью elgg_trigger_event_results:

<?php

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

Параметры:

  • $name — имя события.

  • $type — тип события или „all“ для всех типов.

  • $params — произвольные данные, передаваемые от триггера к обработчикам.

  • $value — начальное значение события.

Запуск последовательности событий Elgg

Вместо ручного запуска событий :before и :after можно запустить последовательность событий. Это запустит событие :before, затем фактическое событие и, наконец, событие :after.

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);

При вызове, например, с 'cache:clear', 'system' запускаются следующие три события

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

  • 'cache:clear', 'system'

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

Параметры:

  • $event — имя события.

  • $object_type — тип объекта (например, «user» или «object»).

  • $object — объект (например, экземпляр ElggUser или ElggGroup)

  • $callable — вызываемый объект для запуска при успешном событии, перед событием :after

Примечание

Начиная с Elgg 6.0 событие :after больше не будет запускаться, если результат вызываемого объекта равен false. Это было сделано для того, чтобы предотвратить ситуацию, когда система считает, что что-то было сделано, но не успешно. Например, последовательность событий 'delete', 'user'. Если обратный вызов (который обрабатывает фактическое удаление из базы данных) не был успешным, событие :after подразумевало, что пользователь был удалён. Теперь это запускается только тогда, когда пользователь действительно удалён из базы данных.

Отмена регистрации обработчиков событий

Функции elgg_unregister_event_handler могут использоваться для удаления обработчиков, уже зарегистрированных другим плагином или ядром Elgg. Параметры идут в том же порядке, что и в функциях регистрации, за исключением того, что нет параметра приоритета.

<?php

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

Анонимные функции или вызываемые объекты нельзя отменить регистрацию, но динамические обратные вызовы методов можно отменить регистрацию, указав статическую версию обратного вызова:

<?php

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

// ... elsewhere

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

Несмотря на то, что обработчик событий ссылается на динамический вызов метода, приведённый выше код успешно удалит обработчик.

Порядок вызова обработчиков

Обработчики вызываются сначала в порядке приоритета, затем в порядке регистрации.

Примечание

До Elgg 2.0 регистрация с ключевыми словами all приводила к тому, что обработчики вызывались позже, даже если они были зарегистрированы с более низкими приоритетами.