has($key)) { for ($p = 0; $p <= static::PRIORITY_LIMIT; $p++) { if (!empty($this->data[$key][$p])) { foreach ($this->data[$key][$p] as $c) { call_user_func_array($c, $args); } } } } } /** * Применение хука * @param string $key ключ * @return mixed */ public function apply(string $key) { $args = func_get_args(); array_shift($args); $content = $args[0] ?? ''; if ($this->has($key)) { for ($p = 0; $p <= static::PRIORITY_LIMIT; $p++) { if (!empty($this->data[$key][$p])) { foreach ($this->data[$key][$p] as $c) { if (is_callable($c)) { $content = call_user_func_array($c, $args); $args[0] = $content; } } } } } return $content; } /** * Добавление хука * @param string $key ключ * @param callable $callable функция обработчик * @param int|null $priority приоритет вызова * @return Hook|bool */ public function add(string $key, callable $callable, ?int $priority = 5) { $key = trim(strval($key)); if ($callable instanceof Closure) { $callable = new Hook($callable); } if ($this->has($key)) { foreach ($this->data[$key] as $hooks) { foreach ($hooks as $c) { if ($c == $callable) { return false; # уже существует } } } } if (is_null($priority) || $priority < 0) { $priority = 5; } $this->data[$key][$priority][] = $callable; return $callable; } /** * Добавление хуков пакетно * @param array $hooks хуки: * [ * 'ключ хука' => значение, * 'ключ хука' => array, * 'ключ хука' => функция обработчик, * ] * @return array */ public function addMany(array $hooks = []): array { if (empty($hooks) || ! is_array($hooks)) { return []; } $result = []; foreach ($hooks as $key => $value) { if (is_string($key)) { if ($value instanceof Closure) { $result[$key] = $this->add($key, $value); } elseif (is_scalar($value)) { $result[$key] = $this->add($key, function () use ($value) { return $value; }); } elseif (is_array($value)) { $result[$key] = $this->add($key, function ($data) use ($value) { foreach ($value as $k => $v) { if (isset($data[$k]) && is_array($v)) { foreach ($v as $kk => $vv) { $data[$k][$kk] = $vv; } } else { $data[$k] = $v; } } return $data; }); } } } return $result; } /** * Удаление хука * @param string $key ключ * @param callable $callable функция обработчик * @return bool */ public function remove(string $key, callable $callable): bool { if ($this->has($key)) { if ($callable instanceof Closure) { $callable = new Hook($callable); } foreach ($this->data[$key] as $p => &$hooks) { foreach ($hooks as $k => $c) { if ($c == $callable) { unset($hooks[$k], $hooks); if (empty($this->data[$key][$p])) { unset($this->data[$key][$p]); } return true; } } } } return false; } /** * Проверка наличия хука * @param string $key ключ * @return bool */ public function has(string $key): bool { return !empty($this->data[$key]); } ## Доступные хуки и фильтры: /** * Хук: Событие инициализации приложения * @see \bff\base\Application::init * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function appInit(callable $callback, ?int $priority = null) { return $this->add('app.init', $callback, $priority); } /** * Расширение списка middleware (посредников) приложения в методе {@see bff::init()} * @param callable|string $callable замыкание или название класса с реализованным методом __invoke * @param array $options доп. опции { * int 'priority' приоритет запуска посредника * bool|null 'admin' выполнять запуск посредника в админ. панели * } * @return Hook */ public function appMiddleware($callable, array $options = []) { return $this->add('app.middleware', function ($list) use ($callable, $options) { $list[] = array_merge(['callback' => $callable], $options); return $list; }); } /** * Хук: Событие инициализации модуля * @param string $module название модуля * @param callable $callback { * @callback-param {@see \Module} $object объект модуля * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleInit(string $module, callable $callback, ?int $priority = null) { return $this->add($module . '.init', $callback, $priority); } /** * Фильтр: Список крон задач модуля * @param string $module название модуля * @param callable $callback { * @callback-param array $tasks список задач модуля * @callback-param {@see \Module} $object объект модуля * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleCronSettings(string $module, callable $callback, ?int $priority = null) { return $this->add('cron.settings.module.' . $module, $callback, $priority); } /** * Фильтр: Список шаблонов писем модуля * @param string $module название модуля * @param callable $callback { * @callback-param array $templates список шаблонов модуля * @callback-param {@see \Module} $object объект модуля * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleSendmailTemplates(string $module, callable $callback, ?int $priority = null) { return $this->add('sendmail.templates.module.' . $module, $callback, $priority); } /** * Фильтр: Список системных настроек модуля * @param string $module название модуля * @param callable $callback { * @callback-param array $settings дополнительные системные настройки * @callback-param {@see \Module} $object объект модуля * @callback-return array настройки * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleSettingsSystem(string $module, callable $callback, ?int $priority = null) { return $this->add('site.settings.system.extra.' . $module, $callback, $priority); } /** * Фильтр: настройки компонента {@see \bff\db\Publicator} инициализируемого в модуле * @param string $module название модуля * @param callable $callback { * @callback-param array $settings настройки компонента * @callback-param {@see \bff\db\Publicator} $object объект компонента * @callback-return array настройки компонента * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleSettingsPublicator(string $module, callable $callback, ?int $priority = null) { return $this->add('publicator.settings.' . $module, $callback, $priority); } /** * Фильтр: Список локализируемых таблиц и полей модуля * @param string $module название модуля * @param callable $callback { * @callback-param array $list список * @callback-param {@see \Module} $object объект модуля * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleLocaleTables(string $module, callable $callback, ?int $priority = null) { return $this->add('locale.tables.' . $module, $callback, $priority); } /** * Фильтр: Список роутов модуля, в случае вызова метода {@see bff::route()} в рамках модуля * @param string $module название модуля * @param callable $callback { * @callback-param array $list список роутов * @callback-param array $options дополнительные опции * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleRoutes(string $module, callable $callback, ?int $priority = null) { if (!empty($module)) { return $this->add($module . '.routes', $callback, $priority); } return $this->routes($callback, $priority); } /** * Фильтр: Формирования ссылок модулeм (метод url() модуля) * @param string $module название модуля * @param callable $callback { * @callback-param string $url сформированный URL ссылки * @callback-param array $data параметры ссылки { * string 'key' ключ * array 'opts' доп. параметры * bool 'dynamic' динамическая ссылка * string 'base' базовый URL * } * @callback-return string URL ссылки * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleUrl(string $module, callable $callback, ?int $priority = null) { return $this->add($module . '.url', $callback, $priority); } /** * Фильтр: Пост-обработка шаблонов модуля * @see \bff\base\View::render() * @param string $module название модуля * @param string $template название файла шаблона модуля (без расширения) * @param callable $callback { * @callback-param string $content сформированный HTML шаблон * @callback-param array $data данные передаваемые в шаблон * @callback-param array $extra { * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * @callback-return string HTML шаблон * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleViewTemplate(string $module, string $template, callable $callback, ?int $priority = null) { return $this->add('view.module.' . $module . '.' . $template, $callback, $priority); } /** * Хук: Предварительная обработка данных шаблонов модуля * @see \bff\base\View::render() * @param string $module название модуля * @param string $template название файла шаблона модуля (без расширения) * @param callable $callback { * @callback-param array $view { * array 'data' @ref данные передаваемые по ссылке * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function moduleViewTemplateData(string $module, string $template, callable $callback, ?int $priority = null) { return $this->add('view.module.' . $module . '.' . $template . '.data', $callback, $priority); } /** * Хук: Событие инициализации плагина (перед вызовом метода start) * @param string $plugin название плагина * @param callable $callback { * @callback-param {@see \Plugin} $object объект плагина * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginInit(string $plugin, callable $callback, ?int $priority = null) { return $this->add('plugins.init.' . $plugin, $callback, $priority); } /** * Хук: Событие старта плагина (сразу после вызова метода start()) * @param string $plugin название плагина * @param callable $callback { * @callback-param {@see \Plugin} $object объект плагина * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginStart(string $plugin, callable $callback, ?int $priority = null) { return $this->add('plugins.start.' . $plugin, $callback, $priority); } /** * Фильтр: Список крон задач плагина * @param string $plugin название плагина * @param callable $callback { * @callback-param array $tasks список задач плагина * @callback-param {@see \Plugin} $object объект плагина * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginCronSettings(string $plugin, callable $callback, ?int $priority = null) { return $this->add('cron.settings.plugin.' . $plugin, $callback, $priority); } /** * Фильтр: Список шаблонов писем плагина * @param string $plugin название плагина * @param callable $callback { * @callback-param array $templates список шаблонов плагина * @callback-param {@see \Plugin} $object объект плагина * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginSendmailTemplates(string $plugin, callable $callback, ?int $priority = null) { return $this->add('sendmail.templates.plugin.' . $plugin, $callback, $priority); } /** * Фильтр: Список табов формы настроек плагина (админ. панель) * @param string $plugin название плагина * @param callable $callback { * @callback-param array $tabs список названий пунктов меню * @callback-param {@see \Plugin} $plugin объект плагина * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginSettingsTabs(string $plugin, callable $callback, ?int $priority = null) { return $this->add('extensions.plugins.' . $plugin . '.settings.tabs', $callback, $priority); } /** * Хук: Расширение содержимого табов формы настроек плагина (админ. панель) * @param string $plugin название плагина * @param callable $callback { * @callback-param array $data { * array 'settings' @ref настройки плагина * array 'tabs' табы формы * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginSettingsTabsContent(string $plugin, callable $callback, ?int $priority = null) { return $this->add('extensions.plugins.' . $plugin . '.settings.tabs.content', $callback, $priority); } /** * Фильтр: Список роутов плагина, в случае вызова метода {@see bff::route()} в рамках плагина * @param string $plugin название плагина * @param callable $callback { * @callback-param array $list список роутов * @callback-param array $options дополнительные опции * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginRoutes(string $plugin, callable $callback, ?int $priority = null) { return $this->add($plugin . '.routes', $callback, $priority); } /** * Фильтр: Пост-обработка шаблонов плагина * @see \bff\base\View::render() * @param string $plugin название плагина * @param string $template название файла шаблона плагина (без расширения) * @param callable $callback { * @callback-param string $content сформированный HTML шаблон * @callback-param array $data данные передаваемые в шаблон * @callback-param array $extra { * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * @callback-return string HTML шаблон * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginViewTemplate(string $plugin, string $template, callable $callback, ?int $priority = null) { return $this->add('view.plugin.' . $plugin . '.' . $template, $callback, $priority); } /** * Хук: Предварительная обработка данных шаблонов плагина * @see \bff\base\View::render() * @param string $plugin название плагина * @param string $template название файла шаблона плагина (без расширения) * @param callable $callback { * @callback-param array $view { * array 'data' @ref данные передаваемые по ссылке * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function pluginViewTemplateData(string $plugin, string $template, callable $callback, ?int $priority = null) { return $this->add('view.plugin.' . $plugin . '.' . $template . '.data', $callback, $priority); } /** * Фильтр: Список табов формы настроек темы (админ. панель) * @param string $theme название темы * @param callable $callback { * @callback-param array $tabs список названий пунктов меню * @callback-param {@see \Theme} $theme объект темы * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function themeSettingsTabs(string $theme, callable $callback, ?int $priority = null) { return $this->add('extensions.themes.' . $theme . '.settings.tabs', $callback, $priority); } /** * Хук: Расширение содержимого табов формы настроек темы (админ. панель) * @param string $theme название темы * @param callable $callback { * @callback-param array $data { * array 'settings' @ref настройки темы * array 'tabs' табы формы * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function themeSettingsTabsContent(string $theme, callable $callback, ?int $priority = null) { return $this->add('extensions.themes.' . $theme . '.settings.tabs.content', $callback, $priority); } /** * Фильтр: Пост-обработка общих шаблонов (из директории /tpl/) * @see \bff\base\View::render() * @param string $template название файла общего шаблона (без расширения) * @param callable $callback { * @callback-param string $content сформированный HTML шаблон * @callback-param array $data данные передаваемые в шаблон * @callback-param array $extra { * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * @callback-return string HTML шаблон * } * @param int|null $priority приоритет вызова * @return Hook */ public function viewTemplate(string $template, callable $callback, ?int $priority = null) { return $this->add('view.tpl.' . $template, $callback, $priority); } /** * Хук: Предварительная обработка данных общих шаблонов (из директории /tpl/) * @see \bff\base\View::render() * @param string $template название файла общего шаблона (без расширения) * @param callable $callback { * @callback-param array $view { * array 'data' @ref данные передаваемые по ссылке * string 'filePath' путь к подключаемому файлу * string 'fileName' имя файла с расширением * bool 'theme' подключается ли файл темы * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function viewTemplateData(string $template, callable $callback, ?int $priority = null) { return $this->add('view.tpl.' . $template . '.data', $callback, $priority); } /** * Событие инициализации блока/страницы * @param string $blockClass класс блока * @param callable $callback { * @callback-param {@see Block} $block объект блока * } * @param int|null $priority приоритет вызова * @return Hook */ public function onBlockInit(string $blockClass, callable $callback, ?int $priority = null) { return $this->add('view.block.init', function ($block) use ($blockClass, $callback) { if ($block instanceof $blockClass) { $callback($block); } }, $priority); } /** * Событие формирования данных блока/страницы * @param string $blockClass класс блока * @param callable $callback { * @callback-param {@see Block} $block объект блока * } * @param int|null $priority приоритет вызова * @return Hook */ public function onBlockData(string $blockClass, callable $callback, ?int $priority = null) { return $this->add('view.block.data', function ($block, $params) use ($blockClass, $callback) { if ($block instanceof $blockClass) { $callback($block, $params); } }, $priority); } /** * Событие рендеринга блока/страницы (фильтр) * @param string $blockClass класс блока * @param callable $callback { * @callback-param string $content контент блока * @callback-param {@see Block} $block объект блока * @callback-return string * } * @param int|null $priority приоритет вызова * @return Hook */ public function onBlockRender(string $blockClass, callable $callback, ?int $priority = null) { return $this->add('view.block.render', function ($content, $block) use ($blockClass, $callback) { if ($block instanceof $blockClass) { return $callback($content, $block); } return $content; }, $priority); } /** * Фильтр: Обработка формирования секции блока * @see \bff\base\View::section() * @param string $blockClass класс блока * @param string $sectionId ID секции * @param callable $callback { * @callback-param string $content содержимое секции * @callback-param {@see Block}|object $object объект блока (формирующего секцию) * @callback-return string итоговое содержимое секции * } * @param int|null $priority приоритет вызова * @return Hook */ public function onBlockSection(string $blockClass, string $sectionId, callable $callback, ?int $priority = null) { return $this->add('view.section.' . $sectionId, function ($content, $block) use ($callback, $blockClass) { if ($block instanceof $blockClass) { return call_user_func($callback, $content, $block); } return $content; }, $priority); } /** * Событие админ списка * @param string $listId id списка * @param string $event ключ события: init, inited, ... * @param callable $callback { * @callback-param {@see BlockList} $list объект списка * @callback-param array $data данные события * } * @param int|null $priority приоритет вызова * @return Hook */ public function onAdminListEvent(string $listId, string $event, callable $callback, ?int $priority = null) { return $this->add($listId . '.admin.list.' . $event, $callback, $priority); } /** * Событие админ формы * @param string $formId id формы * @param string $event ключ события: init, inited, ... * @param callable $callback { * @callback-param {@see Form} $form объект формы * @callback-param array $data данные события * } * @param int|null $priority приоритет вызова * @return Hook */ public function onAdminFormEvent(string $formId, string $event, callable $callback, ?int $priority = null) { return $this->add($formId . '.admin.form.' . $event, $callback, $priority); } /** * Фильтр: Список роутов проекта * @see \bff\base\Application::routes * @param callable $callback { * @callback-param array $list список роутов * @callback-param array $options дополнительные опции * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function routes(callable $callback, ?int $priority = null) { return $this->add('routes', $callback, $priority); } /** * Фильтр: Результат возвращаемого обработчиком роута * @param string|array $id ID роута|нескольких роутов * @param callable $callback { * @callback-param mixed $response результат возвращаемый обработчиком роута * @callback-param array $route данные роута * @callback-param {@see \Psr\Http\Message\ServerRequestInterface} $request объект запроса * @callback-return mixed $response * } * @param int|null $priority приоритет вызова * @return Hook|Hook[]|void */ public function routeAfter($id, callable $callback, ?int $priority = null) { if (is_string($id)) { return $this->add('routing.route.run.after.' . $id, $callback, $priority); } elseif (is_array($id)) { $return = []; foreach ($id as $k) { if (is_string($k)) { $return[$k] = $this->add('routing.route.run.after.' . $k, $callback, $priority); } } return $return; } } /** * Фильтр: Список определяющий порядок основных разделов меню в панели управления * @see \AdminMenu::build() * @param callable $callback { * @callback-param array $tabs список названий пунктов меню * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function adminMenuTabs(callable $callback, ?int $priority = null) { return $this->add('admin.menu.tabs', $callback, $priority); } /** * Хук: событие завершения формирования списка меню в admin-панели * @see \AdminMenu::build() * @param callable $callback { * @callback-param {@see \AdminMenu} $object * } * @param int|null $priority приоритет вызова * @return Hook */ public function adminMenuBuild(callable $callback, ?int $priority = null) { return $this->add('admin.menu.build', $callback, $priority); } /** * Фильтр: Список пунктов со счетчиками в шапке в admin-панели * @param callable $callback { * @callback-param array $list список * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function adminMenuHeaderCounters(callable $callback, ?int $priority = null) { return $this->add('admin.menu.header.counters', $callback, $priority); } /** * Фильтр: Список пунктов меню в выпадающем списке пользователя в правом верхнем углу в admin-панели * @param callable $callback { * @callback-param array $list список * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function adminMenuHeaderUser(callable $callback, ?int $priority = null) { return $this->add('admin.menu.header.user', $callback, $priority); } /** * Хук: Подключение дополнительных javascript файлов * @param bool $frontend true - фронтенд, false - панель управления * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function javascriptExtra(?bool $frontend, callable $callback, ?int $priority = null) { return $this->add(($frontend ? '' : 'admin.') . 'js.extra', $callback, $priority); } /** * Фильтр: Список подключенных javascript файлов * @param bool $frontend true - фронтенд, false - панель управления * @param callable $callback { * @callback-param array $list список файлов * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function javascriptIncludes(?bool $frontend, callable $callback, ?int $priority = null) { return $this->add(($frontend ? '' : 'admin.') . 'js.includes', $callback, $priority); } /** * Фильтр: Список фраз локализации передаваемых в javascript объекта app (frontend) * @param callable $callback { * @callback-param array $list список фраз * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function javascriptAppLang(callable $callback, ?int $priority = null) { return $this->add('js.app.lang', $callback, $priority); } /** * Хук: Подключение дополнительных CSS файлов * @param bool $frontend true - фронтенд, false - панель управления * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function cssExtra(?bool $frontend, callable $callback, ?int $priority = null) { return $this->add(($frontend ? '' : 'admin.') . 'css.extra', $callback, $priority); } /** * Фильтр: Список подключенных CSS файлов * @param bool $frontend true - фронтенд, false - панель управления * @param callable $callback { * @callback-param array $list список файлов * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function cssIncludes(?bool $frontend, callable $callback, ?int $priority = null) { return $this->add(($frontend ? '' : 'admin.') . 'css.includes', $callback, $priority); } /** * Register ip location provider * @param IpLocationProvider|Closure|string $provider * @param int|null $priority * @return mixed */ public function ipLocationProviderRegister($provider, ?int $priority = null) { return Providers::register('geo.ip.location.providers', $provider, $priority); } /** * Register maps provider * @param MapsProvider|Closure|string $provider * @param int|null $priority * @return mixed */ public function geoMapsProviderRegister($provider, ?int $priority = null) { return Providers::register('geo.maps.providers', $provider, $priority); } /** * Register geocode provider * @param GeocodeProvider|Closure|string $provider * @param int|null $priority * @return mixed */ public function geoGeocodeProviderRegister($provider, ?int $priority = null) { return Providers::register('geo.geocode.providers', $provider, $priority); } /** * Register translation provider * @param TranslationProvider|Closure|string $provider * @param int|null $priority * @return mixed */ public function localeTraslationProviderRegister($provider, ?int $priority = null) { return Providers::register('locale.traslation.providers', $provider, $priority); } /** * Register payment system * @param PaymentProvider|Closure|string $pay * @param int|null $priority * @return mixed */ public function billsPaymentProviderRegister($pay, ?int $priority = null) { return Providers::register('bills.payment.providers.list', $pay, $priority); } /** * Хук: Событие сабмита формы пополнения счета * @see \Bills::my_pay() * @param callable $callback { * @callback-param float $amount сумма указанная пользователем * @callback-param string $paySystem ключ системы оплаты * @callback-param array $pay сумма к оплате { * float 'amount' сумма * int 'currency' ID валюты * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function billsPaySubmit(callable $callback, ?int $priority = null) { return $this->add('bills.pay.submit', $callback, $priority); } /** * Хук: событие успешной оплаты * @see \Bills::success() * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function billsPaySuccess(callable $callback, ?int $priority = null) { return $this->add('bills.pay.success', $callback, $priority); } /** * Хук: событие ошибки/отмены оплаты * @see \Bills::fail() * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function billsPayFail(callable $callback, ?int $priority = null) { return $this->add('bills.pay.fail', $callback, $priority); } /** * Хук: событие результирующего метода оплаты (требуется для некоторых систем оплаты) * @see \Bills::result() * @param callable $callback * @param int|null $priority приоритет вызова * @return Hook */ public function billsPayResult(callable $callback, ?int $priority = null) { return $this->add('bills.pay.result', $callback, $priority); } /** * Фильтр: Список статусов счета * @see \Bills::getStatusData() * @param callable $callback { * @callback-param array $list список доступных статусов * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function billsStatusList(callable $callback, ?int $priority = null) { return $this->add('bills.status.list', $callback, $priority); } /** * Фильтр: Настройки отправки почты * @param callable $callback { * @callback-param array $settings настройки почты * @callback-return array настройки * } * @param int|null $priority приоритет вызова * @return Hook */ public function mailConfig(callable $callback, ?int $priority = null) { return $this->add('mail.config', $callback, $priority); } /** * Фильтр: Данные письма перед отправкой * @param callable $callback { * @callback-param array $data данные о письме { * string 'to' @ref email получателя * string 'from' @ref email отправителя или пустая строка * string 'fromName' @ref имя отправителя или пустая строка * string 'body' @ref текст письма * string 'subject' @ref заголовок письма * array 'customHeaders' @ref доп. заголовки письма * } * @callback-return array данные, * если указан ответ в формате ['sended'=>any value], стандартная отправка письма не выполняется * } * @param int|null $priority приоритет вызова * @return Hook */ public function mailSend(callable $callback, ?int $priority = null) { return $this->add('mail.send', $callback, $priority); } /** * Фильтр: Данные шаблона письма перед отправкой * @param callable $callback { * @callback-param array $data данные о шаблоне письма { * string 'to' email получателя * string 'from' email отправителя или пустая строка * string 'fromName' имя отправителя или пустая строка * string 'body' текст письма * string 'subject' заголовок письма * bool 'is_html' используется HTML шаблон письма * int 'wrapper_id' ID шаблона письма * array 'vars' @ref данные подставляемые в шаблон '{макрос}' => 'значение' * string 'lang' ключ языка шаблона * array 'customHeaders' @ref доп. заголовки письма * } * @callback-param string $templateName название шаблона * @callback-return array данные, если указан ответ в формате true/false, стандартная отправка письма не выполняется * } * @param int|null $priority приоритет вызова * @return Hook */ public function mailSendTemplate(callable $callback, ?int $priority = null) { return $this->add('mail.send.template', $callback, $priority); } /** * Хук: Отправка почты (сразу после отправки письма) * @param callable $callback { * @callback-param array $data данные об отправке { * 'to', 'subject', 'body', 'from', 'fromName', * 'result' результат отправки, * 'time' время отправки * } * @callback-param {@see \CMail} $object объект компонента отправки почты * } * @param int|null $priority приоритет вызова * @return Hook */ public function mailSended(callable $callback, ?int $priority = null) { return $this->add('mail.sended', $callback, $priority); } /** * Регистрация SMS провайдера * @param SmsProvider|Closure|string $provider объект SmsProvider * @param int|null $priority * @return mixed */ public function sendmailSmsProviderRegister($provider, ?int $priority = null) { return Providers::register('sendmail.sms.providers.list', $provider, $priority); } /** * Фильтр: Список meta-данных выводимых в блоке * @see \SEO::metaRender * @param callable $callback { * @callback-param array $view список meta-данных * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function seoMetaRender(callable $callback, ?int $priority = null) { return $this->add('seo.meta.render', $callback, $priority); } /** * Фильтр: Подстановка SEO макросов в текст * @see \SEO::metaTextPrepare * @param callable $callback { * @callback-param string|array $text SEO текст или список текстов * @callback-param array $data доп. параметры { * 'replace' ссылка на список замены с => на, * 'macrosData' ссылка на данные подставляемые вместо макросов * } * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function seoMetaTextPrepare(callable $callback, ?int $priority = null) { return $this->add('seo.meta.text.prepare', $callback, $priority); } /** * Фильтр: Данные передаваемые в Sitemap.xml * @see \SEO::cronSitemapXML() * @param callable $callback { * @callback-param array $data данные в формате callback-списка * @callback-return array список * } * @param int|null $priority приоритет вызова * @return Hook */ public function siteCronSitemapXML(callable $callback, ?int $priority = null) { return $this->add('site.cron.sitemapXML', $callback, $priority); } /** * Фильтр: Дополнительная проверка наличия email адреса в списке запрещенных (временных адресов) (isEmailTemporary) * @param callable $callback { * @callback-param bool $isTemporary был помечен системой как временный (true), не был помечен (false) * @callback-param string $email email адрес * @callback-return bool пометка * } * @param int|null $priority приоритет вызова * @return Hook */ public function inputEmailTemporary(callable $callback, ?int $priority = null) { return $this->add('input.email.temporary', $callback, $priority); } /** * Фильтр: Дополнительная валидация номера телефона (isPhoneNumber) * @param callable $callback { * @callback-param string $phoneNumber номер телефона * @callback-return string номер телефона * } * @param int|null $priority приоритет вызова * @return Hook */ public function inputPhoneValidate(callable $callback, ?int $priority = null) { return $this->add('input.phone.validate', $callback, $priority); } /** * Фильтр: Дополнительная валидация текста типа TYPE_TEXT * @param callable $callback { * @callback-param string $text текст * @callback-return string текст * } * @param int|null $priority приоритет вызова * @return Hook */ public function inputTextValidate(callable $callback, ?int $priority = null) { return $this->add('input.text.validate', $callback, $priority); } /** * Фильтр: Дополнительная валидация строки для поиска (cleanSearchString) * @param callable $callback { * @callback-param string $string строка поиска * @callback-return string * } * @param int|null $priority приоритет вызова * @return Hook */ public function inputSearchStringValidate(callable $callback, ?int $priority = null) { return $this->add('input.searchstring.validate', $callback, $priority); } /** * Фильтр: Дополнительная транслитерация текста * @see \func::translit * @param callable $callback { * @callback-param string $text текст для которого выполняется транслитерация * @callback-return string * } * @param int|null $priority приоритет вызова * @return Hook */ public function utilsFuncTranslit(callable $callback, ?int $priority = null) { return $this->add('utils.func.translit', $callback, $priority); } /** * Фильтр: Список транслитерируемых символов применяемых при транслитерации текста * @see \func::translit * @param callable $callback { * @callback-param array $list список 'символ'=>'транслитерация' * @callback-return array * } * @param int|null $priority приоритет вызова * @return Hook */ public function utilsFuncTranslitConvert(callable $callback, ?int $priority = null) { return $this->add('utils.func.translit.convert', $callback, $priority); } /** * Фильтр: Список поддерживаемых провайдеров видео ссылок * @param callable $callback { * @callback-param array $list список настроек провайдеров * @callback-return array * } * @param int|null $priority приоритет вызова * @return Hook */ public function utilsVideoparserProvidersList(callable $callback, ?int $priority = null) { return $this->add('utils.videoparser.providers.list', $callback, $priority); } /** * Фильтр: Список директорий и файлов требующих проверки прав записи * @see \Dev::writableCheckProcess * @param callable $callback { * @callback-param array $list список * @callback-return array * } * @param int|null $priority приоритет вызова * @return Hook */ public function devWritableCheckList(callable $callback, ?int $priority = null) { return $this->add('dev.writable.check.list', $callback, $priority); } /** * Хук: Страница HTTP ошибок (404, ...) * @see \Errors::errorHttp() * @param callable $callback { * @callback-param int $errorCode ключ ошибки: 404, ... * @callback-param array $context контекст { * array 'data' @ref данные об ошибке { * string 'title' заголовок * string 'message' описание * } * {@see \Psr\Http\Message\ResponseInterface} 'response' @ref объект ответа * string 'template' @ref название шаблона по-умолчанию * } * } * @param int|null $priority приоритет вызова * @return Hook */ public function errorsHttpError(callable $callback, ?int $priority = null) { return $this->add('errors.http.error', $callback, $priority); } /** * Фильтр: Тегированный запрос в базу данных * @see \bff\db\Database::tag(), \bff\db\Database::exec() * @param string $key ключ тега * @param callable $callback { * @callback-param string $query строка запроса * @callback-param array $data параметры запроса { * array 'bind' @ref агрументы запроса * array 'data' @ref доп. параметры * } * @callback-return string строка запроса * } * @param int|null $priority приоритет вызова * @return Hook */ public function databaseQuery(string $key, callable $callback, ?int $priority = null) { return $this->add('db.query.' . $key, $callback, $priority); } /** * Фильтр: Данные тегированного запроса в базу данных * @see \bff\db\Database::tag(), \bff\db\illuminate\concerns\HasTags * @param string $key ключ тега * @param callable $callback { * @callback-param array $data данные запроса * } * @param int|null $priority приоритет вызова * @return Hook */ public function databaseQueryData(string $key, callable $callback, ?int $priority = null) { return $this->add('db.query.' . $key . '.data', $callback, $priority); } }