module_name = mb_strtolower($name); $this->module_component = false; if (empty($this->module_dir)) { $this->module_dir = bff()->modulesPath($this->module_name . '/'); } $this->module_dir_tpl = $this->module_dir . 'tpl'; $this->module_dir_tpl_core = bff()->corePath('modules/' . $this->module_name . '/tpl'); /** * Init Model * class_exists autoload Model_ classes */ $modelClass = ($class ?: $name) . 'Model'; if (! class_exists($modelClass)) { $modelClass = $modelClass . 'Base'; } if (class_exists($modelClass)) { $this->model = new $modelClass($this); $this->model->init(); } } /** * Инициализация модуля в качестве компонента * @param string $componentName название компонента * @param string $path директория компонента * @return void */ protected function initModuleAsComponent(string $componentName, string $path) { $path = rtrim($path, DS); $this->module_name = mb_strtolower($componentName); $this->module_dir = $path . DS; $this->module_dir_tpl = $path . DS . 'tpl'; $this->module_component = $this->module_name; # инициализируем модель (необязательно) $modelClass = $componentName . 'Model'; if (class_exists($modelClass)) { $this->model = new $modelClass($this); $this->model->init(); } } public function __call($method, $parameters) { # Attached component Or Extension return $this->callComponent($method, $parameters) ?? $this->callExtension($method, $parameters); } public function onNewRequest($request) { parent::onNewRequest($request); if ($this->model instanceof ResetsAfterRequest) { $this->model->onNewRequest($request); } foreach ($this->components as $name => $component) { $component = $this->getComponent($name); if ($component instanceof ResetsAfterRequest) { $component->onNewRequest($request); } } } /** * Include module script file * @deprecated use View::script() + js::data() * @param string|array $file * @param array|null $data данные javascript * @param array $opts * @return void */ public function js($file, $data = null, array $opts = []) { if (is_array($data)) { $this->view->jsData($data); } if (is_array($file)) { foreach ($file as $f) { $this->js($f, null, $opts); } return; } if (mb_stripos($file, '@module/') === 0) { $file = str_replace('@module', '/js/modules/' . $this->module_name, $file); } $this->view->script($file, $opts); } /** * Формирование php-шаблона * @deprecated use template() * @param array $data @ref данные, которые необходимо передать в шаблон * @param string $view название шаблона, без расширения * @param string|null $path путь к шаблону или путь к шаблонам текущего модуля (по умолчанию) * @param array $opts * @return string|mixed */ public function viewPHP(array &$data, string $view, ?string $path = null, array $opts = []) { if (!empty($path)) { $opts['path'] = $path; } return $this->template($view, $data, $opts); } /** * Формирование шаблона * @param string $view * @param array $data * @param array $opts * @return string|mixed */ public function template(string $view, array $data = [], array $opts = []) { # context $opts['this'] = $opts['this'] ?? $this; # hook prefix $moduleName = ($this->module_component !== false ? $this->module_component : $this->module_name); $opts['hookPrefix'] = 'view.module.' . $moduleName; # view.module.{module} return $this->view->render( $data, $view, (!empty($opts['path']) ? $opts['path'] : $this->module_dir_tpl), $opts ); } /** * Отображаем уведомление (frontend) * @param string $title заголовок сообщения * @param string|array $message текст сообщения(-ний) * @param bool $success * @param array $opts * @return string HTML */ public function showMessage($title = '', $message = '', $success = true, array $opts = []) { if ($success) { return $this->showSuccess($title, $message, $opts); } return $this->showForbidden($title, $message, $opts); } /** * Отображаем уведомление "Успешно..." (frontend) * @param string $title заголовок сообщения * @param string|array $message текст сообщения * @param array $opts * @return string HTML */ public function showSuccess($title = '', $message = '', array $opts = []) { return $this->errors->messageSuccess($title, $message, $opts); } /** * Отображаем уведомление об "Ошибке..." (frontend) * @param string $title заголовок сообщения * @param string|int|array $message текст сообщения или ID сообщения (Errors) * @param array $opts ['auth' - требуется авторизация] * @return string HTML */ public function showForbidden($title = '', $message = '', array $opts = []) { return $this->errors->messageForbidden($title, $message, $opts); } /** * Redirect * @param string|null $url full url / path / null * @param array $opts * @return \bff\http\RedirectResponse|\bff\http\RedirectFactory */ protected function redirect(?string $url = null, array $opts = []) { if (! is_null($url)) { return $this->app->make('redirect')->to($url, $opts); } return $this->app->make('redirect'); } /** * Корректировка URL текущего запроса с последующим 301 редиректом * @param string $url корректный URL * @param array $opts параметры * @return \bff\http\Response|bool */ public function urlCorrection(string $url, array $opts = []) { if ($this->isCron()) { return false; } if (! array_key_exists('status', $opts)) { $opts['status'] = 301; } return Request::urlCorrection($url, $opts); } /** * Устанавливаем meta-теги для страницы модуля * @param string $pageKey ключ страницы * @param array $macrosData данные для макросов * @param array $pageMeta @ref мета-данные страницы (при построении мета с общим шаблоном) * @param array $opts доп. параметры * @return void */ public function setMeta( string $pageKey, array $macrosData = [], array &$pageMeta = [], array $opts = [] ) { $template = SEO::getTemplate($this->module_name, $pageKey, $macrosData); if ($template) { SEO::i()->applyTemplate($template, $pageMeta, $opts); } } /** * Module seo templates * @return array */ public function seoTemplates() { $templates = [ 'pages' => [], 'groups' => [], 'macros' => [], ]; # Module pages with seo settings foreach (SEO::getTemplates($group = $this->module_name) as $template) { $templates['pages'][$template->getSettingsKey()] = $template->toArray(); } return $this->app->filter('seo.templates.' . $group, $templates); } /** * Generate TUID * @param string $value * @return string */ protected function makeTUID(string $value): string { $key = $this->securityKey ?? ''; return md5($key . '%^&*9Th_65' . $this->module_name . '87*(gUD0teQ*&^' . $value . $key); } /** * Validate TUID * @param string $tuid * @param string $value * @return bool */ protected function checkTUID(string $tuid, string $value): bool { return ($this->makeTUID($value) === $tuid); } /** * Сохранение настроек модуля сайта * @param array $config настройки без префикса "modulename_" * @param bool $includeDynamic входят ли в настройки($config) динамические * @return void */ public function configSave(array $config, bool $includeDynamic = false) { $prefix = $this->module_name . '_'; $save = []; foreach ($config as $k => $v) { $save[$prefix . $k] = $v; } config::save($save, $includeDynamic); } /** * Получение настроек модуля сайта * @param array $defaults настройки по-умолчанию [key=>value, ...] * @return array */ public function configLoad(array $defaults = []): array { $config = config::prefixed($this->module_name . '_', $defaults); return array_map('stripslashes', $config); } /** * Добавить сообщение об ошибке в разделе "Состояние системы" * @param string $key уникальный текстовый ключ сообщения * @param string|array $message текст сообщения * @param array $opts * @return void */ public function systemError(string $key, $message, array $opts = []) { $this->systemMessage(HH::ERROR, $key, $message, $opts); } /** * Добавить предупреждение в разделе "Состояние системы" * @param string $key уникальный текстовый ключ сообщения * @param string|array $message текст сообщения * @param array $opts * @return void */ public function systemWarning(string $key, $message, array $opts = []) { $this->systemMessage(HH::WARNING, $key, $message, $opts); } /** * Добавить заметку в разделе "Состояние системы" * @param string $key уникальный текстовый ключ сообщения * @param string|array $message текст сообщения * @param array $opts * @return void */ public function systemNotice(string $key, $message, array $opts = []) { $this->systemMessage(HH::NOTICE, $key, $message, $opts); } /** * Добавить сообщение в разделе "Состояние системы" * @param int $level тип сообщения HH::ERROR, ... * @param string $key уникальный текстовый ключ сообщения * @param string|array $message текст сообщения * @param array $opts * @return void */ public function systemMessage(int $level, string $key, $message, array $opts = []) { $opts['module'] = $this; $this->app->hh()->set($level, $this->module_name . '_' . $key, $message, $opts); } /** * Удалить ранее добавленное сообщение в разделе "Состояние системы" * @param string $key уникальный текстовый ключ сообщение (ранее добавленного) * @param array $opts * @return void */ public function systemResolve(string $key, array $opts = []) { $this->app->hh()->resolve($this->module_name . '_' . $key); } /** * Метод вызываемый в процессе выполнения проверки в разделе "Состояние системы" * В данном методе модуль может добавлять/удалять ранее добавленные сообщения * @return void */ public function systemCheck() { // } /** * Сокращение для доступа к модулю SEO * @return \SEO модуль */ public function seo() { return SEO::i(); } /** * Формирование списка директорий/файлов требующих проверки на наличие прав записи * @return array */ public function writableCheck() { return []; } }