Методы расширения кода
Хуки и фильтры
Хуки используются для написания плагинов и бывают двух видов:
- Хуки - нужны для того, чтобы к ним прикреплять 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 блоки дополнения в файлы шаблоны тем или модулей посредством специальных комментариев (тегов).