Events: события
В ТАО реализована система событий (модуль Events), описывающая стандартный механизм событий в ООП. Что позволяет достаточно быстро внедрять дополнительный функционал в существующий код.
Основной принцип работы заключается в том, что во фреймворке по различным поводам генерируются события, а в коде проекта могут присутствовать специальные обработчики этих событий. Любое событие имеет имя - строковое значение, также в него могут быть переданы аргументы. В некоторых случаях обработчики событий могут возвращать какие-либо значения (в зависимости от самого события).
Генерация событий
Генерация события производится с использованием метода Events::call().
Events::call('name.of.event', $arg1, $arg2);
где,
- name.of.event - имя события, строковое значение.
- $arg1, $arg2 - аргументы, которые будут переданы в обработчик.
При формировании имен событий, для поддержания единообразия, желательно придерживаться сложившегося правила именования событий во фреймворке. А именно, если событие будет генерироваться в рамках компонента, то в имени указывается ключевое слово component и имя компонента, далее идет название модуля (где будет генерироваться событие), название действия. Если событие относится к библиотеке, то в имени должно быть указано ключевое слово CMS .
Например,
component.comments.before.add - компонент Комментарии, вызов события, позволяющего произвести какие-то действия до записи комментария в базу
cms.actions.dispatch - библиотечное событие. Вызывается перед началом диспетчеризации запроса.
Обработка событий
Как правило, в проектах редко возникает необходимость генерировать события. Основное место генерации в ядре фреймворка, в CMS, в библиотечных компонентах. На проектах часто осуществляется только обработка событий. Для этого применяется метод Events::add_listener(), с помощью которого можно подписаться на то или иное событие и повесить на него обработчик.
Events::add_listener('name.of.event', 'my_listener'); //подписываемся на событие name.of.event и вешаем на него функцию my_listener function my_listener($arg1,$arg2) { // ... здесь какой-то код }
На одно событие можно повесить и несколько обработчиков - просто вызвав несколько раз Events::add_listener. Второй параметр - это callback, поэтому мы можем использовать в качестве обработчиков методы классов, а начиная с PHP 5.3 - и безымянные функции.
// безымянная функция в качестве аргумента Events::add_listener('name.of.event', function($arg1, $arg2) { // ... здесь какой-то код });
Есть возможность указать в качестве обработчика функцию из еще не загруженного модуля.
// метод класса в качестве аргумента Events::add_listener('name.of.event', 'App.MyModule::listener');
В этом случае при вызове события модуль App.MyModule будет автоматически подгружен, и в нем будет вызван статический метод listener().
Отдельный вопрос - где располагать описание обработчиков. С технической стороны нет ограничений, соответственно вызов можно организовать в любом месте кода. Здесь важно придерживаться здравого смысла.
1. Регистрация события и реализация метода (функции), который будет вызван при наступлении события в одном месте.
Например, для вывода дополнительного поля в админке для списка записей, необходимо подписаться на событие nodus.admin.items.on_row. Для этого в описании дататайпа подпишемся на данное событие и здесь же, в классе дататайпа, опишем метод, реализующий вывод поля в списке.
// Nodus/app/Datatype/Cat/Type.php Events::add_listener( 'nodus.admin.items.on_row', 'Component.Nodus.App.Datatype.Cat.Type::on_row' ); class Component_Nodus_App_Datatype_Cat_Type extends Component_Nodus_Datatype implements Core_ModuleInterface { ... public static function on_row($row, $controller) { if ($row->datatype()->mnemocode() == 'cat') { $term = Component_Nodus::taxonomy_term($row->color); if ($term){ $row->color = $term->field('title'); } else{ $row->color = ''; } } } }
2. Вынесение регистрации события в конфигурационные настройки компонента.
Все события внутри компонента можно вынести и зарегистрировать в конфигурационных настройках (/ComponentName/config/component.php). Для этого зарезервирована специальная настройка events.
// Nodus/config/component.php return array( ... 'events' => array( 'nodus.admin.items.on_row' => array( Component_Nodus::datatype('cat'), 'on_row' ), ), );
3. Если событий много, правильнее будет, вообще вынести их в отдельный класс со всем описанием функций-обработчиков. Например, в папку app/lib/ проекта.
// app/lib/Events.php class App_Events implements Core_ModuleInterface { public static function initialize() { Events::add_listener('nodus.admin.items.on_row', array(Component_Nodus::datatype('cat'), 'on_row') ); } }
После этого не забываем подключить в index.php.
...
Core::load('App.Events');
...
CMS::Run();
Справочник событий ТАО
Событие | Передаваемые аргументы | Описание |
---|---|---|
cms.actions.dispatch($uri) ../tao/lib/CMS/Handlers.php | $uri - REQUEST_URI | Вызывается в методе run() перед началом диспетчеризации запроса. Обратившись к WS::env()->request, можно подменить что-либо в запросе, выполнить какие-либо действия, а также вернуть объект Net_HTTP_Response - в этом случае диспетчеризация даже не начнется, а будет использован возвращенный отклик. |
cms.fields.{form_name}.{field_name}.after($parms) cms.fields.admin.{$form_name}.{$field_name}.after($parms) ../tao/views/fields/layout-table.phtml | $parms - массив с дополнительной информацией о форме, поле, редактируемой сущности, исполняемом шаблоне | Вызывается в шаблоне layout-table после отрисовки поля средствами CMS.Fields. В качестве аргумента передается массив с дополнительной информацией. Применяется в случае, если нужно дополнить отображение поля. Например, подключить дополнительный скрипт или CSS, вывести рядом с полем дополнительную информацию или контролы. Для администратора такое же событие вызывается с именем: cms.fields.admin.{$form_name}.{$field_name}.after. |
cms.fspages.dirs($dirs) ../tao/lib/CMS/FSPages.php | $parms - массив с дополнительной информацией о форме, поле, редактируемой сущности, исполняемом шаблоне | Вызывается в шаблоне layout-table после отрисовки поля средствами CMS.Fields. В качестве аргумента передается массив с дополнительной информацией. Применяется в случае, если нужно дополнить отображение поля. Например, подключить дополнительный скрипт или CSS, вывести рядом с полем дополнительную информацию или контролы. Для администратора такое же событие вызывается с именем: cms.fields.admin.{$form_name}.{$field_name}.after. |
cms.fspages.realm($realm) ../tao/lib/CMS/Controller/FSPages.php | $realm - имя области | Событие генерируется механизмом статических страниц (CMS.FSPages) в методе route() для уточнения списка каталогов, в которых ищутся шаблоны. При необходимости в список можно добавить свой каталог. |
cms.initialize.ready ../tao/lib/CMS.php | Вызывается в конце инициализации метода initialize() при загрузке модуля CMS. | |
cms.initialize.start ../tao/lib/CMS.php | Вызывается в конце инициализации метода initialize() при загрузке модуля CMS. | |
cms.run ../tao/lib/CMS.php | Вызывается в методе before_run() после инициализации всех компонентов - в начале работы CMS::run(). | |
cms.vars.change($var) cms.vars.change.{$var_name}($var) ../tao/lib/CMS/Fields/Types/Image.php | $var - объект настройки перед сохранением $var_name - мнемокод настройки | Вызывается непосредственно перед сохранением отдельной настройки (CMS.Vars) в методе save_var(). Позволяет обработать данные прежде, чем они будут сохранены, сбросить кеш, сгенерировать еще что-то и т.п. Для обработки данных какой-то конкретной настройки необходимо вешать обработчик на событие вида cms.vars.change.{$var_name}. |
admin.change ../tao/lib/CMS/Fields/Types/Image.php | Вызывается в методе '''action_list()''' после определенных действий с записями (изменение, добавление, удаление, массовое изменение). Для методов action_add(), action_edit(), action_delete() в событие admin.change($item) в качестве аргумента передается объект записи в базу данных. | |
cms.table.access($action, $item) ../tao/lib/CMS/Controller/Table.php | $action - выполняемое действие (edit, add, delete и др.) $item - объект записи в таблице | Вызывается событие в методе access() для проверки доступа к какой-либо операции над объектом записи. Данное событие является общим для всех действий. Если необходимо вызвать событие для конкретной операции, то доступны события cms.tables.access.edit, cms.table.access.delete, cms.table.access.add и др. При определении своего метода типа '''action_имя_действия''' будет работать событие вида cms.table.access.имя_действия. |
cms.table.tabs($tab, $data, $action, $item) ../tao/lib/CMS/Controller/Table.php | $tab - имя вкладки $data - настройки вкладки из массива $form_tabs $action - выполняемое действие (edit, add, delete и др.) $item - объект записи в таблице | Событие вызывается в методе access_tab() и связано с проверкой доступа на отображение вкладки формы редактирования. |
cms.add_component($name, $mapper, $layout) ../tao/lib/CMS/Controller/Table.php | $name - имя компонента $mapper - экземпляр роутера $layout - шаблон обрамления | Вызывается при регистрации компонента в методе add_component() и позволяет внедрить требуемый функционал сразу после регистрации компонента в системе. |
cms.add_component_object($obj, $mapper, $layout) ../tao/lib/CMS.php | $obj - объект компонента $mapper - экземпляр роутера $layout - шаблон обрамления | Вызывается в методе add_component_object(). Позволяет внедрить требуемый функционал сразу после регистрации компонента в системе. |
cms.admin.layout.body.begin cms.admin.layout.body.end ../tao/views/layouts/admin.phtml | Вызываются в шаблоне админки соответственно в начале (сразу после тега BODY) и в конце тела шаблона (перед закрытием BODY), позволяя добавить что-либо. | |
core.find_all_modules($result) ../tao/lib/CMS.php | $result - массив со списком имен компонентов и путей к ним. Ключом выступают имена модулей, а значением физические пути к ним | Событие вызывается в методе find_all_modules() и позволяет внедрить какой-либо функционал перед тем, как будет возвращен массив значений. |
cms.load_components ../tao/lib/CMS.php | Событие вызывается в методе load_components() после загрузки всех подключенных компонентов. | |
cms.navigation.add($title, $item, $url) ../tao/lib/CMS/Navigation.php | $title - заголовок объекта записи (заголовок ссылки) $item - объект записи (пункт меню) $url - адрес ссылки | Событие вызывается в методе read_item(), в момент построения навигации. Позволяет подменить звено навигационного дерева «на лету» или вставить новое, или произвести необходимые изменения в объекте записи, добавить или удалить вложенную ссылку ($item['sub']). Параметры передаются по ссылке, поэтому если изменить непосредственно переменную $url, то ссылка поменяется. |
ws.response($response) ../tao/lib/WS.php | $response - сформированный объект отклика вэб-приложения | Вызывается в методе формирования отклика вэб-приложения process_response() в момент, когда объект отклика уже сформирован и готов к отправке. В событие передается объект отклика, который можно доработать. |
cms.fields.{$form_name}.{$name}.caption($caption, $rcaption) cms.fields.{$form_name}.caption($caption, $rcaption) ../tao/lib/CMS/Fields.php | $caption - заголовок поля $rcaption - заголовок поля (с правой стороны) | Вызывается в методе перед отрисовкой поля формы layout_preprocess(). Может использоваться как для конкретного поля конкретной формы, так и для всех полей конкретной формы. |
cms.fields.upload($name, $data, $file, $new) cms.fields.{$name}.upload($data, $file, $new) ../tao/lib/CMS/Fields.php | $name - имя поля $data - массив настроек поля $file - массив из $_FILES $new - путь к файлу под которым он будет сохранен | Вызывается событие при закачивании файла в методе upload_file() для таких полей как image, attaches, gallery. Событие сработает в ситуации, когда метод вернет данные, отличные от null или true. В этот момент закачивание будет прервано. |
cms.fields.{$form->name}.validation.js($validation_js) ../tao/views/fields/layout-table.phtml | $validation_js - скрипт валидации полей {$form->name} - имя формы | Вызывается в шаблоне формы перед запуском стандартного скрипта валидации полей. Подписавшись на событие, можно подменить скрипт на кастомизированный. И таким образом, например, добавить валидацию по дополнительным полям. |
cache.delete($key) ../tao/lib/Cache/Backend/Dummy.php | key - ключ | Вызывается при удалении кэша по ключу в методе delete(). |
cache.flush ../tao/lib/Cache/Backend/Dummy.php | Не имеет аргументов | Вызывается при инвалидизации кеша в методе flush(). |
cache.has($key) ../tao/lib/Cache/Backend/Dummy.php | $key - ключ | Вызывается в методе has(). |
cms.insertions.gallery.config($config) ../tao/views/insertions/gallery.phtml | $config - массив настроек | Событие вызывается в шаблоне вставки галереи. Позволяет изменить установленные или добавить новые настройки вывода изображений. |
db.schema.execute($data) db.schema.execute($data['name'], $data) ../tao/lib/DB/Schema.php | $data - массив DB.Schema $data['name'] - имя таблицы | Вызывается при обработке DB.Schema в методе execute() перед изменением данных. Позволяет добавить поля, столбцы в таблицу, внести какие-то изменения. Для конкретной таблицы необходимо передать ее имя в качестве аргумента($data['name']). |
db.schema.after_execute($data) db.schema.after_execute($data['name'], $data) ../tao/lib/DB/Schema.php | $data - массив DB.Schema $data['name'] - имя таблицы | Вызывается при обработке DB.Schema в методе execute() после изменения данных. Позволяет добавить поля, столбцы в таблицу, внести какие-то изменения. Для конкретной таблицы необходимо передать ее имя в качестве аргумента($data['name']). |
templates.assets.postprocess($path, $data, $content) ../tao/lib/Templates/HTML/Assets.php | $path - путь к формируемому файлу $data - массив параметров $content - содержимое файла | Событие вызывается при подключении css- или js-файла в методе postprocess(). Позволяет добавить какую-либо обработку после того, как список сформирован. |
templates.assets.preprocess($path, $data, $content) ../tao/lib/Templates/HTML/Assets.php | $path - путь к формируемому файлу $data - массив параметров $content - содержимое файла | Событие вызывается при подключении css- или js-файла в методе preprocess(). Позволяет добавить какую-либо обработку перед формированием списка файлов. |
templates.partial($__name, $__params) ../tao/lib/Templates/HTML.php | $__name - имя шаблона $__params - массив параметров шаблона | Вызывается при формировании шаблона. |
cms.insertions.calendar.setup($router,$orm,$cache) cms.insertions.calendar.{$component}.setup($router,$orm,$cache) ../tao/views/insertions/calendar.phtml | $router $orm $cache $component - произвольный идентификатор для именования процесса обработки | Вызывается перед отрисовкой календаря. Позволяет добавить необходимый функционал. |
cms.calendar.is_holiday($d,$holiday)../tao/views/insertions/calendar.phtml | $d $holiday | Вызывается перед отрисовкой каледаря. Позволяет назначить определенные дни выходными. |