Общие сведения о событиях в UMI.CMS
События - это механизм, который позволяет выполнять некоторые действия при возникновении определенных ситуаций. В UMI.CMS при выполнении многих операций генерируются события. Если система встречает такое место в программе, то происходит следующее:
- Выполнение операции останавливается
- Выполняется поиск обработчиков этого события (по id события)
- Если обработчики данного события найдены, то последовательно выполняются указанные в этих обработчиках методы
- Выполнение операции продолжается
Терминология
- Точка вызова (Event point). Точка вызова события. Определяется в методе-инициаторе события.
- Перехватчик события (Event listener). Отслеживает определенное событие и запускает соответствующий обработчик
- Обработчик события (Event handler). Метод, который исполняется по факту возникновения события
Вызов события осуществляется так:
<?php
...
некий php-код
$event = new umiEventPoint("systemSwitchElementActivity");//строковый идентификатор события
$event->addRef("element", $element);//передаем ссылку на некий объект
$event->setParam("activity", $activity);//передаем некий параметр
$event->setMode("before");//устанавливаем режим - "событие вызвано ДО осуществления операции"
$event->call();// запускаем обработчик события
продолжение кода
?>
Дойдя до точки $event->call() программа ищет в реестре событий событие с указанным идентификатором, находит его, находит соответствующий ему обработчик и выполняет его.
Реестр событий задается с файле events.php для системных событий и custom_events.php для кастомных событий в директории модуля:
$o_listener_on_remove = new umiEventListener('systemDeleteElement', "blogs20", "onElementRemove");
В примере по событию с идентификатором systemDeleteElement вызывается метод onElementRemove в модуле blogs20
При этом создается т.н. обработчик события (umiEventListener). Обработчик события - это класс, который при создании регистрируется в контроллере событий и слушает событие eventId. Если срабатывает указанное событие, то выполняется метод callbackMethod модуля callbackModule. При этом в данный метод передается в качестве первого параметра объект класса umiEventPoint, который и вызвал событие.
Свойства объекта "Событие" (umiEventPoint)
Событие всегда имеет id события (строковой идентификатор), который задается в конструкторе объекта. В событие можно передать дополнительные параметры (например: id пользователя, номер заказа и т.д.) с помощью метода:
(null) umiEventPoint::setParam((string) $paramName, (mixed) $paramValue = NULL);
Эти параметры потом можно будет использовать в обработчике события с помощью метода:
(mixed) umiEventPoint::getParam((string) $paramName);
Помимо обычных параметров, в событие можно передать ссылку на переменную с помощью метода:
(null) umiEventPoint::addRef($refName, &$refValue);
и соответственно эту ссылку можно будет получить в обработчике:
(mixed) &umiEventPoint::getRef($refName);
Передача переменных по ссылке нужна для того, чтобы из обработчика события можно было поменять значение переменной в контексте того метода, где произошло событие.
Примеры использования umiEvent
1) Делаем что-то по операции изменения активности страницу
<?php
public function onElementActivity($oEventPoint) {
if ($oEventPoint->getMode() === 'after') {//запускать обработчик только если вызов ПОСЛЕ совершения события
$o_element = $oEventPoint->getRef('element');//получить елемент, над которым совершена операция
$param = $oEventPoint->getParam('value');//получаем некий параметр
if ($o_element instanceof umiHierarchyElement) {
//что-то делаем
}
}
}
?>
2) В общем, вся работа с событиями не содержит особенностей, необходимо лишь правильно выбирать режим; посмотреть какие параметры передаются можно в исходном коде системы. Единственное исключение - удаление элемента. По какой-то непонятной мне причине, по событию удаления элемента не удается получить родительский к нему - метод getParent возвращает пустое значение. Поэтому заменил его прямым запросом к базе SELECT SQL_CACHE rel FROM cms3_hierarchy WHERE id = '{$element_id}'. В примере ниже реальный метод, пересчитывающий количество записей в блоге / комментариев к записи по событию удаления записи/комментария из админки
<?
public function onElementRemove(iUmiEventPoint $oEventPoint) {
if ($oEventPoint->getMode() === 'after') {
if($o_element = $oEventPoint->getRef('element')){
$id = $o_element->getId();
$h = umiHierarchy::getInstance();
$element_id = (int) $id;
$sql = "SELECT SQL_CACHE rel FROM cms3_hierarchy WHERE id = '{$element_id}'";
$result = l_mysql_query($sql);
if(mysql_num_rows($result)) {
$id = mysql_result($result,0,0);
$o_element = umiHierarchy::getInstance() -> getElement($id, false, false);
$id = $o_element->getId();
$method = $o_element->getMethod();
if (($method == 'post') or ($method == 'blog')) {
$c = $this->recalcCounts($o_element);
}
}
}
}
}
?>