module_title); } /** * Проверка прав доступа текущего пользователя (администратора) к методу модуля * @param string|array $scope * @param string|null $module название модуля или null (текущий модуль) * @return bool */ public function haveAccessTo($scope, ?string $module = null): bool { return ( $this->isAdminPanel() && $this->security->haveAccessTo($module ?? $this->module_name, $scope) ); } /** * Сообщение в админ-панели: в доступе отказано * @param array $opts * @return string|\bff\http\Response */ public function showAccessDenied(array $opts = []) { if ($this->isAJAX()) { return $this->ajaxResponse(Errors::ACCESSDENIED); } return $this->showError(Errors::ACCESSDENIED, $opts); } /** * Сообщение в админ-панели: невозможно выполнить операцию * @param bool $redirect выполнять редирект * @param string|null $methodName название метода или null - текущий метод * @param array $opts * @return string|\bff\http\Response HTML */ public function showImpossible(bool $redirect = false, ?string $methodName = 'listing', array $opts = []) { if ($this->isAJAX()) { return $this->ajaxResponse(Errors::IMPOSSIBLE); } if (empty($methodName)) { $methodName = Route::controllerMethod(); } if ($redirect) { return $this->adminRedirect(Errors::IMPOSSIBLE, $methodName); } return $this->showError(Errors::IMPOSSIBLE, $opts); } /** * Выводим сообщение об ошибке в админ-панели * @param int $errorCode код ошибки * @param array $opts * @return string|\bff\http\Response */ protected function showError(int $errorCode, array $opts = []) { $opts = $this->defaults($opts, [ 'autohide' => false, # скрывать ошибку по таймауту 'popup' => false, ]); if (! $opts['autohide'] || $errorCode === Errors::ACCESSDENIED) { $this->errors->autohide(false); } $referer = Request::referer(); if (! $opts['popup'] && ! empty($referer) && User::logined()) { return $this->redirect($referer . '&errno=' . $errorCode); } $this->errors->set($errorCode); return ''; } /** * Перенаправление в раздел админ-панели * @param int|null $errorCode код ошибки или Errors::SUCCESS * @param string|null $methodName название метода или NULL - текущий метод * @param string|null $moduleName название модуля или NULL * @return \bff\http\Response */ protected function adminRedirect( ?int $errorCode = Errors::SUCCESS, ?string $methodName = 'listing', ?string $moduleName = null ) { if ($this->isAJAX()) { return $this->ajaxResponse($errorCode); } if (empty($methodName)) { $methodName = Route::controllerMethod(); } if (empty($moduleName)) { $moduleName = $this->module_name; } return $this->redirect()->admin( $moduleName . '/' . $methodName, (!empty($errorCode) ? ['errno' => $errorCode] : []) ); } /** * Обвертка php-шаблона врапером для модального окна * @param array $data данные, которые необходимо передать в шаблон * @param string $templateName название шаблона, без расширения ".php" * @param array $opts [title] * @return \bff\http\Response */ public function adminModal(array $data, string $templateName, array $opts = []) { $modal = $this->template('modal', [ 'title' => $opts['title'] ?? '', 'content' => $this->template($templateName, $data), ], [ 'path' => $this->app->basePath('tpl/admin'), ]); return $this->ajaxResponseForm(['modal' => $modal]); } /** * Формирование URL в админ-панели * @param string|null $methodName название метода * @param array|string|null $query array - параметры query, string - название модуля, null (текущий модуль) * @param string|bool $escapeType выполнять квотирование, false - не выполнять, 'html', 'js' * @return string */ public function adminLink(?string $methodName = 'listing', $query = [], $escapeType = false) { if (is_null($methodName)) { return Url::admin(null); } $moduleName = $this->module_name; if (is_string($query) && ! empty($query)) { $moduleName = $query; $query = []; } elseif (! is_array($query)) { $query = []; } return Url::admin($moduleName . '/' . $methodName, $query, $escapeType); } /** * Метод редактирование seo-шаблонов модуля * @return mixed */ public function seo_templates_edit() { return SEO::templatesList($this->module_name, $this->module_title); } /** * Формирование ответа для компонента "autocomplete" * @param array $data @ref результаты поиска * @param string $idKey ключ ID * @param string $titleKey ключ названия * @param string|bool $type тип autocomplete-контрола * @return \bff\http\Response */ protected function autocompleteResponse(&$data, string $idKey = 'id', string $titleKey = 'title', $type = false) { if (empty($data)) { $data = []; } $response = []; if ($type === false) { $type = (!empty($_POST['tag']) ? 'fb' : 'ac' /* autocomplete */); } # autocomplete.fb if ($type === 'fb') { foreach ($data as $v) { $response[] = ['key' => $v[$idKey], 'value' => $v[$titleKey]]; } unset($v); return $this->ajaxResponse($response, 1); } # autocomplete foreach ($data as $v) { $response[$v[$idKey]] = ($titleKey === false ? $v : $v[$titleKey]); } unset($v); return $this->ajaxResponse($response); } /** * Формирование сортировки по указанному полю * @param string $orderBy @ref результирующее название поля, по которому необходимо выполнить сортировку * @param string $orderDirection @ref результирующий порядок сортировки * @param string $defaultOrder сортировка по-умолчанию 'поле-направление', например 'title-desc' * @param array $allowedOrders @ref допустимые варианты сортировки, например array('id'=>'asc','title'=>'desc',...) * @param string $orderVarKey ключ параметра сортировки, по-умолчанию 'order' * @return array|bool */ protected function prepareOrder( &$orderBy, &$orderDirection, $defaultOrder = '', array &$allowedOrders = [], string $orderVarKey = 'order' ) { $order = $this->input->getpost($orderVarKey, TYPE_STR); if (empty($order)) { $order = $defaultOrder; } # порядок сортировки указан некорректно if (empty($order)) { return false; } @list($orderBy, $orderDirection) = explode(tpl::ORDER_SEPARATOR, $order, 2); if (! isset($orderDirection)) { $orderDirection = 'asc'; } if (! empty($allowedOrders) && ! isset($allowedOrders[$orderBy])) { @list($orderBy, $orderDirection) = explode(tpl::ORDER_SEPARATOR, $defaultOrder, 2); } $orderDirection = ($orderDirection == 'asc' ? 'asc' : 'desc'); $orderDirectionNeeded = ($orderDirection == 'asc' ? 'desc' : 'asc'); if (! empty($allowedOrders[$orderBy])) { if (is_array($allowedOrders[$orderBy])) { $allowedOrders[$orderBy]['d'] = $orderDirection; } else { $allowedOrders[$orderBy] = $orderDirection; } } return [ 'order_by' => $orderBy, 'order_dir' => $orderDirection, 'order_dir_needed' => $orderDirectionNeeded, ]; } /** * Формирование выбора кол-ва записей на страницу * @param int $perPage @ref кол-во записей на страницу * @param array $values допустимые варианты * @param int|null $expireDays кол-во дней, в течении которых выбранное кол-во хранится в куках * @param string $varName ключ передаваемый текущее кол-во в запросе * @return string */ protected function preparePerpage( int &$perPage, array $values = [5, 10, 15], ?int $expireDays = 7, string $varName = 'perpage' ): string { $perPage = $this->input->getpost($varName, TYPE_UINT); $cookieKey = $this->app->cookieKey($this->module_name . '_' . $varName); $currentValue = $this->input->cookie($cookieKey, TYPE_UINT); if (! $perPage) { $perPage = $currentValue; if (! in_array($perPage, $values)) { $perPage = current($values); } } else { if (! in_array($perPage, $values)) { $perPage = current($values); } if ($currentValue != $perPage) { Response::setCookie($cookieKey, $perPage, ($expireDays ?? 7)); } } array_walk( $values, function (&$item, $key, $cur) { $attr = ['value' => $item]; if ($item == $cur) { $attr[] = 'selected'; } $item = '' . $item . ''; }, $perPage ); return join('', $values); } }