Методы расширения кода
Хуки и фильтры
Хуки используются для написания плагинов и бывают двух видов:
- Хуки - нужны для того, чтобы к ним прикреплять php функции. Затем эти функции будут срабатывать в момент срабатывания хука.
- Фильтры - нужны, чтобы отфильтровать передаваемое значение, т.е. фильтр получает значение и обязательно должен его вернуть (изменённое или нет).
В функции прикрепленные к хукам и фильтрам могут передаваться дополнительные данные на основе которых можно создавать или же дополнять какую-либо логику действий.
Пример хука встречаемого в коде:
public function processPayRequest()
{
$paySystem = $this->input->get('psystem', TYPE_NOTAGS);
bff::hook('bills.pay.process', $paySystem);
...
В место вызова функции bff::hook можно добавить свой код, а вернее функцию расширяющую/меняющую логику работы. Для того чтобы это сделать вам необходимо написать следующий код:
<?php
bff::hookAdd('bills.pay.process', function($paySystem){
// собственный код
});
Обратите внимание на общий ключ 'bills.pay.process', он то и связывает данный код. Также в созданной вами функции доступны дополнительные параметры, в примере это $paySystem.
Пример фильтра встречаемого в коде:
protected function getContactTypes($options = false)
{
$types = bff::filter('contacts.types.list', array(
self::TYPE_SITE_ERROR => array('title' => _t('contacts', 'Ошибка на сайте')),
self::TYPE_TECH_SUPPORT => array('title' => _t('contacts', 'Технический вопрос')),
self::TYPE_OTHER => array('title' => _t('contacts', 'Другие вопросы')),
));
...
Обратите внимание на обвертку bff::filter(...); Она позволяет выполнять дополнительную фильтрацию данных, в данном примере список типов сообщения в форме контактов.
Для того чтобы это сделать напишем следующий код:
<?php
bff::hookAdd('contacts.types.list', function($list){
# Добавляем новые пункты в список:
$list[] = _t('contacts', 'Блокировка и модерация');
$list[] = _t('contacts', 'Платные услуги');
$list[] = _t('contacts', 'Реклама на сайте');
# Переносим тип "Другие вопросы" в конец списка:
$list[Contacts::TYPE_OTHER]['priority'] = 1000;
return $list;
});
Снова видим общий ключ 'contacts.types.list' выполняющий связующую функцию.
Также в созданный нами фильтр первым параметром передаются данные, после обработки и изменения которых их обязательно нужно вернуть обратно, что и было сделано последней строкой return $list;.
При этом если в функцию передается больше данных, обрабатывается из них всегда только первый, остальные вспомогательные и призваны дополнить картину (контекст вызова).
Расширение классов посредством плагинов
У плагина есть возможность расширять классы модулей (моделей или компонентов) + компонентов ядра, поддержка расширения которых заложена, определить это можно по наличию завершающего символа подчеркивания _ в названии класса. Пример расширения:
// код объявленный в функции start плагина
bff::classExtension('Site_', 'Plugin_Example_Site_Admin', $this->path('site.admin.php'), true);
// код содержимого файла site.admin.php
<?php
class Plugin_Example_Site_Admin extends Plugin_Example_Site_Admin_Base
{
}
- В примере был расширен класс admin контроллера модуля Site для этого была вызвана функция
bff::classExtension - Первым параметром в которой указывается оригинальное название класса объявленного в файле /modules/site/site.adm.class.php
- Далее идет название класса расширения, в примере это
Plugin_Example_Site_Admin, название класса может быть любым уникальным названием, рекомендуем использовать в качестве префикса название самого класса плагина, в примере этоPlugin_Example_. - Далее идет путь к файлу плагина в котором выполняется его объявление, в данном случае указан путь к файлу
site.admin.phpрасположенному в директории плагина - В объявлении класса, как видите, есть базовый класс от которого он наследуется, именование данного класса должно состоят из имени объявляемого класса и завершающего
_Base, в примере этоPlugin_Example_Site_Admin+_Base - В конечном итоге данное действие равносильно следующему порядку наследования:
Site_=>Plugin_Example_Site_Admin=>Site. В центральной части данной цепочки может быть задействовано больше участников, поскольку один и тот же класс могут расширять несколько плагинов, порядок определяется порядком их подключения. -
Важно понимать что названия контроллер-классов модулей (например
Users_) одинаково для фронтенда и админ. панели, поэтому следует всегда указывать какой именно контроллер требуется расширить. - Обращаться к методам модулей проекта в методе
startплагина/темы следует только посредством хуков, иначе это может нарушить порядок расширения классов данного модуля.
Модификация файлов
Также есть возможность вносить изменения в заданные строки файлов модулей и ядра, для этого необходимо создать специальный файл с названием mods.php в корне директории плагина, который должен возвращать массив инструкций модификации.
Под изменением файлов в таком формате понимается создание копии исходного файла, после чего в копию вносятся описанные при помощи инструкций изменения, а система на этапе обращения к оригинальному файлу будет подключать файл-копию, таким образом можно добиться модификации файлов не затрагивая их исходный вариант.
Пример содержания файла mods.php:
<?php
return array(
array(
'file' => '/modules/site/site.class.php',
'search' => 'public function index()',
'replace' => $this->path('mods/site.index.php'),
'replace-file' => true,
'position' => 'after',
'offset' => 1,
'index' => 1,
),
);
Опишем его подробнее:
-
file- в примере выполняется модификация исходного файла/modules/site/site.class.php -
search- в файле выполняется поиск строки с текстомpublic function index() -
replace- код для вставки берется из файлаmods/site.index.phpрасположенного в директории плагина, о том что был указан именно путь к файлу сообщает настройка'replace-file' => true. Также здесь можно указать просто текст для замены. -
position- будет выполняться вставка после найденной строки -
offset- вставка будет выполнятся с пропуском одной строки после строки поискаsearch -
index- действие будет выполняться только для первой найденной строки (для случая если таких в исходном файле найдется несколько)
Описание допустимых параметров:
-
file-string,array- путь к файлу относительно корня проекта, или же массив, позволяющий указывать путь к нескольким файлам -
search-string- строка поиска или уникальный текст из строки, которую необходимо модифицировать или использовать в качестве отправной точки (якоря). Рекомендуем использовать максимально уникальную строку. -
replace-string- строка для замены или же путь к файлу -
replace-file-bool- в значенииtrueсообщает что полеreplaceуказывает на путь к файлу с текстом для замены; по-умолчанию:false -
position-string- позиция (действие) относительно строки поиска:before- вставить перед,after- вставить после,replace- замена найденной строки (подстроки),replace-line- подмена найденной строки полностью -
offset-int- кол-во строк которые следует отступить от найденной строки; по-умолчанию:0; применимо для всех позиций кромеreplace-line -
index-int, array- индекс строки поиска, в случае если в файле несколько одинаковых строк, например если их 5 и вы указали2только вторая по счету найденная строка будет заменена (модифицирована); по-умолчанию:0 -
regexp-bool- строка поискаsearchявляется регулярным выражением; по-умолчанию:false -
ignore-if-string- строка в файле, в случае нахождения которой, модификация файла выполняться не будет -
ignore-if-regexp-boolстрока является регулярным выражением; по-умолчанию:false
Копии файлов хранятся в директории /custom/mods/.
Настройки модификации применяются и кешируются при включении/выключении плагина в админ. панели, для тестирования на этапе разработки следует использовать debug-режим.
Также в режиме разработчика доступна возможность принудительной пересборки модификаторов с развернутым описанием порядка их применения, статуса и принадлежности к плагину/теме.
Альтернативой применения модификаторов являются блоки, с их помощью можно интегрировать HTML блоки дополнения в файлы шаблоны тем или модулей посредством специальных комментариев (тегов).