diff --git a/credits.txt b/credits.txt index 5e15b6c2e..7b4e0c42a 100755 --- a/credits.txt +++ b/credits.txt @@ -10,6 +10,10 @@ Third-party plugins, libraries and resources included in InstantCMS: by Twitter, Inc https://getbootstrap.com + VueJS + by TEvan You && Core Team + https://vuejs.org/ + Font Awesome Free by Fonticons, Inc. https://fontawesome.com diff --git a/install/functions.php b/install/functions.php index 7df0d2fe2..36c50c260 100755 --- a/install/functions.php +++ b/install/functions.php @@ -179,7 +179,10 @@ function get_templates() { continue; } - $list[$dir . '/' . $next] = $next; + // не даём выбрать устаревший шаблон + if($next !== 'default'){ + $list[$dir . '/' . $next] = $next; + } } return $list; diff --git a/install/languages/en/sql/base.sql b/install/languages/en/sql/base.sql index a344d8f13..25e5ce317 100755 --- a/install/languages/en/sql/base.sql +++ b/install/languages/en/sql/base.sql @@ -876,7 +876,6 @@ INSERT INTO `{#}events` (`id`, `event`, `listener`, `ordering`, `is_enabled`) VA (151, 'images_before_upload', 'typograph', 151, 1), (152, 'engine_start', 'content', 152, 1), (153, 'content_category_after_update', 'subscriptions', 153, 1), -(154, 'grid_admin_content_items_args', 'admin', 154, 1), (155, 'user_notify_types', 'rating', 155, 1), (156, 'content_before_item', 'comments', 156, 1), (157, 'content_before_item', 'rating', 157, 1), diff --git a/install/languages/ru/sql/base.sql b/install/languages/ru/sql/base.sql index 921319d7b..72778bf1e 100755 --- a/install/languages/ru/sql/base.sql +++ b/install/languages/ru/sql/base.sql @@ -876,7 +876,6 @@ INSERT INTO `{#}events` (`id`, `event`, `listener`, `ordering`, `is_enabled`) VA (151, 'images_before_upload', 'typograph', 151, 1), (152, 'engine_start', 'content', 152, 1), (153, 'content_category_after_update', 'subscriptions', 153, 1), -(154, 'grid_admin_content_items_args', 'admin', 154, 1), (155, 'user_notify_types', 'rating', 155, 1), (156, 'content_before_item', 'comments', 156, 1), (157, 'content_before_item', 'rating', 157, 1), diff --git a/system/controllers/activity/backend.php b/system/controllers/activity/backend.php index 11c13325c..5b03f594d 100755 --- a/system/controllers/activity/backend.php +++ b/system/controllers/activity/backend.php @@ -15,15 +15,11 @@ public function __construct(cmsRequest $request) { }); } - public function actionIndex() { - $this->redirectToAction('options'); - } - public function getBackendMenu() { return [ [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] diff --git a/system/controllers/activity/backend/grids/grid_types.php b/system/controllers/activity/backend/grids/grid_types.php index 7c596bb2e..58014ef7c 100755 --- a/system/controllers/activity/backend/grids/grid_types.php +++ b/system/controllers/activity/backend/grids/grid_types.php @@ -21,13 +21,13 @@ function grid_types($controller) { 'title' => LANG_EVENTS_LISTENER, 'width' => 200, 'class' => 'd-none d-lg-table-cell', - 'filter' => 'like', + 'filter' => 'exact', 'filter_select' => [ 'items' => function($name){ $admin_model = cmsCore::getModel('admin'); $admin_model->join('activity_types', 'e', 'e.controller = i.name'); $controllers = $admin_model->groupBy('i.id')->getInstalledControllers(); - $items = ['' => '']; + $items = ['' => LANG_ALL]; foreach($controllers as $controller){ $items[$controller['name']] = $controller['title']; } @@ -57,7 +57,7 @@ function grid_types($controller) { $columns[$name] = [ 'title' => LANG_ACTIVITY_DESC.' ['.$lang.']', 'editable' => [ - 'save_action' => href_to('admin', 'inline_save', [urlencode('activity_types'), '{id}', 1]) + 'language_context' => true ] ]; } @@ -66,9 +66,7 @@ function grid_types($controller) { $columns['description'] = [ 'title' => LANG_ACTIVITY_DESC, - 'editable' => [ - 'table' => 'activity_types' - ] + 'editable' => [] ]; } diff --git a/system/controllers/admin/actions/content.php b/system/controllers/admin/actions/content.php index d76ec9ddb..2f093813c 100755 --- a/system/controllers/admin/actions/content.php +++ b/system/controllers/admin/actions/content.php @@ -4,77 +4,190 @@ */ class actionAdminContent extends cmsAction { - public function run($do = false) { - - $ctype_id = 0; - $ctype = []; - - // если нужно, передаем управление другому экшену - if ($do) { - if (!is_numeric($do)) { - $this->runExternalAction('content_' . $do, array_slice($this->params, 1)); - return; - } else { - $ctype_id = $do; - } - } + use icms\traits\oneable; - $ctypes = $this->model_backend_content->getContentTypesFiltered(); + use icms\traits\controllers\actions\listgrid { + getListItemsGridHtml as private traitGetListItemsGridHtml; + } - $key_path = '/1.1'; + private $ctype = []; - // Сохранённый путь дерева - $tree_path = cmsUser::getCookie('content_tree_path'); + private $tree_path_key = ''; - if ($tree_path) { - $tree_path = explode('/', trim($tree_path, '/')); + private $category_id = 1; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $this->external_action_prefix = 'content_'; + + $this->toolbar_hook = 'admin_content_toolbar'; + } + + public function prepareRun() { + + $this->loadCtype(($this->params[0] ?? 0), ($this->params[1] ?? false)); + + $category = $this->model_backend_content->getCategory($this->ctype['name'], $this->category_id); + if (!$category) { + return cmsCore::error404(); } - // Если $ctype_id передан, формируем $key_path - if ($ctype_id) { + $this->table_name = $this->model->getContentTypeTableName($this->ctype['name']); + $this->grid_name = 'content_items'; + $this->grid_args = [$this->ctype]; + $this->ups_key = $this->ctype['name'].'.'; + + $this->tool_buttons = [ + [ + 'class' => 'menu d-xl-none', + 'data' => [ + 'toggle' =>'quickview', + 'toggle-element' => '#left-quickview' + ], + 'title' => LANG_MENU + ], + [ + 'class' => 'settings', + 'title' => LANG_CONFIG, + 'href' => null + ], + [ + 'class' => 'logs', + 'title' => LANG_MODERATION_LOGS, + 'href' => null + ], + [ + 'class' => 'folder', + 'childs_count' => 4, + 'title' => LANG_CATEGORIES + ], + [ + 'class' => 'add_folder', + 'level' => 2, + 'title' => LANG_CP_CONTENT_CATS_ADD + ], + [ + 'class' => 'edit_folder', + 'level' => 2, + 'title' => LANG_EDIT + ], + [ + 'class' => 'delete_folder', + 'level' => 2, + 'title' => LANG_DELETE_CATEGORY, + 'confirm' => LANG_DELETE_CATEGORY_CONFIRM + ], + [ + 'class' => 'tree_folder', + 'level' => 2, + 'title' => LANG_CP_CONTENT_CATS_ORDER, + 'onclick' => 'return contentCatsReorder($(this))' + ], + [ + 'class' => 'add add_site', + 'title' => LANG_CP_CONTENT_ITEM_ADD + ], + [ + 'class' => 'add add_cpanel', + 'title' => LANG_CP_CONTENT_ITEM_ADD_CP + ] + ]; + + $this->list_callback = function ($model) use($category) { + + $model->filterCategory($this->ctype['name'], $category, true, !empty($this->ctype['options']['is_cats_multi'])); + + $model->joinUser(); + + $model->joinLeft( + 'moderators_logs', + 'mlog', + "mlog.target_id = i.id AND mlog.target_controller = 'content' AND mlog.target_subject = '{$this->ctype['name']}' AND mlog.date_expired IS NOT NULL" + ); + $model->select('mlog.date_expired', 'trash_date_expired'); + + $model->joinModerationsTasks($this->ctype['name']); + + return $model; + }; + } - $key_path = '/' . $ctype_id . '.1'; + public function getListItemsGridHtml() { - // дополняем его категориями, если в куках этот тип контента - if ($tree_path && '/' . $tree_path[0] === $key_path) { - $key_path = '/' . implode('/', $tree_path); - } - } else { + $ctypes = $this->getOnce($this->model_backend_content)->getContentTypesFiltered(); - // Иначе, берём id типа контента из кук и формируем $key_path - if ($tree_path) { + $grid_html = $this->traitGetListItemsGridHtml(); - $ctype_id = (int) $tree_path[0]; + return $this->cms_template->renderInternal($this, 'content', [ + 'key_path' => $this->tree_path_key, + 'ctype' => $this->ctype, + 'ctypes' => $ctypes, + 'grid_html' => $grid_html + ]); + } - $key_path = '/' . implode('/', $tree_path); - } + private function loadCtype($ctype_id, $category_id) { + + if ($category_id !== false) { + $this->category_id = $category_id; } + // Если передан из урл if ($ctype_id) { - $ctype = $this->model_backend_content->getContentType($ctype_id); + $this->ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype && $do) { + if (!$this->ctype) { return cmsCore::error404(); } } - if (!empty($ctype)) { - $grid = $this->loadDataGrid('content_items', $ctype['name'], 'admin.grid_filter.content.' . $ctype['name']); - } else { - $grid = $this->loadDataGrid('content_items'); + // Сохранённый путь дерева + $tree_path = cmsUser::getCookie('content_tree_path'); + + if ($tree_path) { + + $tree_path = ltrim($tree_path, '/'); + + if (preg_match('/^([0-9\/\.]+)$/i', $tree_path)) { + + $this->tree_path_key = $tree_path; + + $tree_keys = explode('/', $tree_path); + + $tree_key = explode('.', end($tree_keys)); + + $ctype_id = (int)($tree_key[0] ?? 0); + + // если не передан из урла, берём из куки + if (!$this->ctype) { + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + } + + if ($this->ctype) { + + if ($category_id === false) { + $this->category_id = (int)($tree_key[1] ?? $this->category_id); + } + + return; + } + } } - $diff_order = cmsUser::getUPS('admin.grid_filter.content.diff_order'); + // Иначе первый из списка + if (!$this->ctype) { - return $this->cms_template->render('content', [ - 'key_path' => $key_path, - 'ctype' => $ctype, - 'ctype_id' => $ctype_id, - 'ctypes' => $ctypes, - 'grid' => $grid, - 'diff_order' => $diff_order - ]); + $ctypes = $this->getOnce($this->model_backend_content)->getContentTypesFiltered(); + + $this->ctype = reset($ctypes); + + $this->tree_path_key = $this->ctype['id'].'.'.$this->category_id; + } + + return; } } diff --git a/system/controllers/admin/actions/content_filter.php b/system/controllers/admin/actions/content_filter.php index 918f4ef8d..1c68ae1d8 100755 --- a/system/controllers/admin/actions/content_filter.php +++ b/system/controllers/admin/actions/content_filter.php @@ -11,8 +11,6 @@ public function run($ctype_id) { return cmsCore::error404(); } - $datasets = $this->model_backend_content->getContentDatasets($ctype_id); - $fields = $this->model_backend_content->getContentFields($ctype['name']); $fields = cmsEventsManager::hook('ctype_content_fields', $fields); @@ -41,16 +39,17 @@ public function run($ctype_id) { ]; } + $fields[] = [ + 'title' => LANG_CP_SHOW_ONLY_IN_TRASH, + 'name' => 'is_deleted', + 'handler' => new fieldCheckbox('is_deleted') + ]; + list($fields, $ctype) = cmsEventsManager::hook('admin_content_filter', [$fields, $ctype]); list($fields, $ctype) = cmsEventsManager::hook('admin_content_' . $ctype['name'] . '_filter', [$fields, $ctype]); - $diff_order = cmsUser::getUPS('admin.grid_filter.content.diff_order'); - - return $this->cms_template->render('content_filter', [ - 'ctype' => $ctype, - 'datasets' => $datasets, - 'fields' => $fields, - 'diff_order' => $diff_order + return $this->cms_template->render('grid_advanced_filter', [ + 'fields' => $fields ]); } diff --git a/system/controllers/admin/actions/content_grid_columns.php b/system/controllers/admin/actions/content_grid_columns.php deleted file mode 100644 index 511598685..000000000 --- a/system/controllers/admin/actions/content_grid_columns.php +++ /dev/null @@ -1,53 +0,0 @@ -request->isAjax() - || - !is_numeric($ctype_id) - ){ return cmsCore::error404(); } - - $items = $this->getContentGridColumnsSettings($ctype_id); - - if(!$items){ return cmsCore::error404(); } - - if($this->request->has('submit')){ - - $new_config = $this->request->get('columns', array()); - - cmsUser::setUPS('admin.grid_columns.content.'.$ctype_id, $new_config); - cmsUser::setUPS('admin.grid_columns.content.'.$ctype_id.'.changed', true); - - return $this->cms_template->renderJSON(array( - 'error' => false - )); - - } - - if($this->request->has('reset')){ - - cmsUser::deleteUPS('admin.grid_columns.content.'.$ctype_id); - - return $this->cms_template->renderJSON(array( - 'error' => false - )); - - } - - $default = $this->getContentGridColumnsSettingsDefault(); - - $saved = cmsUser::getUPS('admin.grid_columns.content.'.$ctype_id)?:array(); - - $config = array_merge($default, $saved); - - return $this->cms_template->render('content_grid_columns', array( - 'items' => $items, - 'config' => $config, - 'ctype_id' => $ctype_id - )); - - } - -} diff --git a/system/controllers/admin/actions/content_items_ajax.php b/system/controllers/admin/actions/content_items_ajax.php deleted file mode 100755 index 5b2c60922..000000000 --- a/system/controllers/admin/actions/content_items_ajax.php +++ /dev/null @@ -1,106 +0,0 @@ -request->isAjax()) { - return cmsCore::error404(); - } - - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { $this->halt(); } - - $category = $this->model_backend_content->getCategory($ctype['name'], $parent_id); - if (!$category) { $this->halt(); } - - $grid = $this->loadDataGrid('content_items', $ctype['name']); - - $dataset_filters = []; - $filter = []; - $filter_str = $this->request->get('filter', ''); - - // Одновременно смениться и тип контента, и настройка diff_order не могут - $diff_order = cmsUser::getUPS('admin.grid_filter.content.diff_order'); - - // Изменён тип контента и должна быть сохранена сортировка - if ($filter_str && mb_strpos($filter_str, 'ctype_changed=1') !== false && $diff_order) { - // Проверим, что эта сортировка есть в бд, иначе будет использоваться пришедшая - $ups_filter_str = cmsUser::getUPS('admin.grid_filter.content.' . $ctype['name']); - if ($ups_filter_str) { - $filter_str = $ups_filter_str; - } - // Чтобы заполнить поля поиска фильтра - $grid['options']['load_columns'] = true; - } else { - $filter_str = cmsUser::getUPSActual('admin.grid_filter.content.' . $ctype['name'], $filter_str); - } - - if ($filter_str) { - - parse_str($filter_str, $filter); - - if (!empty($filter['advanced_filter'])) { - - parse_str($filter['advanced_filter'], $dataset_filters); - - if (!empty($dataset_filters['dataset'])) { - - $dataset = $this->model_backend_content->getContentDataset($dataset_filters['dataset']); - - $this->model_backend_content->applyDatasetFilters($dataset, true); - } - - $this->model_backend_content->applyDatasetFilters($dataset_filters); - - // Различная сортировка у разных типов контента, сохранение настройки - $new_diff_order = !empty($dataset_filters['diff_order']) ? '1' : '0'; - if ($new_diff_order !== $diff_order) { - cmsUser::setUPS('admin.grid_filter.content.diff_order', $new_diff_order); - } - } - - if (!empty($filter['order_by']) && !isset($grid['columns'][$filter['order_by']])) { - unset($filter['order_by']); - } - - $this->model_backend_content->applyGridFilter($grid, $filter); - - // В случае обновления 'columns' грида для заполнения полей фильтров - $grid['filter'] = $filter; - } - - $this->model_backend_content->filterCategory($ctype['name'], $category, true, !empty($ctype['options']['is_cats_multi'])); - - $this->model_backend_content->disableDeleteFilter(); - $this->model_backend_content->disableApprovedFilter(); - $this->model_backend_content->disablePubFilter(); - $this->model_backend_content->disablePrivacyFilter(); - - $total = $this->model_backend_content->getContentItemsCount($ctype['name']); - - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - - $pages = ceil($total / $perpage); - - $this->model_backend_content->setPerPage($perpage); - - $this->model_backend_content->joinLeft( - 'moderators_logs', - 'mlog', - "mlog.target_id = i.id AND mlog.target_controller = 'content' AND mlog.target_subject = '{$ctype['name']}' AND mlog.date_expired IS NOT NULL" - ); - $this->model_backend_content->select('mlog.date_expired', 'trash_date_expired'); - - $this->model_backend_content->joinModerationsTasks($ctype['name']); - - $items = $this->model_backend_content->getContentItems($ctype['name']); - - $this->cms_template->renderGridRowsJSON($grid, $items, $total, $pages); - - $this->halt(); - } - -} diff --git a/system/controllers/admin/actions/controllers.php b/system/controllers/admin/actions/controllers.php index 420bde07c..e71471b26 100755 --- a/system/controllers/admin/actions/controllers.php +++ b/system/controllers/admin/actions/controllers.php @@ -2,21 +2,62 @@ class actionAdminControllers extends cmsAction { - public function run($do = false) { + use icms\traits\controllers\actions\listgrid { + renderListItemsGrid as private traitRenderListItemsGrid; + } + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $this->table_name = 'controllers'; + $this->grid_name = 'controllers'; + $this->title = LANG_CP_SECTION_CONTROLLERS; + + $this->external_action_prefix = 'controllers_'; + + $this->list_callback = function ($model) { - // если нужно, передаем управление другому экшену - if ($do) { + cmsCore::loadAllControllersLanguages(); - $this->runExternalAction('controllers_' . $do, array_slice($this->params, 1)); + if (!$model->order_by) { + $model->orderByList([ + [ + 'by' => 'is_enabled', + 'to' => 'desc' + ], + [ + 'by' => 'title', + 'to' => 'asc' + ] + ]); + } - return; - } + return $model; + }; - $grid = $this->loadDataGrid('controllers', false, 'admin.grid_filter.controllers'); + $this->item_callback = function ($item, $model) { - return $this->cms_template->render('controllers', [ - 'grid' => $grid + $item['title'] = string_lang($item['name'] . '_CONTROLLER', $item['title']); + + return $item; + }; + } + + public function renderListItemsGrid(){ + + $this->cms_template->addMenuItems('admin_toolbar', $this->getAddonsMenu()); + + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_COMPONENTS, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] ]); + + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/controllers_ajax.php b/system/controllers/admin/actions/controllers_ajax.php deleted file mode 100755 index 1eb117f70..000000000 --- a/system/controllers/admin/actions/controllers_ajax.php +++ /dev/null @@ -1,37 +0,0 @@ -request->isAjax()) { - return cmsCore::error404(); - } - - cmsCore::loadAllControllersLanguages(); - - $grid = $this->loadDataGrid('controllers'); - - $this->model->setPerPage(admin::perpage); - - $filter = []; - $filter_str = $this->request->get('filter', ''); - - $filter_str = cmsUser::getUPSActual('admin.grid_filter.controllers', $filter_str); - - if ($filter_str) { - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } - - $total = $this->model->getInstalledControllersCount(); - $pages = ceil($total / admin::perpage); - - $controllers = $this->model->getInstalledControllers(); - - $this->cms_template->renderGridRowsJSON($grid, $controllers, $total, $pages); - - return $this->halt(); - } - -} diff --git a/system/controllers/admin/actions/controllers_edit.php b/system/controllers/admin/actions/controllers_edit.php index 6db4fe923..781e18e5a 100755 --- a/system/controllers/admin/actions/controllers_edit.php +++ b/system/controllers/admin/actions/controllers_edit.php @@ -2,39 +2,45 @@ class actionAdminControllersEdit extends cmsAction { - public function run($controller_name){ + public function run($controller_name) { - if (!$controller_name) { cmsCore::error404(); } + if (!$controller_name) { + return cmsCore::error404(); + } $controller_info = $this->model->getControllerInfo($controller_name); if (!$controller_info) { + // если компонент имеет несколько контроллеров и один из них использует опции другого $controller_info = cmsEventsManager::hook("admin_{$controller_name}_controller_info", false); - if (!$controller_info) { cmsCore::error404(); } + if (!$controller_info) { + return cmsCore::error404(); + } } cmsCore::loadControllerLanguage($controller_info['name']); - $controller_title = string_lang($controller_info['name'].'_CONTROLLER', $controller_info['title']); + $controller_title = string_lang($controller_info['name'] . '_CONTROLLER', $controller_info['title']); $this->cms_template->setPageTitle($controller_title); $this->cms_template->addBreadcrumb(LANG_CP_SECTION_CONTROLLERS, $this->cms_template->href_to('controllers')); - $this->cms_template->addBreadcrumb($controller_title, $this->cms_template->href_to('controllers', 'edit/'.$controller_info['name'])); + $this->cms_template->addBreadcrumb($controller_title, $this->cms_template->href_to('controllers', 'edit/' . $controller_info['name'])); + + if (!$controller_info['is_backend']) { - if (!$controller_info['is_backend']){ - return $this->cms_template->render('controllers_edit', array( + return $this->cms_template->render('controllers_edit', [ 'is_backend' => false, 'ctype' => false, 'controller_name' => $controller_info['name'], 'controller_title' => $controller_title - )); + ]); } // - // Загружаем бакенд выбранного контроллера + // Загружаем бэкенд выбранного контроллера // - $backend_context = $this->request->isAjax() ? cmsRequest::CTX_AJAX : cmsRequest::CTX_INTERNAL; - $backend_request = new cmsRequest($this->request->getData(), $backend_context); + $backend_context = $this->request->isAjax() ? cmsRequest::CTX_AJAX : cmsRequest::CTX_INTERNAL; + $backend_request = new cmsRequest($this->request->getData(), $backend_context); $backend_controller = $this->loadControllerBackend($controller_info['name'], $backend_request); // меню компонента в админке @@ -45,39 +51,49 @@ public function run($controller_name){ // связан ли контроллер с типами контента $ctype = cmsCore::getModel('content')->getContentTypeByName($backend_controller->maintained_ctype ? $backend_controller->maintained_ctype : $controller_name); - // Определяем текущий экшен бакенда - $action_name = count($this->params)>1 ? $this->params[1] : 'index'; + // Определяем текущий экшен бэкенда + $action_name = count($this->params) > 1 ? $this->params[1] : 'index'; + + // Сразу включаем экшен опций, чтобы не писать редиректы + if($action_name === 'index' && + !$backend_controller->isActionExists('index') && + $backend_controller->isActionExists('options')){ + + $action_name = 'options'; + } // // Удаляем из массива параметров название контроллера и экшен // if (count($this->params) <= 2) { - $params = array(); + $params = []; } else { - $params = $this->params; - unset($params[0]); - unset($params[1]); + $params = array_slice($this->params, 2); } list( $backend_controller, $action_name, $params - ) = cmsEventsManager::hook("backend_{$controller_info['name']}_before_action", [ - $backend_controller, - $action_name, - $params - ]); + ) = cmsEventsManager::hook("backend_{$controller_info['name']}_before_action", [ + $backend_controller, + $action_name, + $params + ]); + + // Если запрос пришел по AJAX, то выполняем экшен бэкенда сразу же + if ($this->request->isAjax()) { - // Если запрос пришел по AJAX, то выполняем экшен бакенда сразу же - if ($this->request->isAjax()){ $backend_controller->runAction($action_name, $params); - $this->halt(); + + return $this->halt(); } - // Подключаем CSS бакенда если он есть + // Подключаем CSS бэкенда если он есть $css_file = $this->cms_template->getStylesFileName($controller_info['name'], 'backend'); - if ($css_file){ $this->cms_template->addCSS($css_file); } + if ($css_file) { + $this->cms_template->addCSS($css_file); + } $backend_sub_menu = $backend_controller->getBackendSubMenu(); @@ -85,39 +101,40 @@ public function run($controller_name){ $this->cms_template->setMenuItems('backend', $backend_menu); - if($ctype){ + if ($ctype) { $this->cms_template->addMenuItem('breadcrumb-menu', [ - 'title' => LANG_CONTENT_TYPE.' «'.$ctype['title'].'»', - 'url' => $this->cms_template->href_to('ctypes', ['edit', $ctype['id']]), + 'title' => LANG_CONTENT_TYPE . ' «' . $ctype['title'] . '»', + 'url' => $this->cms_template->href_to('ctypes', ['edit', $ctype['id']]), 'options' => [ - 'icon' => 'retweet' + 'icon' => 'retweet' ] ]); } - $help_href_const = 'LANG_HELP_URL_COM_'.strtoupper($backend_controller->name); - if(defined($help_href_const)){ + $help_href_const = 'LANG_HELP_URL_COM_' . strtoupper($backend_controller->name); + + if (defined($help_href_const)) { + $this->cms_template->addMenuItem('breadcrumb-menu', [ - 'title' => LANG_HELP, - 'url' => constant($help_href_const), + 'title' => LANG_HELP, + 'url' => constant($help_href_const), 'options' => [ 'target' => '_blank', - 'icon' => 'question-circle' + 'icon' => 'question-circle' ] ]); } $html = $backend_controller->runAction($action_name, $params); - return $this->cms_template->render('controllers_edit', array( - 'is_backend' => true, - 'ctype' => $ctype, - 'controller_name' => $controller_info['name'], - 'controller_title' => $controller_title, - 'html' => $html - )); - + return $this->cms_template->render('controllers_edit', [ + 'is_backend' => true, + 'ctype' => $ctype, + 'controller_name' => $controller_info['name'], + 'controller_title' => $controller_title, + 'html' => $html + ]); } } diff --git a/system/controllers/admin/actions/controllers_events.php b/system/controllers/admin/actions/controllers_events.php index 2fa02afc6..1638b63de 100644 --- a/system/controllers/admin/actions/controllers_events.php +++ b/system/controllers/admin/actions/controllers_events.php @@ -2,18 +2,45 @@ class actionAdminControllersEvents extends cmsAction { - public function run(){ + use icms\traits\controllers\actions\listgrid { + getListItemsGridHtml as private traitGetListItemsGridHtml; + } + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $this->table_name = 'events'; + $this->grid_name = 'controllers_events'; + + $this->list_callback = function ($model) { + + $model->limit(false); - $grid = $this->loadDataGrid('controllers_events'); + return $model; + }; + } + + public function getListItemsGridHtml(){ $diff_events = $this->getEventsDifferences(); - return $this->cms_template->render('controllers_events', array( + if (!empty($diff_events['added']) || !empty($diff_events['deleted'])) { + + $this->tool_buttons[] = [ + 'class' => 'refresh', + 'title' => LANG_EVENTS_REFRESH, + 'href' => $this->cms_template->href_to('controllers', ['events_update']) + ]; + } + + $grid_html = $this->traitGetListItemsGridHtml(); + + return $this->cms_template->renderInternal($this, 'controllers_events', [ 'events_add' => $diff_events['added'], 'events_delete' => $diff_events['deleted'], - 'grid' => $grid - )); - + 'grid_html' => $grid_html + ]); } } diff --git a/system/controllers/admin/actions/controllers_events_ajax.php b/system/controllers/admin/actions/controllers_events_ajax.php deleted file mode 100644 index 7fbc77c4a..000000000 --- a/system/controllers/admin/actions/controllers_events_ajax.php +++ /dev/null @@ -1,29 +0,0 @@ -request->isAjax()) { cmsCore::error404(); } - - $grid = $this->loadDataGrid('controllers_events'); - - $filter = array(); - $filter_str = $this->request->get('filter', ''); - - $filter_str = cmsUser::getUPSActual('admin.grid_filter.events', $filter_str); - - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } - - $events = $this->model->getEvents(); - - $this->cms_template->renderGridRowsJSON($grid, $events); - - $this->halt(); - - } - -} diff --git a/system/controllers/admin/actions/ctypes_datasets.php b/system/controllers/admin/actions/ctypes_datasets.php index ebdbb2fce..4ed17b9f7 100755 --- a/system/controllers/admin/actions/ctypes_datasets.php +++ b/system/controllers/admin/actions/ctypes_datasets.php @@ -4,36 +4,64 @@ */ class actionAdminCtypesDatasets extends cmsAction { - public function run($ctype_id = null) { + use icms\traits\controllers\actions\listgrid { + renderListItemsGrid as private traitRenderListItemsGrid; + } - if (!$ctype_id) { - return cmsCore::error404(); - } + private $ctype = []; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { + $ctype_id = $params[0] ?? 0; + + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + if (!$this->ctype) { return cmsCore::error404(); } - $this->dispatchEvent('ctype_loaded', [$ctype, 'datasets']); + $this->table_name = 'content_datasets'; + $this->grid_name = 'ctype_datasets'; + $this->grid_args = [href_to($this->name, 'ctypes', ['datasets_edit', '{id}'])]; + $this->title = LANG_CP_CTYPE_DATASETS.' · '.$this->ctype['title']; - $grid = $this->loadDataGrid('ctype_datasets', [href_to('admin', 'ctypes', ['datasets_reorder', $ctype['id']]), href_to($this->name, 'ctypes', ['datasets_edit', '{id}'])]); + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_DATASET_ADD, + 'href' => $this->cms_template->href_to('ctypes', ['datasets_add', $this->ctype['id']]) + ], + [ + 'class' => 'view_list', + 'title' => LANG_CP_CTYPE_TO_LIST, + 'href' => $this->cms_template->href_to('ctypes') + ], + ]; - if ($this->request->isAjax()) { + $this->list_callback = function ($model) { - $this->model_backend_content->orderBy('ordering', 'asc'); + $model->filterEqual('ctype_id', $this->ctype['id']); - $datasets = $this->model_backend_content->getContentDatasets($ctype_id); + return $model; + }; - $this->cms_template->renderGridRowsJSON($grid, $datasets); + } - return $this->halt(); - } + public function renderListItemsGrid(){ - return $this->cms_template->render('ctypes_datasets', [ - 'ctype' => $ctype, - 'grid' => $grid + $this->dispatchEvent('ctype_loaded', [$this->ctype, 'datasets']); + + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_CTYPES_DATASETS, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] ]); + + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/ctypes_datasets_reorder.php b/system/controllers/admin/actions/ctypes_datasets_reorder.php deleted file mode 100755 index c3133899a..000000000 --- a/system/controllers/admin/actions/ctypes_datasets_reorder.php +++ /dev/null @@ -1,29 +0,0 @@ -request->get('items', []); - if (!$items) { - cmsCore::error404(); - } - - $this->model_backend_content->reorderContentDatasets($items); - - if ($this->request->isAjax()) { - - return $this->cms_template->renderJSON([ - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - ]); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - return $this->redirectBack(); - } - -} diff --git a/system/controllers/admin/actions/ctypes_datasets_toggle.php b/system/controllers/admin/actions/ctypes_datasets_toggle.php deleted file mode 100755 index b13821fec..000000000 --- a/system/controllers/admin/actions/ctypes_datasets_toggle.php +++ /dev/null @@ -1,35 +0,0 @@ -cms_template->renderJSON([ - 'error' => true - ]); - } - - $dataset = $this->model_backend_content->getContentDataset($dataset_id); - - if (!$dataset) { - - return $this->cms_template->renderJSON([ - 'error' => true - ]); - } - - $is_visible = $dataset['is_visible'] ? 0 : 1; - - $this->model_backend_content->toggleContentDatasetVisibility($dataset_id, $is_visible); - - return $this->cms_template->renderJSON([ - 'error' => false, - 'is_on' => $is_visible - ]); - } - -} diff --git a/system/controllers/admin/actions/ctypes_fields.php b/system/controllers/admin/actions/ctypes_fields.php index 5774fcf10..60e6a0d33 100755 --- a/system/controllers/admin/actions/ctypes_fields.php +++ b/system/controllers/admin/actions/ctypes_fields.php @@ -4,46 +4,75 @@ */ class actionAdminCtypesFields extends cmsAction { - public function run($ctype_id = null) { + use icms\traits\controllers\actions\listgrid { + renderListItemsGrid as private traitRenderListItemsGrid; + } - if (!$ctype_id) { - return cmsCore::error404(); - } + private $ctype = []; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $ctype_id = $params[0] ?? 0; - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + if (!$this->ctype) { return cmsCore::error404(); } - $this->dispatchEvent('ctype_loaded', [$ctype, 'fields']); + $this->table_name = $this->model->getContentTypeTableName($this->ctype['name']) . '_fields'; + $this->grid_name = 'ctype_fields'; + $this->grid_args = $this->ctype['name']; + $this->title = LANG_CP_CTYPE_FIELDS; - $grid = $this->loadDataGrid('ctype_fields', $ctype['name']); + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_FIELD_ADD, + 'href' => $this->cms_template->href_to('ctypes', ['fields_add', $this->ctype['id']]) + ], + [ + 'class' => 'view_list', + 'title' => LANG_CP_CTYPE_TO_LIST, + 'href' => $this->cms_template->href_to('ctypes') + ] + ]; - if ($this->request->isAjax()) { + $this->list_callback = function ($model) { - $filter = []; - $filter_str = cmsUser::getUPSActual('admin.grid_filter.ctypes_fields', $this->request->get('filter', '')); + $model->selectTranslatedField('i.values', $this->table_name, 'default'); - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model_backend_content->applyGridFilter($grid, $filter); - } + return $model; + }; - $this->model_backend_content->orderBy('ordering', 'asc'); + $this->item_callback = function ($item, $model) { - $fields = $this->model_backend_content->getContentFields($ctype['name'], false, false); + $field_class = 'field' . string_to_camel('_', $item['type']); - $fields = cmsEventsManager::hook('ctype_content_fields', $fields); + $handler = new $field_class($item['name']); - $this->cms_template->renderGridRowsJSON($grid, $fields); + $item['handler_title'] = $handler->getTitle(); - return $this->halt(); - } + return $item; + }; + } + + public function renderListItemsGrid(){ - return $this->cms_template->render('ctypes_fields', [ - 'ctype' => $ctype, - 'grid' => $grid + // Для того, чтобы сформировалось подменю типа контента, см system/controllers/admin/actions/ctypes.php + $this->dispatchEvent('ctype_loaded', [$this->ctype, 'fields']); + + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_CTYPES_FIELDS, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] ]); + + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/ctypes_filters.php b/system/controllers/admin/actions/ctypes_filters.php index bca5082b2..aca602cf3 100644 --- a/system/controllers/admin/actions/ctypes_filters.php +++ b/system/controllers/admin/actions/ctypes_filters.php @@ -4,48 +4,70 @@ */ class actionAdminCtypesFilters extends cmsAction { - public function run($ctype_id = null) { + use icms\traits\controllers\actions\listgrid { + getListItemsGridHtml as private traitgetListItemsGridHtml; + renderListItemsGrid as private traitRenderListItemsGrid; + } - if (!$ctype_id) { - return cmsCore::error404(); - } + private $ctype = []; + + public function __construct($controller, $params = []) { - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { + parent::__construct($controller, $params); + + $ctype_id = $params[0] ?? 0; + + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + if (!$this->ctype) { return cmsCore::error404(); } - $this->dispatchEvent('ctype_loaded', [$ctype, 'filters']); + $this->table_name = $this->model->getContentTypeTableName($this->ctype['name']) . '_filters'; + $this->grid_name = 'ctype_filters'; + $this->grid_args = ['ctype' => $this->ctype]; + $this->title = LANG_CP_CTYPE_FILTERS; + + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_FILTER_ADD, + 'href' => $this->cms_template->href_to('ctypes', ['filters_add', $this->ctype['id']]) + ], + [ + 'class' => 'view_list', + 'title' => LANG_CP_CTYPE_TO_LIST, + 'href' => $this->cms_template->href_to('ctypes') + ] + ]; + } - $table_exists = $this->model_backend_content->isFiltersTableExists($ctype['name']); + public function getListItemsGridHtml(){ - if (!$table_exists) { + if (!$this->model_backend_content->isFiltersTableExists($this->ctype['name'])) { - return $this->cms_template->render('ctypes_filters', [ - 'table_exists' => $table_exists, - 'ctype' => $ctype, - 'grid' => [] + return $this->cms_template->renderInternal($this, 'ctypes_filters_error', [ + 'ctype' => $this->ctype ]); } - $grid = $this->loadDataGrid('ctype_filters', ['ctype' => $ctype]); - - if ($this->request->isAjax()) { - - $this->model_backend_content->orderBy('id', 'asc'); - - $filters = $this->model_backend_content->getContentFilters($ctype['name']); + return $this->traitgetListItemsGridHtml(); + } - $this->cms_template->renderGridRowsJSON($grid, $filters); + public function renderListItemsGrid() { - return $this->halt(); - } + // Для того, чтобы сформировалось подменю типа контента, см system/controllers/admin/actions/ctypes.php + $this->dispatchEvent('ctype_loaded', [$this->ctype, 'filters']); - return $this->cms_template->render('ctypes_filters', [ - 'table_exists' => $table_exists, - 'ctype' => $ctype, - 'grid' => $grid + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_CTYPES_FILTERS, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] ]); + + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/ctypes_props.php b/system/controllers/admin/actions/ctypes_props.php index 8ebae1669..5b13bec8b 100755 --- a/system/controllers/admin/actions/ctypes_props.php +++ b/system/controllers/admin/actions/ctypes_props.php @@ -4,41 +4,131 @@ */ class actionAdminCtypesProps extends cmsAction { - public function run($ctype_id = null, $category_id = false) { + use icms\traits\controllers\actions\listgrid { + getListItemsGridHtml as private traitGetListItemsGridHtml; + } - if (!$ctype_id) { - return cmsCore::error404(); - } + private $ctype = []; + private $cookie_path_key = ''; + private $tree_path_key = ''; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $ctype_id = $params[0] ?? 0; - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + if (!$this->ctype) { return cmsCore::error404(); } - $this->dispatchEvent('ctype_loaded', [$ctype, 'props']); + $this->table_name = $this->model->getContentTypeTableName($this->ctype['name']) . '_props_bind'; + $this->grid_name = 'ctype_props'; + $this->grid_args = $this->cms_template->href_to('ctypes', ['props_reorder', $this->ctype['name']]); - $cats = $this->model_backend_content->getSubCategories($ctype['name']); + $this->tool_buttons = [ + [ + 'class' => 'menu d-xl-none', + 'data' => [ + 'toggle' =>'quickview', + 'toggle-element' => '#left-quickview' + ], + 'title' => LANG_CATEGORIES + ], + [ + 'class' => 'add d-none datagrid_change', + 'title' => LANG_CP_FIELD_ADD, + 'data' => [ + 'href' => $this->cms_template->href_to('ctypes', ['props_add', $this->ctype['id']]) + ] + ], + [ + 'class' => 'add_folder datagrid_change', + 'title' => LANG_CP_CONTENT_CATS_ADD, + 'data' => [ + 'href' => $this->cms_template->href_to('content', ['cats_add', $this->ctype['id']]) + ] + ], + [ + 'class' => 'edit_folder d-none datagrid_change', + 'title' => LANG_CP_CONTENT_CATS_EDIT, + 'data' => [ + 'href' => $this->cms_template->href_to('content', ['cats_edit', $this->ctype['id']]) + ] + ], + [ + 'class' => 'delete_folder d-none datagrid_change datagrid_csrf', + 'title' => LANG_DELETE_CATEGORY, + 'data' => [ + 'href' => $this->cms_template->href_to('content', ['cats_delete', $this->ctype['id']]) + ], + 'confirm' => LANG_DELETE_CATEGORY_CONFIRM + ] + ]; - $props = $this->model_backend_content->orderBy('title')->getContentProps($ctype['name']); + $this->cookie_path_key = 'props_'.$this->ctype['name'].'_tree_path'; + $this->tree_path_key = $this->ctype['id'].'.0'; - $grid = $this->loadDataGrid('ctype_props', $this->cms_template->href_to('ctypes', ['props_reorder', $ctype['name']])); + $default_category_id = 0; - if ($this->request->isAjax()) { + if (cmsUser::hasCookie($this->cookie_path_key)) { - $this->model_backend_content->orderBy('ordering', 'asc'); + $tree_key = ltrim(cmsUser::getCookie($this->cookie_path_key), '/'); - $fields = $this->model_backend_content->getContentPropsBinds($ctype['name'], $category_id); + if (preg_match('/^([0-9\/\.]+)$/i', $tree_key)) { - $this->cms_template->renderGridRowsJSON($grid, $fields); + $this->tree_path_key = $tree_key; - return $this->halt(); + $tree_keys = explode('/', $tree_key); + + $tree_key = explode('.', end($tree_keys)); + + $default_category_id = $tree_key[1] ?? 0; + } } - return $this->cms_template->render('ctypes_props', [ - 'ctype' => $ctype, - 'cats' => $cats, - 'props' => $props, - 'grid' => $grid + $category_id = $params[1] ?? $default_category_id; + + $this->list_callback = function ($model) use($category_id) { + + $model->selectOnly('p.*'); + $model->select('p.id', 'prop_id'); + $model->select('i.id', 'id'); + $model->select('i.cat_id', 'cat_id'); + + $model->join($model->table_prefix . $this->ctype['name'] . '_props', 'p', 'p.id = i.prop_id'); + + if ($category_id) { + $model->filterEqual('i.cat_id', $category_id); + } + + $model->groupBy('i.prop_id'); + + $model->limit(false); + + return $model; + }; + } + + public function getListItemsGridHtml() { + + // Для того, чтобы сформировалось подменю типа контента, см system/controllers/admin/actions/ctypes.php + $this->dispatchEvent('ctype_loaded', [$this->ctype, 'props']); + + $cats = $this->model_backend_content->getSubCategories($this->ctype['name']); + + $props = $this->model_backend_content->orderBy('title')->getContentProps($this->ctype['name']); + + $grid_html = $this->traitGetListItemsGridHtml(); + + return $this->cms_template->renderInternal($this, 'ctypes_props', [ + 'cookie_path_key' => $this->cookie_path_key, + 'tree_path_key' => $this->tree_path_key, + 'ctype' => $this->ctype, + 'cats' => $cats, + 'props' => $props, + 'grid_html' => $grid_html ]); } diff --git a/system/controllers/admin/actions/ctypes_props_bind.php b/system/controllers/admin/actions/ctypes_props_bind.php index b64887b58..e8815c845 100755 --- a/system/controllers/admin/actions/ctypes_props_bind.php +++ b/system/controllers/admin/actions/ctypes_props_bind.php @@ -35,9 +35,11 @@ public function run($ctype_id = null, $category_id = null) { $this->model_backend_content->bindContentProp($ctype['name'], $prop_id, $cats); - cmsUser::addSessionMessage(LANG_CP_PROPS_BIND_SC, 'success'); - - return $this->redirectToAction('ctypes', ['props', $ctype_id]); + return $this->cms_template->renderJSON([ + 'errors' => false, + 'success_text' => LANG_CP_PROPS_BIND_SC, + 'callback' => 'icms.adminProps.propBinded' + ]); } } diff --git a/system/controllers/admin/actions/ctypes_relations.php b/system/controllers/admin/actions/ctypes_relations.php index f95423fb3..66b346339 100755 --- a/system/controllers/admin/actions/ctypes_relations.php +++ b/system/controllers/admin/actions/ctypes_relations.php @@ -4,35 +4,61 @@ */ class actionAdminCtypesRelations extends cmsAction { - public function run($ctype_id = null) { + use icms\traits\controllers\actions\listgrid { + renderListItemsGrid as private traitRenderListItemsGrid; + } - if (!$ctype_id) { - return cmsCore::error404(); - } + private $ctype = []; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { + $ctype_id = $params[0] ?? 0; + + $this->ctype = $this->model_backend_content->getContentType($ctype_id); + if (!$this->ctype) { return cmsCore::error404(); } - $grid = $this->loadDataGrid('ctype_relations', href_to('admin', 'ctypes', ['relations_reorder', $ctype['id']])); + $this->table_name = 'content_relations'; + $this->grid_name = 'ctype_relations'; + $this->title = LANG_CP_CTYPE_RELATIONS; - if ($this->request->isAjax()) { + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_RELATION_ADD, + 'href' => $this->cms_template->href_to('ctypes', ['relations_add', $this->ctype['id']]) + ], + [ + 'class' => 'view_list', + 'title' => LANG_CP_CTYPE_TO_LIST, + 'href' => $this->cms_template->href_to('ctypes') + ] + ]; - $relations = $this->model_backend_content->getContentRelations($ctype_id); + $this->list_callback = function ($model) { - $this->cms_template->renderGridRowsJSON($grid, $relations); + return $model->filterEqual('ctype_id', $this->ctype['id']); + }; + } - return $this->halt(); - } + public function renderListItemsGrid(){ // Для того, чтобы сформировалось подменю типа контента, см system/controllers/admin/actions/ctypes.php - $this->dispatchEvent('ctype_loaded', [$ctype, 'relations']); + $this->dispatchEvent('ctype_loaded', [$this->ctype, 'relations']); - return $this->cms_template->render('ctypes_relations', [ - 'ctype' => $ctype, - 'grid' => $grid + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_CTYPES_RELATIONS, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] ]); + + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/ctypes_relations_reorder.php b/system/controllers/admin/actions/ctypes_relations_reorder.php deleted file mode 100755 index b9d935a8a..000000000 --- a/system/controllers/admin/actions/ctypes_relations_reorder.php +++ /dev/null @@ -1,29 +0,0 @@ -request->get('items', []); - if (!$items) { - return cmsCore::error404(); - } - - $this->model_backend_content->reorderContentRelation($items); - - if ($this->request->isAjax()) { - - return $this->cms_template->renderJSON([ - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - ]); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - return $this->redirectBack(); - } - -} diff --git a/system/controllers/admin/actions/inline_save.php b/system/controllers/admin/actions/inline_save.php index cb043c157..410fc58ec 100755 --- a/system/controllers/admin/actions/inline_save.php +++ b/system/controllers/admin/actions/inline_save.php @@ -1,5 +1,9 @@ table_name = 'menu_items'; + $this->grid_name = 'menu_items'; + + $this->external_action_prefix = 'menu_'; + + $this->toolbar_hook = 'admin_menu_toolbar'; + + $this->tool_buttons = [ + [ + 'class' => 'menu d-xl-none', + 'data' => [ + 'toggle' =>'quickview', + 'toggle-element' => '#left-quickview' + ], + 'title' => LANG_MENU + ], + [ + 'class' => 'add_item', + 'icon' => 'plus-circle', + 'title' => LANG_CP_MENU_ITEM_ADD, + 'href' => $this->cms_template->href_to('menu', ['item_add', 1, 0]) + ], + [ + 'class' => 'add_menu', + 'icon' => 'folder-plus', + 'title' => LANG_CP_MENU_ADD, + 'href' => $this->cms_template->href_to('menu', ['add']) + ], + [ + 'class' => 'edit_menu', + 'icon' => 'edit', + 'title' => LANG_CP_MENU_EDIT, + 'href' => $this->cms_template->href_to('menu', ['edit']) + ], + [ + 'class' => 'delete_menu', + 'icon' => 'minus-circle', + 'title' => LANG_CP_MENU_DELETE, + 'confirm' => LANG_CP_MENU_DELETE_CONFIRM, + 'href' => $this->cms_template->href_to('menu', ['delete']) + ] + ]; + + $tree_key = $params[0] ?? ltrim(cmsUser::getCookie('menu_tree_path'), '/'); - // если нужно, передаем управление другому экшену - if ($do) { - $this->runExternalAction('menu_' . $do, array_slice($this->params, 1)); - return; + if (!preg_match('/^([0-9\.]+)$/i', $tree_key)) { + $tree_key = '1.0'; } - $menu_model = cmsCore::getModel('menu'); + $tree_key = explode('.', $tree_key); + + $menu_id = $tree_key[0] ?? 1; + $parent_id = $tree_key[1] ?? 0; + + $this->list_callback = function ($model) use ($menu_id, $parent_id) { + + $model->filterEqual('menu_id', $menu_id); + + $model->filterEqual('parent_id', $parent_id); + + $model->limit(false); + + return $model; + }; + } + + public function getListItemsGridHtml() { - $menus = $menu_model->getMenus(); + $menus = $this->model_menu->getMenus(); - $grid = $this->loadDataGrid('menu_items'); + $grid_html = $this->traitGetListItemsGridHtml(); - return $this->cms_template->render('menu', [ - 'menus' => $menus, - 'grid' => $grid + return $this->cms_template->renderInternal($this, 'menu', [ + 'menus' => $menus, + 'grid_html' => $grid_html ]); } diff --git a/system/controllers/admin/actions/menu_delete.php b/system/controllers/admin/actions/menu_delete.php index 58d72510a..2930b5831 100755 --- a/system/controllers/admin/actions/menu_delete.php +++ b/system/controllers/admin/actions/menu_delete.php @@ -1,26 +1,39 @@ request->get('csrf_token', ''))) { + return cmsCore::error404(); + } - $menu = $menu_model->getMenu($id); + $menu = $this->model_menu->getMenu($id); + + if (!$menu) { + return cmsCore::error404(); + } if ($menu['is_fixed']) { + cmsUser::addSessionMessage(LANG_CP_MENU_IS_FIXED); - $this->redirectBack(); + + return $this->redirectToAction('menu'); } - $menu_model->deleteMenu($id); + $this->model_menu->deleteMenu($id); cmsUser::setCookiePublic('menu_tree_path', '1.0'); - $this->redirectToAction('menu'); + cmsUser::addSessionMessage(LANG_DELETE_SUCCESS, 'success'); + return $this->redirectToAction('menu'); } } diff --git a/system/controllers/admin/actions/menu_edit.php b/system/controllers/admin/actions/menu_edit.php index d110b15f9..266ed385a 100755 --- a/system/controllers/admin/actions/menu_edit.php +++ b/system/controllers/admin/actions/menu_edit.php @@ -5,7 +5,11 @@ */ class actionAdminMenuEdit extends cmsAction { - public function run($id) { + public function run($id = false) { + + if (!$id) { + return cmsCore::error404(); + } $form = $this->getForm('menu', ['edit']); diff --git a/system/controllers/admin/actions/menu_item_delete.php b/system/controllers/admin/actions/menu_item_delete.php index 02e71bcc0..805c22738 100755 --- a/system/controllers/admin/actions/menu_item_delete.php +++ b/system/controllers/admin/actions/menu_item_delete.php @@ -2,20 +2,21 @@ class actionAdminMenuItemDelete extends cmsAction { - public function run($id){ + public function run($id = false) { - if (!$id) { cmsCore::error404(); } + if (!$id) { + return cmsCore::error404(); + } - if (!cmsForm::validateCSRFToken( $this->request->get('csrf_token', '') )){ - cmsCore::error404(); + if (!cmsForm::validateCSRFToken($this->request->get('csrf_token', ''))) { + return cmsCore::error404(); } $this->model_menu->deleteMenuItem($id); cmsUser::addSessionMessage(LANG_DELETE_SUCCESS, 'success'); - $this->redirectToAction('menu'); - + return $this->redirectToAction('menu'); } } diff --git a/system/controllers/admin/actions/menu_item_toggle.php b/system/controllers/admin/actions/menu_item_toggle.php deleted file mode 100644 index c7a3dfd8a..000000000 --- a/system/controllers/admin/actions/menu_item_toggle.php +++ /dev/null @@ -1,38 +0,0 @@ -cms_template->renderJSON([ - 'error' => true - ]); - } - - $item = $this->model_menu->getItemByField('menu_items', 'id', $id); - if (!$item) { - - return $this->cms_template->renderJSON([ - 'error' => true - ]); - } - - $is_pub = $item['is_enabled'] ? 0 : 1; - - $this->model_menu->update('menu_items', $id, [ - 'is_enabled' => $is_pub - ]); - - cmsCache::getInstance()->clean('menu.items'); - - return $this->cms_template->renderJSON([ - 'error' => false, - 'is_on' => $is_pub - ]); - } - -} diff --git a/system/controllers/admin/actions/menu_items_ajax.php b/system/controllers/admin/actions/menu_items_ajax.php deleted file mode 100755 index 42dc1996c..000000000 --- a/system/controllers/admin/actions/menu_items_ajax.php +++ /dev/null @@ -1,24 +0,0 @@ -request->isAjax()) { - return cmsCore::error404(); - } - - $grid = $this->loadDataGrid('menu_items'); - - $items = $this->model_menu->getMenuItems($menu_id, $parent_id); - - $total = $items ? 1 : 0; - - $this->cms_template->renderGridRowsJSON($grid, $items, $total); - - return $this->halt(); - } - -} diff --git a/system/controllers/admin/actions/menu_items_reorder.php b/system/controllers/admin/actions/menu_items_reorder.php deleted file mode 100755 index c0e9296f3..000000000 --- a/system/controllers/admin/actions/menu_items_reorder.php +++ /dev/null @@ -1,21 +0,0 @@ -request->get('items', array()); - if (!$items){ cmsCore::error404(); } - - cmsCore::getModel('menu')->reorderMenuItems($items); - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/admin/actions/reorder.php b/system/controllers/admin/actions/reorder.php index 25fd14b88..fda3db596 100755 --- a/system/controllers/admin/actions/reorder.php +++ b/system/controllers/admin/actions/reorder.php @@ -20,7 +20,7 @@ public function run($table_name) { $this->model->reorderByList($table_name, $items); - $cache_keys = explode('_', $table_name); + $cache_keys = explode('_', str_replace(['{', '}'], '', $table_name)); cmsCache::getInstance()->clean(implode('.', $cache_keys)); diff --git a/system/controllers/admin/actions/settings_scheduler.php b/system/controllers/admin/actions/settings_scheduler.php index e043f70b8..54b3ca808 100755 --- a/system/controllers/admin/actions/settings_scheduler.php +++ b/system/controllers/admin/actions/settings_scheduler.php @@ -2,20 +2,46 @@ class actionAdminSettingsScheduler extends cmsAction { - public function run($do = false) { + use icms\traits\controllers\actions\listgrid { + renderListItemsGrid as private traitRenderListItemsGrid; + } + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $this->table_name = 'scheduler_tasks'; + $this->grid_name = 'scheduler'; + $this->title = LANG_CP_SCHEDULER; - // если нужно, передаем управление другому экшену - if ($do){ - $this->runExternalAction('settings_scheduler_'.$do, array_slice($this->params, 1)); - return; - } + $this->external_action_prefix = 'settings_scheduler_'; + + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_SCHEDULER_TASK_ADD, + 'href' => $this->cms_template->href_to('settings', ['scheduler', 'add']) + ] + ]; + + $this->cms_template->addBreadcrumb(LANG_CP_SECTION_SETTINGS, $this->cms_template->href_to('settings')); + $this->cms_template->addBreadcrumb(LANG_CP_SCHEDULER, $this->cms_template->href_to('settings', ['scheduler'])); + + $this->cms_template->addMenuItems('admin_toolbar', $this->getSettingsMenu()); + } - $grid = $this->loadDataGrid('scheduler', false, 'admin.grid_filter.set_scheduler'); + public function renderListItemsGrid(){ - return $this->cms_template->render('settings_scheduler', array( - 'grid' => $grid - )); + $this->cms_template->addMenuItem('breadcrumb-menu', [ + 'title' => LANG_HELP, + 'url' => LANG_HELP_URL_SETTINGS_SCHEDULER, + 'options' => [ + 'target' => '_blank', + 'icon' => 'question-circle' + ] + ]); + return $this->traitRenderListItemsGrid(); } } diff --git a/system/controllers/admin/actions/settings_scheduler_add.php b/system/controllers/admin/actions/settings_scheduler_add.php index 22fafb077..440e42031 100755 --- a/system/controllers/admin/actions/settings_scheduler_add.php +++ b/system/controllers/admin/actions/settings_scheduler_add.php @@ -4,7 +4,7 @@ class actionAdminSettingsSchedulerAdd extends cmsAction { public function run() { - $form = $this->getForm('scheduler_task', array('add')); + $form = $this->getForm('scheduler_task', ['add']); $task = []; @@ -20,22 +20,20 @@ public function run() { cmsUser::addSessionMessage(LANG_CP_SAVE_SUCCESS, 'success'); - $this->redirectToAction('settings', array('scheduler')); + $this->redirectToAction('settings', ['scheduler']); } if ($errors) { cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error'); } - } - return $this->cms_template->render('settings_scheduler_task', array( + return $this->cms_template->render('settings_scheduler_task', [ 'do' => 'add', 'task' => $task, 'form' => $form, 'errors' => isset($errors) ? $errors : false - )); - + ]); } } diff --git a/system/controllers/admin/actions/settings_scheduler_ajax.php b/system/controllers/admin/actions/settings_scheduler_ajax.php deleted file mode 100755 index 6cf5467dd..000000000 --- a/system/controllers/admin/actions/settings_scheduler_ajax.php +++ /dev/null @@ -1,39 +0,0 @@ -request->isAjax()) { cmsCore::error404(); } - - $grid = $this->loadDataGrid('scheduler'); - - $filter = array(); - $filter_str = $this->request->get('filter', ''); - - $filter_str = cmsUser::getUPSActual('admin.grid_filter.set_scheduler', $filter_str); - - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } - - $grid['filter'] = $filter; - - $total = $this->model->getSchedulerTasksCount(); - - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - - $this->model->setPerPage($perpage); - - $pages = ceil($total / $perpage); - - $tasks = $this->model->getSchedulerTasks(); - - $this->cms_template->renderGridRowsJSON($grid, $tasks, $total, $pages); - - $this->halt(); - - } - -} diff --git a/system/controllers/admin/actions/settings_scheduler_delete.php b/system/controllers/admin/actions/settings_scheduler_delete.php index c84963b22..bb3ab6ce8 100755 --- a/system/controllers/admin/actions/settings_scheduler_delete.php +++ b/system/controllers/admin/actions/settings_scheduler_delete.php @@ -2,19 +2,14 @@ class actionAdminSettingsSchedulerDelete extends cmsAction { - public function run($id){ + use icms\traits\controllers\actions\deleteItem; - if (!$id) { cmsCore::error404(); } + public function __construct($controller, $params = []) { - if (!cmsForm::validateCSRFToken( $this->request->get('csrf_token', '') )){ - cmsCore::error404(); - } + parent::__construct($controller, $params); - $this->model->deleteSchedulerTask($id); - - cmsUser::addSessionMessage(LANG_DELETE_SUCCESS, 'success'); - - $this->redirectToAction('settings', array('scheduler')); + $this->table_name = 'scheduler_tasks'; + $this->success_url = $this->cms_template->href_to('settings', 'scheduler'); } diff --git a/system/controllers/admin/actions/settings_scheduler_edit.php b/system/controllers/admin/actions/settings_scheduler_edit.php index aca583c98..4e533bfa4 100755 --- a/system/controllers/admin/actions/settings_scheduler_edit.php +++ b/system/controllers/admin/actions/settings_scheduler_edit.php @@ -4,15 +4,17 @@ class actionAdminSettingsSchedulerEdit extends cmsAction { public function run($id = false) { - if (!$id) { cmsCore::error404(); } + if (!$id) { + return cmsCore::error404(); + } - $form = $this->getForm('scheduler_task', array('edit')); + $form = $this->getForm('scheduler_task', ['edit']); $task = $this->model->getSchedulerTask($id); if ($this->request->has('submit')) { - $task = $form->parse($this->request, true); + $task = $form->parse($this->request, true); $errors = $form->validate($this, $task); if (!$errors) { @@ -21,22 +23,20 @@ public function run($id = false) { cmsUser::addSessionMessage(LANG_CP_SAVE_SUCCESS, 'success'); - $this->redirectToAction('settings', array('scheduler')); + $this->redirectToAction('settings', ['scheduler']); } if ($errors) { cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error'); } - } - return $this->cms_template->render('settings_scheduler_task', array( + return $this->cms_template->render('settings_scheduler_task', [ 'do' => 'edit', 'task' => $task, 'form' => $form, 'errors' => isset($errors) ? $errors : false - )); - + ]); } } diff --git a/system/controllers/admin/actions/settings_scheduler_toggle.php b/system/controllers/admin/actions/settings_scheduler_toggle.php deleted file mode 100755 index 70c53e2db..000000000 --- a/system/controllers/admin/actions/settings_scheduler_toggle.php +++ /dev/null @@ -1,31 +0,0 @@ -cms_template->renderJSON(array( - 'error' => true - )); - } - - $task = $this->model->getSchedulerTask($id); - if (!$task) { - return $this->cms_template->renderJSON(array( - 'error' => true - )); - } - - $is_active = $task['is_active'] ? 0 : 1; - - $this->model->toggleSchedulerPublication($id, $is_active); - - return $this->cms_template->renderJSON(array( - 'error' => false, - 'is_on' => $is_active - )); - - } - -} diff --git a/system/controllers/admin/actions/settings_switch_template.php b/system/controllers/admin/actions/settings_switch_template.php new file mode 100755 index 000000000..78993468e --- /dev/null +++ b/system/controllers/admin/actions/settings_switch_template.php @@ -0,0 +1,23 @@ +update('template_admin', $name); + + if (!$result) { + cmsUser::addSessionMessage(LANG_CP_SETTINGS_NOT_WRITABLE, 'error'); + } + + return $this->redirectToAction(''); + } + +} diff --git a/system/controllers/admin/actions/users.php b/system/controllers/admin/actions/users.php index d85aa0902..11a89c9c2 100755 --- a/system/controllers/admin/actions/users.php +++ b/system/controllers/admin/actions/users.php @@ -4,65 +4,100 @@ */ class actionAdminUsers extends cmsAction { - public function run($do = false) { + use icms\traits\controllers\actions\listgrid { + getListItemsGridHtml as private traitGetListItemsGridHtml; + } - // если нужно, передаем управление другому экшену - if ($do && !is_numeric($do)) { - $this->runExternalAction('users_' . $do, array_slice($this->params, 1)); - return; + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $this->table_name = '{users}'; + $this->grid_name = 'users'; + + $this->external_action_prefix = 'users_'; + + $this->toolbar_hook = 'admin_users_toolbar'; + + $this->tool_buttons = [ + [ + 'class' => 'menu d-xl-none', + 'data' => [ + 'toggle' =>'quickview', + 'toggle-element' => '#left-quickview' + ], + 'title' => LANG_GROUPS + ], + [ + 'class' => 'users_add', + 'icon' => 'user-plus', + 'title' => LANG_CP_USER_ADD, + 'href' => null + ], + [ + 'class' => 'users_group', + 'icon' => 'users', + 'childs_count' => 3, + 'title' => LANG_GROUP, + 'href' => '' + ], + [ + 'icon' => 'folder-plus', + 'level' => 2, + 'title' => LANG_CP_USER_GROUP_ADD, + 'href' => $this->cms_template->href_to('users', 'group_add') + ], + [ + 'class' => 'edit_user', + 'icon' => 'pen', + 'level' => 2, + 'title' => LANG_CP_USER_GROUP_EDIT, + 'href' => null + ], + [ + 'class' => 'delete_user', + 'icon' => 'times', + 'level' => 2, + 'title' => LANG_CP_USER_GROUP_DELETE, + 'href' => null, + 'onclick' => "return confirm('".LANG_CP_USER_GROUP_DELETE_CONFIRM."')" + ], + [ + 'class' => 'group_perms d-none', + 'icon' => 'user-shield', + 'title' => LANG_CP_USER_GROUP_PERMS, + 'href' => null + ] + ]; + + $group_id = $params[0] ?? ltrim(cmsUser::getCookie('users_tree_path'), '/'); + + if (!preg_match('/^([0-9]+)$/i', $group_id)) { + $group_id = 0; } - $groups = $this->model_users->getGroups(); - $groups = array_pad($groups, (count($groups) + 1) * -1, ['id' => 0, 'title' => LANG_ALL]); - - $grid = $this->loadDataGrid('users', false, 'admin.grid_filter.users'); - - if ($this->request->isAjax()) { - - $this->model_users->setPerPage(admin::perpage); - - $filter = []; - $filter_str = $this->request->get('filter', ''); - - $filter_str = cmsUser::getUPSActual('admin.grid_filter.users', $filter_str); - - if ($filter_str) { - - $this->model_users->setTablePrefix(''); + $this->list_callback = function ($model) use ($group_id) { - parse_str($filter_str, $filter); - - $this->model_users->applyGridFilter($grid, $filter); - - if (!empty($filter['advanced_filter'])) { - - parse_str($filter['advanced_filter'], $dataset_filters); - - $this->model_users->applyDatasetFilters($dataset_filters); - } - } - - // тут id группы - if ($do) { - $this->model_users->filterGroup($do); + if ($group_id) { + $model->join('{users}_groups_members', 'm', "m.user_id = i.id AND m.group_id = '{$group_id}'"); } - $this->model_users->disableDeleteFilter(); + $model->joinSessionsOnline('i'); - $total = $this->model_users->getUsersCount(); - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - $pages = ceil($total / $perpage); + return $model; + }; + } - $users = $this->model_users->getUsers(); + public function getListItemsGridHtml() { - $this->cms_template->renderGridRowsJSON($grid, $users, $total, $pages); + $groups = $this->model_users->getGroups(); + $groups = array_pad($groups, (count($groups) + 1) * -1, ['id' => 0, 'title' => LANG_ALL]); - $this->halt(); - } + $grid_html = $this->traitGetListItemsGridHtml(); - return $this->cms_template->render('users', [ - 'groups' => $groups, - 'grid' => $grid + return $this->cms_template->renderInternal($this, 'users', [ + 'groups' => $groups, + 'grid_html' => $grid_html ]); } diff --git a/system/controllers/admin/actions/users_filter.php b/system/controllers/admin/actions/users_filter.php index 8db0b5c62..414394a08 100755 --- a/system/controllers/admin/actions/users_filter.php +++ b/system/controllers/admin/actions/users_filter.php @@ -2,34 +2,33 @@ class actionAdminUsersFilter extends cmsAction { - public function run($group_id = false){ + public function run() { - $fields = cmsCore::getModel('content')->setTablePrefix('')->getContentFields('{users}'); + $fields = cmsCore::getModel('content')->setTablePrefix('')->getContentFields('{users}'); - $fields[] = array( - 'title' => LANG_RATING, - 'name' => 'rating', + $fields[] = [ + 'title' => LANG_RATING, + 'name' => 'rating', 'handler' => new fieldNumber('rating') - ); + ]; - $fields[] = array( - 'title' => LANG_KARMA, - 'name' => 'karma', + $fields[] = [ + 'title' => LANG_KARMA, + 'name' => 'karma', 'handler' => new fieldNumber('karma') - ); + ]; - $fields[] = array( - 'title' => LANG_USER_IS_ADMIN, - 'name' => 'is_admin', + $fields[] = [ + 'title' => LANG_USER_IS_ADMIN, + 'name' => 'is_admin', 'handler' => new fieldCheckbox('is_admin') - ); + ]; - $fields = cmsEventsManager::hook('admin_users_filter', $fields); + $fields = cmsEventsManager::hook('admin_users_filter', $fields); - return $this->cms_template->render('users_filter', array( + return $this->cms_template->render('grid_advanced_filter', [ 'fields' => $fields - )); - + ]); } } diff --git a/system/controllers/admin/frontend.php b/system/controllers/admin/frontend.php index 4678a2966..44085eef5 100755 --- a/system/controllers/admin/frontend.php +++ b/system/controllers/admin/frontend.php @@ -1076,114 +1076,13 @@ public function getAddonsMethod($name, $params = [], $cacheable = false) { return $data; } - public function getContentGridColumnsSettings($ctype_id){ - - $ctype = $this->model_backend_content->getContentType($ctype_id); - if (!$ctype) { return false; } - - $fields = $this->model_backend_content->getContentFields($ctype['name']); - $fields = cmsEventsManager::hook('ctype_content_fields', $fields); - - $items = array( - 'system' => array( - 'title' => array('title' => LANG_TITLE,'filters' => array('exact'=>LANG_CP_GRID_COLYMNS_EXACT,'like'=>LANG_CP_GRID_COLYMNS_LIKE)), - 'date_pub' => array('title' => LANG_DATE,'filters' => array('date'=>LANG_CP_GRID_COLYMNS_DATE)), - 'is_approved' => array('title' => LANG_MODERATION), - 'is_pub' => array('title' => LANG_ON,'filters' => array('select'=>LANG_CP_GRID_COLYMNS_SELECT),'filter_select' => array('items'=>array(''=>LANG_SELECT,'1'=>LANG_ON,'0'=>LANG_OFF))), - 'user_nickname' => array('title' => LANG_AUTHOR,'filters' => array('exact'=>LANG_CP_GRID_COLYMNS_EXACT,'like'=>LANG_CP_GRID_COLYMNS_LIKE)) - ), - 'user' => array() - ); - if($ctype['is_rating']){ - $items['system']['rating'] = array('title' => LANG_RATING,'filters' => array('exact'=>LANG_CP_GRID_COLYMNS_EXACT,'like'=>LANG_CP_GRID_COLYMNS_LIKE)); - } - if($ctype['is_comments']){ - $items['system']['comments'] = array('title' => LANG_COMMENTS,'filters' => array('exact'=>LANG_CP_GRID_COLYMNS_EXACT,'like'=>LANG_CP_GRID_COLYMNS_LIKE)); - } - if(!empty($ctype['options']['hits_on'])){ - $items['system']['hits_count'] = array('title' => LANG_HITS,'filters' => array('exact'=>LANG_CP_GRID_COLYMNS_EXACT,'like'=>LANG_CP_GRID_COLYMNS_LIKE)); - } - foreach($fields as $key => $field){ - if(($field['is_fixed'] && isset($items['system'][$key])) || $key === 'user'){continue;} - - $type = $field['is_fixed'] ? 'system' : 'user'; - $items[$type][$key] = array('title' => $field['title'],'filters' => array(),'handlers' => array()); - if(in_array($field['type'], array('number','string','url','user'))){ - $items[$type][$key]['filters']['exact'] = LANG_CP_GRID_COLYMNS_EXACT; - } - if(in_array($field['type'], array('html','number','string','text','url','user'))){ - $items[$type][$key]['filters']['like'] = LANG_CP_GRID_COLYMNS_LIKE; - } - if(in_array($field['type'], array('html','text'))){ - $items[$type][$key]['handlers_only'] = LANG_CP_GRID_COLYMNS_CUT_TEXT; - $items[$type][$key]['handler_only'] = function($value, $item){return mb_substr(strip_tags($value), 0, 100);}; - } - if(strpos($key, 'date_') === 0){ - $items[$type][$key]['filters']['date'] = LANG_CP_GRID_COLYMNS_DATE; - } - if($field['type'] === 'checkbox'){ - $items[$type][$key]['filters']['select'] = LANG_CP_GRID_COLYMNS_SELECT; - $items[$type][$key]['filter_select'] = array('items'=>array(''=>LANG_SELECT,'1'=>LANG_ON,'0'=>LANG_OFF)); - $items[$type][$key]['handlers']['flag'] = LANG_CP_GRID_COLYMNS_FLAG; - }else - if($field['type'] === 'string'){ - $items[$type][$key]['handlers']['to_filter'] = LANG_CP_GRID_COLYMNS_TO_FILTER; - $items[$type][$key]['handler_to_filter'] = function($value, $item) use($key){return ''.$value.'';}; - }else - if($field['type'] === 'images'){ - $items[$type][$key]['handlers_only'] = LANG_CP_GRID_COLYMNS_IMAGES_NMB; - $items[$type][$key]['handler_only'] = function($value, $item){return $value ? count(!is_array($value) ? cmsModel::yamlToArray($value) : $value) : 0;}; - }else - if($field['type'] === 'image'){ - $items[$type][$key]['handlers_only'] = LANG_CP_GRID_COLYMNS_PREVIEW; - $presets = array($field['handler']->getOption('size_teaser'), $field['handler']->getOption('size_full')); - $items[$type][$key]['handler_only'] = function($value, $item) use($presets){ - if(!$value){return '';} - $value = !is_array($value) ? cmsModel::yamlToArray($value) : $value; - return html_image($value, $presets, '', array('class' => 'grid_image_preview img-thumbnail')); - }; - }else - if(in_array($field['type'], ['list', 'listbitmask', 'listmultiple'])){ - $items[$type][$key]['handlers_only'] = '—'; - $items[$type][$key]['handler_only'] = function($value, $item)use($field,$ctype){ - if(!$value){return '';} - $item['ctype'] = $ctype; - $item['ctype_name'] = $ctype['name']; - $field['handler']->setItem($item); - return $field['handler']->parseTeaser($value); - }; - }else - if($field['handler']->is_denormalization){ - $items[$type][$key]['handlers_only'] = '—'; - $items[$type][$key]['handler_only'] = function($value, $item)use($field){ - if(!$value){return '';} - return $item[$field['handler']->getDenormalName()]; - }; - } - } - return $items; - } - - public function getContentGridColumnsSettingsDefault(){ - return array( - 'system' => array( - 'title' => array('enabled' => true,'filter' => 'like'), - 'date_pub' => array('enabled' => true), - 'is_approved' => array('enabled' => true), - 'is_pub' => array('enabled' => true), - 'user_nickname' => array('enabled' => true) - ), - 'user' => array() - ); - } - - public function getSchemeColForm($do, $row, $col = []){ + public function getSchemeColForm($do, $row, $col = []) { $form = $this->getForm('widgets_cols', [$do, (!empty($col['id']) ? $col['id'] : 0), $row]); $col_scheme_options = cmsEventsManager::hookAll('admin_col_scheme_options', ['add', $row, []]); - if($col_scheme_options){ + if ($col_scheme_options) { foreach ($col_scheme_options as $controller_name => $fields) { foreach ($fields as $field) { $form->addField('basic', $field); @@ -1192,16 +1091,15 @@ public function getSchemeColForm($do, $row, $col = []){ } return $form; - } - public function getSchemeRowForm($do, $row, $col = []){ + public function getSchemeRowForm($do, $row, $col = []) { $form = $this->getForm('widgets_rows', [$do]); $row_scheme_options = cmsEventsManager::hookAll('admin_row_scheme_options', [$do, $row, $col]); - if($row_scheme_options){ + if ($row_scheme_options) { foreach ($row_scheme_options as $controller_name => $fields) { foreach ($fields as $field) { $form->addField('basic', $field); @@ -1210,7 +1108,6 @@ public function getSchemeRowForm($do, $row, $col = []){ } return $form; - } } diff --git a/system/controllers/admin/grids/grid_content_items.php b/system/controllers/admin/grids/grid_content_items.php index fb8bd58c2..aaca15739 100755 --- a/system/controllers/admin/grids/grid_content_items.php +++ b/system/controllers/admin/grids/grid_content_items.php @@ -1,130 +1,257 @@ false, - 'is_sortable' => true, - 'is_filter' => true, - 'is_pagination' => true, - 'is_columns_settings' => true, - 'is_draggable' => false, - 'is_selectable' => true, - 'order_by' => 'id', - 'order_to' => 'desc', - 'show_id' => true - ); - - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30, - 'filter' => 'exact' - ), - 'title' => array( - 'title' => LANG_TITLE, - 'href' => href_to($ctype_name, 'edit', '{id}') . '?back=' . href_to($controller->name, 'content'), +function grid_content_items($controller, $ctype) { + + $fields = $controller->model_backend_content->getContentFields($ctype['name']); + + $options = [ + 'advanced_filter' => $controller->cms_template->href_to('content', ['filter', $ctype['id']]), + 'is_sortable' => true, + 'is_filter' => true, + 'is_pagination' => true, + 'is_draggable' => false, + 'is_selectable' => true, + 'select_actions' => [ + [ + 'title' => LANG_CP_CONTENT_ITEMS_EDIT, + 'action' => 'open', + 'url' => $controller->cms_template->href_to('content', ['items_edit', '{0}']) + ], + [ + 'title' => LANG_MOVE, + 'action' => 'open', + 'url' => $controller->cms_template->href_to('content', ['item_move', '{0}', '{1}']) + ], + [ + 'title' => LANG_DELETE, + 'action' => 'submit', + 'confirm' => LANG_DELETE_SELECTED_CONFIRM, + 'url' => $controller->cms_template->href_to('content', ['item_delete', '{0}']) + ], + [ + 'title' => LANG_BASKET_DELETE, + 'action' => 'submit', + 'confirm' => LANG_TRASH_DELETE_SELECTED_CONFIRM, + 'url' => $controller->cms_template->href_to('content', ['item_trash_put', '{0}']) + ] + ], + 'order_by' => 'date_pub', + 'order_to' => 'desc', + 'show_id' => false + ]; + + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ + 'title' => LANG_TITLE, + 'href' => href_to($ctype['name'], 'edit', '{id}') . '?back=' . href_to($controller->name, 'content'), 'filter' => 'like' - ), - 'date_pub' => array( - 'title' => LANG_DATE, - 'class' => 'd-none d-lg-table-cell', - 'width' => 110, - 'handler' => function($value, $item){ - if($item['is_deleted']){ - return ''.html_date($value, true).''; - } + ], + 'date_pub' => [ + 'title' => LANG_DATE, + 'class' => 'd-none d-lg-table-cell', + 'switchable' => true, + 'filter' => 'date', + 'handler' => function ($value, $item) { return html_date($value, true); } - ), - 'is_approved' => array( - 'title' => LANG_MODERATION, - 'class' => 'd-none d-sm-table-cell', - 'width' => 150, - 'handler' => function($value, $item) use ($controller, $ctype_name){ - if($item['is_deleted']){ - $string = ''; - if($item['trash_date_expired']){ + ], + 'is_approved' => [ + 'title' => LANG_MODERATION, + 'class' => 'd-none d-sm-table-cell', + 'width' => 150, + 'switchable' => true, + 'handler' => function ($value, $item) use ($controller, $ctype) { + if ($item['is_deleted']) { + $string = ''; + if ($item['trash_date_expired']) { $expired = ((time() - strtotime($item['trash_date_expired'])) > 0) ? true : false; - $string .= sprintf(LANG_MODERATION_IN_TRASH_TIME, ($expired ? '-' : '').string_date_age_max($item['trash_date_expired'])); + $string .= sprintf(LANG_MODERATION_IN_TRASH_TIME, ($expired ? '-' : '') . string_date_age_max($item['trash_date_expired'])); } else { $string .= LANG_MODERATION_IN_TRASH; } $string .= ''; return $string; } - if($item['is_approved']){ - if($item['approved_by']){ + if ($item['is_approved']) { + if ($item['approved_by']) { return html_bool_span(LANG_MODERATION_SUCCESS, true); } else { return html_bool_span(LANG_MODERATION_NOT_NEEDED, true); } } else { - if(!empty($item['is_draft'])){ + if (!empty($item['is_draft'])) { return html_bool_span(LANG_CONTENT_DRAFT_NOTICE, false); } return html_bool_span(LANG_CONTENT_NOT_APPROVED, false); } } - ), - 'is_pub' => array( - 'title' => LANG_ON, - 'class' => 'd-none d-sm-table-cell', - 'width' => 40, - 'flag' => true, - 'flag_toggle' => href_to($controller->name, 'content', array('item_toggle', $ctype_name, '{id}')) - ), - 'user_nickname' => array( - 'title' => LANG_AUTHOR, - 'class' => 'd-none d-lg-table-cell', - 'href' => href_to('users', '{user_id}'), - 'order_by' => 'u.nickname', - ), - ); - - $actions = array( - array( - 'title' => LANG_VIEW, - 'class' => 'view', - 'href' => href_to($ctype_name, '{slug}.html') - ), - array( + ], + 'is_pub' => [ + 'title' => LANG_ON, + 'class' => 'd-none d-sm-table-cell', + 'width' => 40, + 'flag' => true, + 'switchable' => true, + 'flag_toggle' => href_to($controller->name, 'content', ['item_toggle', $ctype['name'], '{id}']) + ], + 'user_id' => [ + 'title' => LANG_AUTHOR, + 'class' => 'd-none d-lg-table-cell', + 'switchable' => true, + 'href' => href_to('users', '{user_id}'), + 'key_alias' => 'user_nickname', + 'order_by' => 'u.nickname' + ] + ]; + + if ($ctype['is_rating']) { + + $columns['rating'] = [ + 'title' => LANG_RATING, + 'filter' => 'exact', + 'switchable' => true, + 'disable' => true + ]; + } + if ($ctype['is_comments']) { + + $columns['comments'] = [ + 'title' => LANG_COMMENTS, + 'filter' => 'exact', + 'switchable' => true, + 'disable' => true + ]; + } + if (!empty($ctype['options']['hits_on'])) { + + $columns['hits_count'] = [ + 'title' => LANG_HITS, + 'filter' => 'exact', + 'switchable' => true, + 'disable' => true + ]; + } + + foreach ($fields as $name => $field) { + + if ($field['handler']->is_virtual || + $field['is_system'] || + $field['is_fixed'] || + isset($columns[$name])) { + continue; + } + + $filter = $filter_select = $handler = $flag = null; + if (in_array($field['type'], ['number', 'html', 'string', 'text', 'url'])) { + $filter = 'like'; + } + if (in_array($field['type'], ['date', 'age'])) { + $filter = 'date'; + } + if ($field['type'] === 'checkbox') { + $flag = true; + $filter = 'filled'; + $filter_select = ['items' => ['' => LANG_ALL, '1' => LANG_ON, '0' => LANG_OFF]]; + } + if (in_array($field['type'], ['html', 'text'])) { + $handler = function ($value, $item) { + return string_short($value, 100); + }; + } + if ($field['type'] === 'images') { + $handler = function ($value, $item) { + return $value ? count(!is_array($value) ? cmsModel::yamlToArray($value) : $value) : 0; + }; + } + if ($field['type'] === 'image') { + $presets = [$field['handler']->getOption('size_teaser'), $field['handler']->getOption('size_full')]; + $handler = function ($value, $item) use ($presets) { + if (!$value) { + return ''; + } + $value = !is_array($value) ? cmsModel::yamlToArray($value) : $value; + return html_image($value, $presets, '', ['class' => 'grid_image_preview img-thumbnail']); + }; + } + if (in_array($field['type'], ['list', 'listbitmask', 'listmultiple'])) { + + $filter = 'exact'; + $filter_select = ['items' => ['' => LANG_ALL] + $field['handler']->getListItems()]; + + $handler = function ($value, $item)use ($field, $ctype) { + if (!$value) { + return ''; + } + $item['ctype'] = $ctype; + $item['ctype_name'] = $ctype['name']; + $field['handler']->setItem($item); + return $field['handler']->parseTeaser($value); + }; + } + if ($field['handler']->is_denormalization) { + $handler = function ($value, $item)use ($field) { + if (!$value) { + return ''; + } + return $item[$field['handler']->getDenormalName()]; + }; + } + + $columns[$name] = [ + 'title' => $field['title'], + 'flag' => $flag, + 'filter' => $filter, + 'filter_select' => $filter_select, + 'handler' => $handler, + 'switchable' => true, + 'disable' => true + ]; + } + + $actions = [ + [ + 'title' => LANG_VIEW, + 'class' => 'view', + 'target' => '_blank', + 'href' => href_to($ctype['name'], '{slug}.html') + ], + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->name, 'content', array('item_edit', $ctype_name, '{id}')) . '?back=' . href_to($controller->name, 'content') - ), - array( - 'title' => LANG_RESTORE, - 'class' => 'basket_remove', - 'href' => href_to($ctype_name, 'trash_remove', '{id}') . '?back=' . href_to($controller->name, 'content'), + 'href' => href_to($controller->name, 'content', ['item_edit', $ctype['name'], '{id}']) . '?back=' . href_to($controller->name, 'content') + ], + [ + 'title' => LANG_RESTORE, + 'class' => 'basket_remove', + 'href' => href_to($ctype['name'], 'trash_remove', '{id}') . '?back=' . href_to($controller->name, 'content'), 'confirm' => LANG_CP_CONTENT_ITEM_RESTORE_CONFIRM, - 'handler' => function($row){ + 'handler' => function ($row) { return $row['is_deleted']; } - ), - array( - 'title' => LANG_BASKET_DELETE, - 'class' => 'basket_put', - 'href' => href_to($ctype_name, 'trash_put', '{id}') . '?back=' . href_to($controller->name, 'content'), + ], + [ + 'title' => LANG_BASKET_DELETE, + 'class' => 'basket_put', + 'href' => href_to($ctype['name'], 'trash_put', '{id}') . '?back=' . href_to($controller->name, 'content'), 'confirm' => LANG_CP_CONTENT_ITEM_BASKET_DELETE_CONFIRM, - 'handler' => function($row){ + 'handler' => function ($row) { return !$row['is_deleted']; } - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($ctype_name, 'delete', '{id}') . '?back=' . href_to($controller->name, 'content'), + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($ctype['name'], 'delete', '{id}') . '?back=' . href_to($controller->name, 'content'), 'confirm' => LANG_CP_CONTENT_ITEM_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } - diff --git a/system/controllers/admin/grids/grid_controllers.php b/system/controllers/admin/grids/grid_controllers.php index 66bd2fe36..0aa2697ea 100755 --- a/system/controllers/admin/grids/grid_controllers.php +++ b/system/controllers/admin/grids/grid_controllers.php @@ -1,100 +1,99 @@ false, - 'order_to' => false, + $options = [ + 'order_by' => false, + 'order_to' => false, 'is_pagination' => false - ); + ]; - $columns = array( - 'title' => array( + $columns = [ + 'title' => [ 'title' => LANG_TITLE, - 'href' => href_to($controller->name, 'controllers', array('edit', '{name}')), + 'href' => href_to($controller->name, 'controllers', ['edit', '{name}']), 'filter' => 'like', - 'href_handler' => function($item) { + 'href_handler' => function ($item) { return $item['is_backend']; } - ), - 'slug' => array( - 'title' => LANG_ADMIN_CONTROLLER_SLUG, - 'class' => 'd-none d-lg-table-cell', - 'width' => 300, - 'editable' => array( - 'table' => 'controllers', - 'attributes' => array('placeholder' => '{name}') - ), - 'handler' => function ($v, $row){ - if(!$v){ + ], + 'slug' => [ + 'title' => LANG_ADMIN_CONTROLLER_SLUG, + 'class' => 'd-none d-lg-table-cell', + 'editable' => [ + 'attributes' => ['placeholder' => '{name}'], + 'rules' => [ + ['sysname'] + ] + ], + 'handler' => function ($v, $row) { + if (!$v) { return $row['name']; } return $v; } - ), - 'is_enabled' => array( - 'title' => LANG_IS_ENABLED, - 'flag' => true, - 'flag_toggle' => href_to($controller->name, 'controllers', array('toggle', '{id}')), - 'width' => 70, - 'handler' => function ($v, $row) use ($denied){ - if(in_array($row['name'], $denied)){ - return ''; + ], + 'is_enabled' => [ + 'title' => LANG_IS_ENABLED, + 'flag' => true, + 'flag_toggle' => href_to($controller->name, 'controllers', ['toggle', '{id}']), + 'href_handler' => function ($row) use ($denied) { + if (in_array($row['name'], $denied)) { + return false; } - return $v; + return true; } - ), - 'version' => array( - 'title' => LANG_VERSION, - 'class' => 'd-none d-lg-table-cell', - 'width' => 70, + ], + 'version' => [ + 'title' => LANG_VERSION, + 'class' => 'd-none d-lg-table-cell', + 'width' => 70, 'filter' => 'like' - ), - 'author' => array( - 'title' => LANG_AUTHOR, - 'class' => 'd-none d-lg-table-cell', - 'width' => 250, - 'href' => '{url}', + ], + 'author' => [ + 'title' => LANG_AUTHOR, + 'class' => 'd-none d-lg-table-cell', + 'width' => 200, + 'href' => '{url}', 'filter' => 'like' - ) - ); + ] + ]; - $actions = array( - array( - 'title' => LANG_CP_PACKAGE_CONTENTS, - 'class' => 'view ajax-modal', - 'href' => href_to($controller->name, 'package_files_list', array('controllers', '{id}')), - 'handler' => function($row){ + $actions = [ + [ + 'title' => LANG_CP_PACKAGE_CONTENTS, + 'class' => 'view ajax-modal', + 'href' => href_to($controller->name, 'package_files_list', ['controllers', '{id}']), + 'handler' => function ($row) { return $row['files']; } - ), - array( - 'title' => LANG_CONFIG, - 'class' => 'config', - 'href' => href_to($controller->name, 'controllers', array('edit', '{name}')), - 'handler' => function($row){ + ], + [ + 'title' => LANG_CONFIG, + 'class' => 'config', + 'href' => href_to($controller->name, 'controllers', ['edit', '{name}']), + 'handler' => function ($row) { return $row['is_backend']; } - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', 'confirm' => LANG_CP_DELETE_COMPONENT_CONFIRM, - 'href' => href_to($controller->name, 'controllers_delete', array('{name}')), - 'handler' => function($row){ + 'href' => href_to($controller->name, 'controllers_delete', ['{name}']), + 'handler' => function ($row) { return $row['is_external']; } - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/admin/grids/grid_controllers_events.php b/system/controllers/admin/grids/grid_controllers_events.php index 77c3f3faf..3b5eca6d9 100644 --- a/system/controllers/admin/grids/grid_controllers_events.php +++ b/system/controllers/admin/grids/grid_controllers_events.php @@ -1,10 +1,11 @@ false, 'is_sortable' => false, 'is_filter' => true, 'is_draggable' => true, @@ -12,56 +13,48 @@ function grid_controllers_events ($controller){ 'is_pagination' => false, 'order_by' => 'ordering', 'order_to' => 'asc' - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30 - ), - 'event' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'event' => [ 'title' => LANG_EVENTS_EVENT_NAME, 'filter' => 'like' - ), - 'listener' => array( + ], + 'listener' => [ 'title' => LANG_EVENTS_LISTENER, - 'width' => 200, - 'class' => 'd-none d-lg-table-cell', - 'filter' => 'like', + 'width' => 280, + 'class' => 'd-none d-lg-table-cell', + 'filter' => 'in', 'filter_select' => array( - 'items' => function($name){ + 'items' => function ($name) { $admin_model = cmsCore::getModel('admin'); $admin_model->join('events', 'e', 'e.listener = i.name'); $controllers = $admin_model->groupBy('i.id')->getInstalledControllers(); - $items = ['' => '']; - foreach($controllers as $controller){ + $items = []; + foreach ($controllers as $controller) { $items[$controller['name']] = $controller['title']; } return $items; } ), - 'handler' => function($val, $row){ - return string_lang($val.'_CONTROLLER', $val); + 'handler' => function ($val, $row) { + return string_lang($val . '_CONTROLLER', $val); } - ), - 'ordering' => array( - 'title' => LANG_ORDER, - 'class' => 'd-none d-lg-table-cell', - 'width' => 70 - ), - 'is_enabled' => array( + ], + 'is_enabled' => [ 'title' => LANG_IS_ENABLED, 'flag' => true, - 'flag_toggle' => href_to($controller->name, 'controllers', array('events_toggle', '{id}')), + 'flag_toggle' => href_to($controller->name, 'controllers', ['events_toggle', '{id}']), 'width' => 80 - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, - 'actions' => array() - ); - + 'actions' => [] + ]; } diff --git a/system/controllers/admin/grids/grid_ctype_datasets.php b/system/controllers/admin/grids/grid_ctype_datasets.php index 6a3791b63..f696ce557 100755 --- a/system/controllers/admin/grids/grid_ctype_datasets.php +++ b/system/controllers/admin/grids/grid_ctype_datasets.php @@ -1,69 +1,70 @@ false, 'is_filter' => false, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $drag_save_url, + 'drag_save_url' => href_to('admin', 'reorder', ['content_datasets']), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'width' => 30 - ), - 'title' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ 'title' => LANG_CP_DATASET_TITLE, 'href' => $edit_url, - 'editable' => array( - 'table' => 'content_datasets' - ) - ), - 'max_count' => array( + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 100] + ] + ] + ], + 'max_count' => [ 'title' => LANG_LIST_LIMIT, - 'class' => 'd-none d-lg-table-cell', + 'class' => 'd-none d-lg-table-cell', 'width' => 130, - 'handler' => function($value, $row) { + 'handler' => function ($value, $row) { return $value ? $value : '—'; } - ), - 'name' => array( + ], + 'name' => [ 'title' => LANG_SYSTEM_NAME, 'class' => 'd-none d-lg-table-cell', 'width' => 150 - ), - 'is_visible' => array( + ], + 'is_visible' => [ 'title' => LANG_PUBLICATION, 'flag' => true, - 'flag_toggle' => href_to($controller->name, 'ctypes', array('datasets_toggle', '{id}')), + 'flag_toggle' => href_to('admin', 'toggle_item', ['{id}', 'content_datasets', 'is_visible']), 'width' => 90 - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', 'href' => $edit_url - ), - array( + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->name, 'ctypes', array('datasets_delete', '{id}')), + 'href' => href_to($controller->name, 'ctypes', ['datasets_delete', '{id}']), 'confirm' => LANG_CP_DATASET_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/admin/grids/grid_ctype_filters.php b/system/controllers/admin/grids/grid_ctype_filters.php index 123fffe92..c19bd3650 100755 --- a/system/controllers/admin/grids/grid_ctype_filters.php +++ b/system/controllers/admin/grids/grid_ctype_filters.php @@ -1,8 +1,8 @@ false, 'is_filter' => false, 'is_pagination' => false, @@ -10,46 +10,52 @@ function grid_ctype_filters($controller, $ctype = []){ 'order_by' => 'id', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'width' => 30 - ), - 'title' => array( - 'title' => LANG_TITLE, - 'href' => href_to($controller->name, 'ctypes', array('filters_add', $ctype['id'], '{id}', 'edit')) - ), - 'slug' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ + 'title' => LANG_TITLE, + 'href' => href_to($controller->name, 'ctypes', ['filters_add', $ctype['id'], '{id}', 'edit']), + 'editable' => [ + 'attributes' => ['placeholder' => '{title}'], + 'rules' => [ + ['required'], + ['max_length', 100] + ] + ] + ], + 'slug' => [ 'title' => LANG_SYSTEM_NAME, 'width' => 350 - ) - ); + ] + ]; - $actions = array( - array( - 'title' => LANG_VIEW, - 'class' => 'view', - 'href' => href_to(((cmsConfig::get('ctype_default') && in_array($ctype['name'], cmsConfig::get('ctype_default'))) ? '' : $ctype['name']), '{slug}') - ), - array( + $actions = [ + [ + 'title' => LANG_VIEW, + 'class' => 'view', + 'target' => '_blank', + 'href' => href_to(((cmsConfig::get('ctype_default') && in_array($ctype['name'], cmsConfig::get('ctype_default'))) ? '' : $ctype['name']), '{slug}') + ], + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->name, 'ctypes', array('filters_add', $ctype['id'], '{id}', 'edit')) - ), - array( + 'href' => href_to($controller->name, 'ctypes', ['filters_add', $ctype['id'], '{id}', 'edit']) + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->name, 'ctypes', array('filters_delete', $ctype['id'], '{id}')), + 'href' => href_to($controller->name, 'ctypes', ['filters_delete', $ctype['id'], '{id}']), 'confirm' => LANG_CP_FILTER_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/admin/grids/grid_ctype_props.php b/system/controllers/admin/grids/grid_ctype_props.php index 574a2c564..091e05746 100755 --- a/system/controllers/admin/grids/grid_ctype_props.php +++ b/system/controllers/admin/grids/grid_ctype_props.php @@ -2,7 +2,7 @@ function grid_ctype_props($controller, $drag_save_url){ - $options = array( + $options = [ 'is_sortable' => false, 'is_filter' => false, 'is_pagination' => false, @@ -11,66 +11,62 @@ function grid_ctype_props($controller, $drag_save_url){ 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30, - ), - 'title' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ 'title' => LANG_CP_FIELD_TITLE, - 'href' => href_to($controller->name, 'ctypes', array('props_edit', '{ctype_id}', '{prop_id}')), - ), - 'fieldset' => array( - 'title' => LANG_CP_FIELD_FIELDSET, - 'class' => 'd-none d-lg-table-cell', - 'handler' => function($value, $row){ + 'href' => href_to($controller->name, 'ctypes', ['props_edit', '{ctype_id}', '{prop_id}']) + ], + 'fieldset' => [ + 'title' => LANG_CP_FIELD_FIELDSET, + 'class' => 'd-none d-lg-table-cell', + 'handler' => function ($value, $row) { return $value ? $value : '—'; } - ), - 'is_in_filter' => array( - 'title' => LANG_FILTER, - 'class' => 'd-none d-lg-table-cell', - 'flag' => true, - 'flag_toggle' => href_to($controller->name, 'ctypes', array('props_toggle', '{ctype_id}', '{prop_id}')), - 'width' => 60, - ), - 'type' => array( - 'title' => LANG_CP_FIELD_TYPE, - 'width' => 150, - 'handler' => function($value, $row){ - return constant('LANG_PARSER_'.mb_strtoupper($value)); - }, - ), - ); + ], + 'is_in_filter' => [ + 'title' => LANG_FILTER, + 'class' => 'd-none d-lg-table-cell', + 'flag' => true, + 'flag_toggle' => href_to($controller->name, 'ctypes', ['props_toggle', '{ctype_id}', '{prop_id}']), + 'width' => 60 + ], + 'type' => [ + 'title' => LANG_CP_FIELD_TYPE, + 'width' => 150, + 'handler' => function ($value, $row) { + return constant('LANG_PARSER_' . mb_strtoupper($value)); + } + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->name, 'ctypes', array('props_edit', '{ctype_id}', '{prop_id}')) - ), - array( + 'href' => href_to($controller->name, 'ctypes', ['props_edit', '{ctype_id}', '{prop_id}']) + ], + [ 'title' => LANG_CP_PROPS_UNBIND, 'class' => 'unbind', - 'href' => href_to($controller->name, 'ctypes', array('props_unbind', '{ctype_id}', '{prop_id}', '{cat_id}')), + 'href' => href_to($controller->name, 'ctypes', ['props_unbind', '{ctype_id}', '{prop_id}', '{cat_id}']), 'confirm' => LANG_CP_PROPS_UNBIND_CONFIRM - ), - array( + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->name, 'ctypes', array('props_delete', '{ctype_id}', '{prop_id}')), + 'href' => href_to($controller->name, 'ctypes', ['props_delete', '{ctype_id}', '{prop_id}']), 'confirm' => LANG_CP_PROPS_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } - diff --git a/system/controllers/admin/grids/grid_ctype_relations.php b/system/controllers/admin/grids/grid_ctype_relations.php index c37aa4481..014878416 100755 --- a/system/controllers/admin/grids/grid_ctype_relations.php +++ b/system/controllers/admin/grids/grid_ctype_relations.php @@ -1,64 +1,61 @@ false, 'is_filter' => false, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $drag_save_url, + 'drag_save_url' => href_to('admin', 'reorder', ['content_relations']), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30, - ), - 'title' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ 'title' => LANG_CP_RELATION_TITLE, - 'href' => href_to($controller->name, 'ctypes', array('relations_edit', '{ctype_id}', '{id}')), - ), - 'layout' => array( - 'title' => LANG_CP_RELATION_LAYOUT_TYPE, - 'class' => 'd-none d-lg-table-cell', - 'handler' => function($value, $row){ + 'href' => href_to($controller->name, 'ctypes', ['relations_edit', '{ctype_id}', '{id}']), + ], + 'layout' => [ + 'title' => LANG_CP_RELATION_LAYOUT_TYPE, + 'class' => 'd-none d-lg-table-cell', + 'handler' => function ($value, $row) { return constant('LANG_CP_RELATION_LAYOUT_' . strtoupper($value)); } - ), - 'target_controller' => array( - 'title' => LANG_EVENTS_LISTENER, - 'width' => 100, - 'handler' => function($value, $row){ - return string_lang('LANG_'.strtoupper($value).'_CONTROLLER'); + ], + 'target_controller' => [ + 'title' => LANG_EVENTS_LISTENER, + 'width' => 100, + 'handler' => function ($value, $row) { + return string_lang('LANG_' . strtoupper($value) . '_CONTROLLER'); } - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->name, 'ctypes', array('relations_edit', '{ctype_id}', '{id}')) - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($controller->name, 'ctypes', array('relations_delete', '{id}')), + 'href' => href_to($controller->name, 'ctypes', ['relations_edit', '{ctype_id}', '{id}']) + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($controller->name, 'ctypes', ['relations_delete', '{id}']), 'confirm' => LANG_CP_RELATION_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/admin/grids/grid_menu_items.php b/system/controllers/admin/grids/grid_menu_items.php index 70d667d91..fd466fdfd 100755 --- a/system/controllers/admin/grids/grid_menu_items.php +++ b/system/controllers/admin/grids/grid_menu_items.php @@ -1,9 +1,8 @@ false, + $options = [ 'is_sortable' => false, 'is_filter' => false, 'is_pagination' => false, @@ -12,54 +11,48 @@ function grid_menu_items($controller){ 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'width' => 30, - ), - 'title' => array( - 'title' => LANG_CP_MENU_ITEM_TITLE, - 'width' => 250, - 'href' => href_to($controller->name, 'menu', array('item_edit', '{id}')), - 'editable' => array( - 'table' => 'menu_items' - ) - ), - 'url' => array( - 'title' => LANG_CP_MENU_ITEM_URL, - 'class' => 'd-none d-lg-table-cell', - 'editable' => array( - 'table' => 'menu_items' - ) - ), - 'is_enabled' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ + 'title' => LANG_CP_MENU_ITEM_TITLE, + 'width' => 250, + 'href' => href_to($controller->name, 'menu', ['item_edit', '{id}']), + 'editable' => [] + ], + 'url' => [ + 'title' => LANG_CP_MENU_ITEM_URL, + 'class' => 'd-none d-lg-table-cell', + 'editable' => [] + ], + 'is_enabled' => [ 'title' => LANG_IS_ENABLED, 'flag' => true, - 'flag_toggle' => href_to($controller->root_url, 'menu_item_toggle', array('{id}')), + 'flag_toggle' => href_to('admin', 'toggle_item', ['{id}', 'menu_items', 'is_enabled']), 'width' => 80 - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->name, 'menu', array('item_edit', '{id}')) - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($controller->name, 'menu', array('item_delete', '{id}')), + 'href' => href_to($controller->name, 'menu', ['item_edit', '{id}']) + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($controller->name, 'menu', ['item_delete', '{id}']), 'confirm' => LANG_CP_MENU_ITEM_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/admin/grids/grid_scheduler.php b/system/controllers/admin/grids/grid_scheduler.php index 9c7d6c43b..38860ca15 100755 --- a/system/controllers/admin/grids/grid_scheduler.php +++ b/system/controllers/admin/grids/grid_scheduler.php @@ -22,7 +22,7 @@ function grid_scheduler($controller) { 'title' => LANG_CP_SCHEDULER_TASK_CONTROLLER, 'class' => 'd-none d-lg-table-cell', 'width' => 150, - 'filter' => 'like', + 'filter' => 'exact', 'filter_select' => [ 'items' => function ($name)use ($controller) { @@ -31,7 +31,7 @@ function grid_scheduler($controller) { return $item['controller']; }, 'controller'); - $items = ['' => '']; + $items = ['' => LANG_ALL]; foreach ($controllers as $cont) { if(!empty($tasks_controllers[$cont['name']])){ $items[$cont['name']] = $cont['title']; @@ -51,7 +51,7 @@ function grid_scheduler($controller) { 'class' => 'd-none d-sm-table-cell', 'flag' => true, 'width' => 60, - 'flag_toggle' => href_to($controller->name, 'settings/scheduler', ['toggle', '{id}']) + 'flag_toggle' => href_to($controller->name, 'toggle_item', ['{id}', 'scheduler_tasks', 'is_active']), ], 'period' => [ 'title' => LANG_CP_SCHEDULER_TASK_PERIOD, diff --git a/system/controllers/admin/grids/grid_users.php b/system/controllers/admin/grids/grid_users.php index 6b36499dc..bce3798be 100755 --- a/system/controllers/admin/grids/grid_users.php +++ b/system/controllers/admin/grids/grid_users.php @@ -2,124 +2,131 @@ function grid_users($controller){ - $options = array( - 'is_auto_init' => false, - 'is_sortable' => true, - 'is_filter' => true, - 'is_pagination' => true, - 'is_draggable' => false, - 'order_by' => 'id', - 'order_to' => 'asc', - 'show_id' => true - ); + $options = [ + 'advanced_filter' => $controller->cms_template->href_to('users', ['filter']), + 'is_sortable' => true, + 'is_filter' => true, + 'is_pagination' => true, + 'is_draggable' => false, + 'order_by' => 'id', + 'order_to' => 'asc', + 'show_id' => false + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30, - 'filter' => 'exact' - ), - 'nickname' => array( - 'title' => LANG_NICKNAME, - 'href' => href_to($controller->name, 'users', array('edit', '{id}')), - 'filter' => 'like', - 'handler' => function($nickname, $user) { - if ($user['is_admin']) { - $nickname = '' . $nickname . ''; - } - return $nickname; + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'nickname' => [ + 'title' => LANG_NICKNAME, + 'href' => href_to($controller->name, 'users', ['edit', '{id}']), + 'filter' => 'like', + 'tooltip_handler' => function ($user) { + return $user['is_admin'] ? LANG_USER_IS_ADMIN : ''; + }, + 'handler' => function ($value, $user) { + return ''. + html_avatar_image($user['avatar'], 'micro', $user['nickname']) + .''.($user['is_admin'] ? ''.$value.'' : $value).''; } - ), - 'email' => array( - 'title' => LANG_EMAIL, - 'width' => 200, - 'filter' => 'like' - ), - 'ip' => array( - 'title' => LANG_USERS_PROFILE_LAST_IP, - 'width' => 130, - 'class' => 'd-none d-xxl-table-cell', - 'filter' => 'like', - 'handler' => function($value){ - if(!$value){ + ], + 'email' => [ + 'title' => LANG_EMAIL, + 'switchable' => true, + 'filter' => 'like' + ], + 'ip' => [ + 'title' => LANG_USERS_PROFILE_LAST_IP, + 'width' => 130, + 'class' => 'd-none d-xxl-table-cell', + 'filter' => 'like', + 'switchable' => true, + 'handler' => function ($value) { + if (!$value) { return ''; - } elseif(strpos($value, '127.') === 0){ + } elseif (strpos($value, '127.') === 0) { return $value; } $location = string_ip_to_location($value, true); - return '
'.$value.' '.(!empty($location['code']) ? ''.$location['code'].' ' : '').'
'; + return '
' . $value . ' ' . (!empty($location['code']) ? '' . $location['code'] . ' ' : '') . ''. html_svg_icon('solid', 'globe', 16, false).'
'; } - ), - 'date_reg' => array( - 'title' => LANG_REGISTRATION, - 'class' => 'd-none d-md-table-cell', - 'width' => 80, - 'filter' => 'date', - 'handler' => function($date, $user){ - $ld = $user['is_online'] ? LANG_ONLINE : LANG_USERS_PROFILE_LOGDATE.' '.string_date_age_max($user['date_log'], true); - return ''.html_date($date).''; + ], + 'date_reg' => [ + 'title' => LANG_REGISTRATION, + 'class' => 'd-none d-md-table-cell', + 'filter' => 'date', + 'switchable' => true, + 'tooltip_handler' => function ($user) { + return $user['is_online'] ? LANG_ONLINE : LANG_USERS_PROFILE_LOGDATE . ' ' . string_date_age_max($user['date_log'], true); + }, + 'handler' => function ($date, $user) { + return html_date($date); } - ), - 'karma' => array( - 'title' => LANG_KARMA, - 'class' => 'd-none d-xxl-table-cell', - 'width' => 60, - 'filter' => 'exact', - 'handler' => function($value){ - return ''.html_signed_num($value).''; + ], + 'karma' => [ + 'title' => LANG_KARMA, + 'class' => 'd-none d-xxl-table-cell', + 'width' => 60, + 'filter' => 'exact', + 'switchable' => true, + 'handler' => function ($value) { + return '' . html_signed_num($value) . ''; } - ), - 'rating' => array( - 'title' => LANG_RATING, - 'class' => 'd-none d-xxl-table-cell', - 'width' => 60, - 'filter' => 'exact' - ), - 'is_locked' => array( - 'title' => LANG_CP_USER_LOCKED, - 'class' => 'd-none d-sm-table-cell', - 'flag' => 'flag_lock', - 'width' => 24, - 'handler' => function($value, $user){ - $title = $user['is_locked'] ? ($user['lock_reason'] ? $user['lock_reason'] : LANG_TO.' '.strip_tags(html_date($user['lock_until']))) : ''; - return '
'.$value.'
'; + ], + 'rating' => [ + 'title' => LANG_RATING, + 'class' => 'd-none d-xxl-table-cell', + 'width' => 60, + 'switchable' => true, + 'filter' => 'exact' + ], + 'is_locked' => [ + 'title' => LANG_CP_USER_LOCKED, + 'class' => 'd-none d-sm-table-cell', + 'flag' => 'flag_lock', + 'width' => 24, + 'switchable' => true, + 'tooltip_handler' => function ($user) { + if (!$user['is_locked']) { + return ''; + } + return ($user['lock_reason'] ? $user['lock_reason'].', ' : '') . LANG_TO . ' ' . strip_tags(html_date($user['lock_until'])); } - ), - 'is_deleted' => array( - 'title' => LANG_ADMIN_IS_DELETED, - 'class' => 'd-none d-sm-table-cell', - 'width' => 24, - 'handler' => function($value, $user){ + ], + 'is_deleted' => [ + 'title' => LANG_ADMIN_IS_DELETED, + 'class' => 'd-none d-sm-table-cell', + 'width' => 24, + 'switchable' => true, + 'handler' => function ($value, $user) { return html_bool_span(($value ? LANG_YES : LANG_NO), !$value); } - ) - ); + ] + ]; - $actions = array( - array( - 'title' => LANG_PROFILE, - 'class' => 'view', - 'href' => href_to('users', '{id}') - ), - array( + $actions = [ + [ + 'title' => LANG_PROFILE, + 'target' => '_blank', + 'class' => 'view', + 'href' => href_to('users', '{id}') + ], + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to('users', '{id}', array('edit')) . '?back=' . href_to($controller->name, 'users') - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($controller->name, 'users', array('delete', '{id}')), + 'href' => href_to('users', '{id}', ['edit']) . '?back=' . href_to($controller->name, 'users') + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($controller->name, 'users', ['delete', '{id}']), 'confirm' => LANG_CP_USER_DELETE_CONFIRM - ), - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } - diff --git a/system/controllers/admin/hooks/grid_admin_content_items_args.php b/system/controllers/admin/hooks/grid_admin_content_items_args.php deleted file mode 100644 index 4738c1af0..000000000 --- a/system/controllers/admin/hooks/grid_admin_content_items_args.php +++ /dev/null @@ -1,101 +0,0 @@ -request->isAjax()){ return $data; } - - list($grid, $args) = $data; - - $ctype_name = $args[1]; - - $content_model = cmsCore::getModel('content'); - - $ctype = $content_model->getContentTypeByName($ctype_name); - - $saved = cmsUser::getUPS('admin.grid_columns.content.' . $ctype['id']); - - if (!$saved) { - return $data; - } - - $controller = $args[0]; - $content_table = $content_model->table_prefix . $ctype['name']; - - $settings = $this->getContentGridColumnsSettings($ctype['id']); - $default = $this->getContentGridColumnsSettingsDefault(); - - $changed = false; - - foreach ($saved as $type => $fields) { - foreach ($fields as $name => $field) { - if (!empty($field['enabled'])) { - - if (!empty($field['filter']) && isset($settings[$type][$name]['filters'][$field['filter']])) { // && валидация - - if(!isset($grid['columns'][$name]['filter'])){ - $changed = true; - } - - $grid['columns'][$name]['filter'] = $field['filter']; - - if (strpos($name, 'date_') !== 0 && $field['filter'] === 'select') { - $grid['columns'][$name]['filter'] = 'exact'; - $grid['columns'][$name]['filter_select'] = $settings[$type][$name]['filter_select']; - } - - } else if (isset($grid['columns'][$name]['filter'])) { - unset($grid['columns'][$name]['filter']); - } - - if (isset($default[$type][$name])) { - continue; - } - - // для стоковых менять только фильтр - if (!isset($settings[$type][$name])) { - continue; - } - - $grid['columns'][$name]['title'] = $settings[$type][$name]['title']; - - if (!empty($field['handler']) && isset($settings[$type][$name]['handlers'][$field['handler']])) { - if ($field['handler'] === 'flag') { - $grid['columns'][$name]['flag'] = true; - $grid['columns'][$name]['flag_toggle'] = href_to($controller->name, 'toggle_item', array('{id}', $content_table, $name)); - $grid['columns'][$name]['width'] = 60; - } else if ($field['handler'] === 'to_filter') { - $grid['columns'][$name]['handler'] = $settings[$type][$name]['handler_to_filter']; - } - } - - if (!empty($settings[$type][$name]['handlers_only'])) { - $grid['columns'][$name]['handler'] = $settings[$type][$name]['handler_only']; - } - - } else if (isset($default[$type][$name])) { - unset($grid['columns'][$name]); - } - } - } - - // пришедшие фильтра сбивают фокус с поля ввода - if (cmsUser::getUPS('admin.grid_columns.content.' . $ctype['id'] . '.changed')) { - - cmsUser::deleteUPS('admin.grid_columns.content.' . $ctype['id'] . '.changed'); - - $grid['options']['load_columns'] = true; - - } - - // когда включаем фильтр для существующих полей - if($changed){ - $grid['options']['load_columns'] = true; - } - - return array($grid, $args); - - } - -} diff --git a/system/controllers/admin/model.php b/system/controllers/admin/model.php index f943d386a..fb029189b 100755 --- a/system/controllers/admin/model.php +++ b/system/controllers/admin/model.php @@ -30,11 +30,7 @@ public function getInstalledControllers() { $item['title'] = string_lang($item['name'] . '_CONTROLLER', $item['title']); return $item; - }); - } - - public function getInstalledControllersCount() { - return $this->getCount('controllers'); + }) ?: []; } public function getControllerInfo($controller_name){ @@ -116,21 +112,11 @@ public function deleteEvent($listener, $event) { //========================== ПЛАНИРОВЩИК ===============================// //============================================================================// - public function getSchedulerTasksCount() { - - return $this->getCount('scheduler_tasks'); - } - - public function getSchedulerTasks() { - - return $this->get('scheduler_tasks'); - } - public function getPendingSchedulerTasks() { $tasks = $this->filterEqual('is_active', 1)-> orderBy('ordering', 'asc')-> - getSchedulerTasks(); + get('scheduler_tasks'); $pending = []; @@ -180,11 +166,6 @@ public function updateSchedulerTaskDate($task) { ]); } - public function deleteSchedulerTask($id) { - - return $this->delete('scheduler_tasks', $id); - } - public function toggleSchedulerPublication($id, $is_active) { return $this->update('scheduler_tasks', $id, [ diff --git a/system/controllers/admin/traits/queueActions.php b/system/controllers/admin/traits/queueActions.php new file mode 100644 index 000000000..fe84c7d0e --- /dev/null +++ b/system/controllers/admin/traits/queueActions.php @@ -0,0 +1,123 @@ +backend_menu[] = [ + 'title' => sprintf(LANG_CP_QUEUE_TITLE, $this->queue['queue_name']), + 'url' => href_to($this->root_url, 'queue'), + 'options' => [ + 'icon' => 'recycle' + ] + ]; + + return $this->backend_menu; + } + + /** + * Экшен очереди + * + * @return string + */ + public function actionQueue() { + + if (empty($this->queue['use_queue_action'])) { + return cmsCore::error404(); + } + + $grid = $this->controller_admin->loadDataGrid('queue', ['contex_controller' => $this]); + + if ($this->request->isAjax()) { + + $filter = []; + $filter_str = $this->request->get('filter', ''); + + if ($filter_str) { + parse_str($filter_str, $filter); + } + + $this->controller_admin->model->filterIn('queue', $this->queue['queues']); + + $total = $this->controller_admin->model->getCount(cmsQueue::getTableName()); + + $perpage = isset($filter['perpage']) ? $filter['perpage'] : 30; + $page = isset($filter['page']) ? intval($filter['page']) : 1; + + $this->controller_admin->model->limitPage($page, $perpage); + + $this->controller_admin->model->orderByList([ + ['by' => 'date_started', 'to' => 'asc'], + ['by' => 'priority', 'to' => 'desc'], + ['by' => 'date_created', 'to' => 'asc'] + ]); + + $jobs = $this->controller_admin->model->get(cmsQueue::getTableName()); + + return $this->cms_template->renderGridRowsJSON($grid, $jobs, $total); + } + + return $this->cms_template->getRenderedAsset('ui/grid', [ + 'grid' => $grid, + 'page_title' => sprintf(LANG_CP_QUEUE_TITLE, $this->queue['queue_name']), + 'source_url' => href_to($this->root_url, 'queue'), + ]); + } + + /** + * Экшен рестарта задания очереди + * + * @param integer $job_id + * @return type + */ + public function actionQueueRestart($job_id) { + + if (empty($this->queue['use_queue_action'])) { + return cmsCore::error404(); + } + + cmsQueue::restartJob(['id' => $job_id]); + + return $this->redirectBack(); + } + + /** + * Экшен удаления задания очереди + * + * @param integer $job_id + * @return type + */ + public function actionQueueDelete($job_id) { + + if (empty($this->queue['use_queue_action'])) { + return cmsCore::error404(); + } + + $csrf_token = $this->request->get('csrf_token', ''); + if (!cmsForm::validateCSRFToken($csrf_token)) { + return cmsCore::error404(); + } + + cmsQueue::deleteJob(['id' => $job_id]); + + return $this->redirectBack(); + } + +} diff --git a/system/controllers/auth/backend.php b/system/controllers/auth/backend.php index 422100539..251d1919d 100755 --- a/system/controllers/auth/backend.php +++ b/system/controllers/auth/backend.php @@ -5,15 +5,11 @@ class backendAuth extends cmsBackend { public $useDefaultOptionsAction = true; public $useSeoOptions = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - public function getBackendMenu() { return [ [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] diff --git a/system/controllers/comments/actions/approve.php b/system/controllers/comments/actions/approve.php index 32a7e0448..699a7c9b6 100755 --- a/system/controllers/comments/actions/approve.php +++ b/system/controllers/comments/actions/approve.php @@ -1,5 +1,8 @@ cms_template->renderJSON([ 'error' => true, - 'message' => LANG_COMMENT_ERROR + 'message' => sprintf(LANG_REQUEST_PARAMS_ERROR, 'id') ]); } $comment = $this->model->getComment($comment_id); - if (!$comment) { + if (!$comment || $comment['is_approved']) { return $this->cms_template->renderJSON([ 'error' => true, - 'message' => LANG_COMMENT_ERROR + 'message' => LANG_COMMENT_DELETED ]); } @@ -29,7 +32,7 @@ public function run() { if (!$is_moderator) { return $this->cms_template->renderJSON([ 'error' => true, - 'message' => LANG_COMMENT_ERROR + 'message' => ERR_FORBIDDEN ]); } @@ -67,6 +70,7 @@ public function run() { return $this->cms_template->renderJSON([ 'error' => false, + 'is_on' => 1, // для одобрения с админки 'message' => '', 'id' => $comment['id'], 'parent_id' => $comment['parent_id'], diff --git a/system/controllers/comments/backend.php b/system/controllers/comments/backend.php index 3bc64ce4b..25578547a 100755 --- a/system/controllers/comments/backend.php +++ b/system/controllers/comments/backend.php @@ -16,7 +16,7 @@ public function __construct(cmsRequest $request) { array_unshift($this->backend_menu, [ 'title' => LANG_COMMENTS_LIST, - 'url' => href_to($this->root_url, 'comments_list'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'comments' ] @@ -38,8 +38,4 @@ public function __construct(cmsRequest $request) { ); } - public function actionIndex() { - $this->redirectToAction('comments_list'); - } - } diff --git a/system/controllers/comments/backend/actions/comments_delete.php b/system/controllers/comments/backend/actions/comments_delete.php index 26aeec0ff..edc836ef1 100755 --- a/system/controllers/comments/backend/actions/comments_delete.php +++ b/system/controllers/comments/backend/actions/comments_delete.php @@ -12,10 +12,12 @@ public function run($id = null) { $items = $this->request->get('selected', []); } - if (!$items) { cmsCore::error404(); } + if (!$items) { + return cmsCore::error404(); + } if (!cmsForm::validateCSRFToken($this->request->get('csrf_token', ''))) { - cmsCore::error404(); + return cmsCore::error404(); } foreach ($items as $comment_id) { @@ -26,7 +28,7 @@ public function run($id = null) { cmsUser::addSessionMessage(html_spellcount($this->delete_count, LANG_COMMENT1, LANG_COMMENT2, LANG_COMMENT10) . LANG_COMMENTS_DELETED, 'success'); - $this->redirectToAction('comments_list'); + return $this->redirectToAction(''); } private function deleteComment($id) { diff --git a/system/controllers/comments/backend/actions/comments_list.php b/system/controllers/comments/backend/actions/comments_list.php deleted file mode 100755 index a417637f1..000000000 --- a/system/controllers/comments/backend/actions/comments_list.php +++ /dev/null @@ -1,45 +0,0 @@ -loadDataGrid('comments_list'); - - $filter = array(); - $filter_str = $this->request->get('filter', ''); - - if ($filter_str){ - parse_str($filter_str, $filter); - $grid['filter'] = $filter; - } - - if ($this->request->isAjax()) { - - $this->model->setPerPage(admin::perpage); - - if ($filter_str){ - if(!empty($filter['author_ip'])){ - $filter['author_ip'] = string_iptobin($filter['author_ip']); - } - $this->model->applyGridFilter($grid, $filter); - } - - $total = $this->model->getCount('comments'); - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - $pages = ceil($total / $perpage); - - $data = $this->model->joinUserLeft()->get('comments'); - - $this->cms_template->renderGridRowsJSON($grid, $data, $total, $pages); - - $this->halt(); - - } - - return $this->cms_template->render('backend/comments_list', array( - 'grid' => $grid - )); - - } - -} diff --git a/system/controllers/comments/backend/actions/index.php b/system/controllers/comments/backend/actions/index.php new file mode 100755 index 000000000..ef5438258 --- /dev/null +++ b/system/controllers/comments/backend/actions/index.php @@ -0,0 +1,21 @@ +table_name = 'comments'; + $this->grid_name = 'comments_list'; + + $this->list_callback = function ($model) { + + $model->joinUserLeft(); + + return $model; + }; + } + +} diff --git a/system/controllers/comments/backend/grids/grid_comments_list.php b/system/controllers/comments/backend/grids/grid_comments_list.php index 1262c28ff..5f83f3348 100755 --- a/system/controllers/comments/backend/grids/grid_comments_list.php +++ b/system/controllers/comments/backend/grids/grid_comments_list.php @@ -1,43 +1,49 @@ true, - 'is_filter' => true, - 'is_pagination' => true, - 'is_draggable' => false, - 'is_selectable' => true, - 'order_by' => 'date_pub', - 'order_to' => 'desc', - 'show_id' => true - ); + $options = [ + 'is_sortable' => true, + 'is_filter' => true, + 'is_pagination' => true, + 'is_draggable' => false, + 'is_selectable' => true, + 'order_by' => 'date_pub', + 'order_to' => 'desc', + 'show_id' => false, + 'select_actions' => [ + [ + 'title' => LANG_DELETE, + 'action' => 'submit', + 'confirm' => LANG_DELETE_SELECTED_CONFIRM, + 'url' => $controller->cms_template->href_to('comments_delete') + ] + ] + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30 - ), - 'date_pub' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'date_pub' => [ 'title' => LANG_DATE, - 'class' => 'd-none d-lg-table-cell', - 'width' => 110, - 'handler' => function($value, $item) { + 'class' => 'd-none d-lg-table-cell', + 'handler' => function ($value, $item) { return html_date($value, true); }, - 'filter' => 'date' - ), - 'target_id' => array( - 'title' => LANG_COMMENTS_TEXT, - 'handler' => function($value, $row) use($controller) { - return ''.string_short($row['content_html'], 350).''; + 'filter' => 'range_date' + ], + 'target_id' => [ + 'title' => LANG_COMMENTS_TEXT, + 'sortable' => false, + 'handler' => function ($value, $row) use ($controller) { + return '' . string_short($row['content_html'], 350) . ''; } - ), - 'user_id' => array( - 'title' => LANG_AUTHOR, - 'width' => 180, - 'handler' => function($value, $row) { + ], + 'user_id' => [ + 'title' => LANG_AUTHOR, + 'switchable' => true, + 'handler' => function ($value, $row) { if ($row['user_id']) { $v = '' . $row['user_nickname'] . ''; } else { @@ -48,76 +54,80 @@ function grid_comments_list($controller){ } return $v; } - ), - 'author_ip' => array( - 'title' => LANG_COMMENTS_IP, - 'class' => 'd-none d-lg-table-cell', - 'width' => 120, - 'filter' => 'like', - 'handler' => function($value) { + ], + 'author_ip' => [ + 'title' => LANG_COMMENTS_IP, + 'class' => 'd-none d-lg-table-cell', + 'width' => 120, + 'sortable' => false, + 'filter' => 'ip', + 'switchable' => true, + 'handler' => function ($value) { if ($value) { - $value = string_bintoip($value); - return '' . $value . ' '; + $value = string_bintoip($value); + $location = string_ip_to_location($value, true); + return $value . (!empty($location['code']) ? ' ' . $location['code'] : ''); } return ''; } - ), - 'rating' => array( - 'title' => LANG_RATING, - 'class' => 'd-none d-lg-table-cell', - 'width' => 50, - 'handler' => function($value, $row) { + ], + 'rating' => [ + 'title' => LANG_RATING, + 'class' => 'd-none d-lg-table-cell', + 'width' => 50, + 'switchable' => true, + 'handler' => function ($value, $row) { return '' . html_signed_num($value) . ''; }, 'filter' => 'exact' - ), - 'is_deleted' => array( - 'title' => LANG_COMMENTS_IS_DELETED, - 'class' => 'd-none d-lg-table-cell', - 'flag' => 'flag_lock', - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'comments', 'is_deleted', 1)), - 'width' => 50, - 'filter' => 'exact' - ), - 'is_approved' => array( - 'title' => LANG_MODERATION, - 'flag' => true, - 'width' => 50, - 'filter' => 'exact', - 'handler' => function($value, $item){ - if(!$item['is_approved']){ - return '
'; - } - return '
'; - } - ), - 'is_private' => array( - 'title' => LANG_COMMENTS_IS_PRIVATE, - 'class' => 'd-none d-lg-table-cell', - 'flag' => true, - 'width' => 50, - 'filter' => 'exact' - ), - ); + ], + 'is_deleted' => [ + 'title' => LANG_COMMENTS_IS_DELETED, + 'class' => 'd-none d-lg-table-cell', + 'flag' => 'flag_lock', + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'comments', 'is_deleted', 1]), + 'width' => 50, + 'switchable' => true, + 'filter' => 'nn', + 'filter_checkbox' => LANG_YES + ], + 'is_approved' => [ + 'title' => LANG_MODERATION, + 'flag' => true, + 'flag_toggle' => href_to('comments', 'approve') . '?id={id}', + 'flag_confirm' => LANG_COMMENTS_APPROVE . '?', + 'width' => 50, + 'switchable' => true, + 'filter' => 'zero', + 'filter_checkbox' => LANG_NO + ], + 'is_private' => [ + 'title' => LANG_COMMENTS_IS_PRIVATE, + 'class' => 'd-none d-lg-table-cell', + 'switchable' => true, + 'flag' => true, + 'width' => 50 + ] + ]; - $actions = array( - array( - 'title' => LANG_COMMENTS_VIEW, - 'class' => 'view', - 'href' => rel_to_href('{target_url}').'#comment_{id}' - ), - array( + $actions = [ + [ + 'title' => LANG_COMMENTS_VIEW, + 'class' => 'view', + 'target' => '_blank', + 'href' => rel_to_href('{target_url}') . '#comment_{id}' + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'comments_delete', array('{id}')), + 'href' => href_to($controller->root_url, 'comments_delete', ['{id}']), 'confirm' => LANG_COMMENTS_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/content/backend/model.php b/system/controllers/content/backend/model.php index 27345bfc4..dacd86a69 100755 --- a/system/controllers/content/backend/model.php +++ b/system/controllers/content/backend/model.php @@ -525,21 +525,6 @@ public function deleteContentDataset($id){ } - public function toggleContentDatasetVisibility($id, $is_visible){ - return $this->update('content_datasets', $id, array( - 'is_visible' => $is_visible - )); - } - - public function reorderContentDatasets($fields_ids_list){ - - $this->reorderByList('content_datasets', $fields_ids_list); - - cmsCache::getInstance()->clean('content.datasets'); - - return true; - } - //============================================================================// //============================= Фильтры ==================================// //============================================================================// @@ -649,16 +634,6 @@ public function deleteContentRelation($id){ } - public function reorderContentRelation($fields_ids_list){ - - $this->reorderByList('content_relations', $fields_ids_list); - - cmsCache::getInstance()->clean('content.relations'); - - return true; - - } - //============================================================================// //============================ СВОЙСТВА =================================// //============================================================================// diff --git a/system/controllers/forms/backend/actions/fields_reorder.php b/system/controllers/forms/backend/actions/fields_reorder.php deleted file mode 100644 index ef84009d1..000000000 --- a/system/controllers/forms/backend/actions/fields_reorder.php +++ /dev/null @@ -1,25 +0,0 @@ -request->get('items', array()); - if (!$items){ cmsCore::error404(); } - - $this->model->reorderFormFields($items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/forms/backend/actions/form_fields.php b/system/controllers/forms/backend/actions/form_fields.php index b39b7e5ca..5bc6e4291 100644 --- a/system/controllers/forms/backend/actions/form_fields.php +++ b/system/controllers/forms/backend/actions/form_fields.php @@ -2,40 +2,54 @@ class actionFormsFormFields extends cmsAction { - public function run($form_id = 0) { + use icms\traits\controllers\actions\listgrid; + + public function __construct($controller, $params = []) { + + parent::__construct($controller, $params); + + $form_id = $params[0] ?? 0; $form_data = $this->model->getForm($form_id); - if(!$form_data){ cmsCore::error404(); } - $grid = $this->loadDataGrid('form_fields'); + if (!$form_data) { + return cmsCore::error404(); + } + + $this->table_name = 'forms_fields'; + $this->grid_name = 'form_fields'; - if($this->request->isAjax()){ + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_FIELD_ADD, + 'href' => $this->cms_template->href_to('fields_add', $form_data['id']) + ] + ]; - $filter = array(); - $filter_str = $this->request->get('filter', ''); + $this->cms_template->addBreadcrumb($form_data['title'], $this->cms_template->href_to('edit', [$form_data['id']])); - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } + $this->cms_template->addMenuItems('admin_toolbar', $this->getFormMenu('edit', $form_data['id'])); - $this->model->filterEqual('form_id', $form_id); + $this->list_callback = function ($model) use($form_data) { - $this->model->orderBy('ordering', 'asc'); + $model->filterEqual('form_id', $form_data['id']); - $fields = $this->model->getFormFields(false); + $model->orderBy('ordering', 'asc'); - $this->cms_template->renderGridRowsJSON($grid, $fields); + return $model; + }; - $this->halt(); + $this->item_callback = function ($item, $model) { - } + $field_class = 'field' . string_to_camel('_', $item['type']); + + $handler = new $field_class($item['name']); + + $item['handler_title'] = $handler->getTitle(); - return $this->cms_template->render([ - 'menu' => $this->getFormMenu('edit', $form_data['id']), - 'form_data' => $form_data, - 'grid' => $grid - ]); + return $item; + }; } diff --git a/system/controllers/forms/backend/grids/grid_form_fields.php b/system/controllers/forms/backend/grids/grid_form_fields.php index 5ebfd3e75..84e732576 100644 --- a/system/controllers/forms/backend/grids/grid_form_fields.php +++ b/system/controllers/forms/backend/grids/grid_form_fields.php @@ -1,70 +1,92 @@ false, - 'is_filter' => false, + 'is_filter' => true, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('fields_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', 'forms_fields'), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'width' => 30, - ), - 'title' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ 'title' => LANG_CP_FIELD_TITLE, - 'href' => href_to($controller->root_url, 'fields_edit', array('{id}')), - ), - 'fieldset' => array( - 'title' => LANG_CP_FIELD_FIELDSET, - 'class' => 'd-none d-lg-table-cell', - 'handler' => function($value, $row){ + 'href' => href_to($controller->root_url, 'fields_edit', ['{id}']), + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 100] + ] + ] + ], + 'fieldset' => [ + 'title' => LANG_CP_FIELD_FIELDSET, + 'class' => 'd-none d-lg-table-cell', + 'handler' => function ($value, $row) { return $value ? $value : '—'; - } - ), - 'is_enabled' => array( - 'title' => LANG_IS_ENABLED, - 'flag' => true, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'forms_fields', 'is_enabled')), - 'width' => 80 - ), - 'name' => array( + }, + 'filter' => 'exact', + 'filter_select' => [ + 'items' => function($name) { + $fieldsets = cmsCore::getModel('content')->setTablePrefix('')->getContentFieldsets('forms'); + $items = ['' => LANG_ALL]; + foreach($fieldsets as $fieldset) { $items[$fieldset] = $fieldset; } + return $items; + } + ] + ], + 'is_enabled' => [ + 'title' => LANG_IS_ENABLED, + 'flag' => true, + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'forms_fields', 'is_enabled']), + 'width' => 80 + ], + 'name' => [ 'title' => LANG_SYSTEM_NAME, 'class' => 'd-none d-lg-table-cell', 'width' => 120, - ), - 'handler_title' => array( + ], + 'type' => [ 'title' => LANG_CP_FIELD_TYPE, 'class' => 'd-none d-lg-table-cell', 'width' => 150, - ), - ); + 'handler' => function ($value, $row) { + return $row['handler_title']; + }, + 'filter' => 'exact', + 'filter_select' => [ + 'items' => function($name) { + return ['' => LANG_ALL] + cmsForm::getAvailableFormFields('only_public', 'forms'); + } + ] + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'fields_edit', array('{id}')) - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($controller->root_url, 'fields_delete', array('{id}')), + 'href' => href_to($controller->root_url, 'fields_edit', ['{id}']) + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($controller->root_url, 'fields_delete', ['{id}']), 'confirm' => LANG_CP_FIELD_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/forms/backend/grids/grid_forms.php b/system/controllers/forms/backend/grids/grid_forms.php index 4cd99886f..18f09c397 100644 --- a/system/controllers/forms/backend/grids/grid_forms.php +++ b/system/controllers/forms/backend/grids/grid_forms.php @@ -2,87 +2,79 @@ function grid_forms($controller) { - $options = array( - 'is_sortable' => true, - 'is_filter' => true, - 'is_pagination' => true, - 'is_draggable' => false, - 'is_selectable' => false, - 'order_by' => 'id', - 'order_to' => 'asc', - 'show_id' => true - ); + $options = []; - $columns = array( - 'id' => array( + $columns = [ + 'id' => [ 'title' => 'id', 'width' => 30, 'filter' => 'exact' - ), - 'title' => array( + ], + 'title' => [ 'title' => LANG_TITLE, 'width' => 150, 'href' => href_to($controller->root_url, 'edit', '{id}'), 'filter' => 'like' - ), - 'name' => array( + ], + 'name' => [ 'title' => LANG_SYSTEM_NAME, 'width' => 150, 'filter' => 'like' - ) - ); + ] + ]; - if(!empty($controller->options['allow_embed'])){ - $columns['hash'] = array( - 'title' => LANG_FORMS_CP_FORMS_EMBED, - 'handler' => function ($v, $row){ - return html_input('text', '', '', ['onclick' => '$(this).select();']); + if (!empty($controller->options['allow_embed'])) { + + $columns['hash'] = [ + 'title' => LANG_FORMS_CP_FORMS_EMBED, + 'handler' => function ($v, $row) { + return html_input('text', '', '', ['onclick' => '$(this).select();']); } - ); + ]; } - if(!empty($controller->options['allow_shortcode'])){ - $columns['tpl_form'] = array( - 'title' => LANG_FORMS_CP_FORMS_SHORTCODE, - 'handler' => function ($v, $row){ - return html_input('text', '', '{forms:'.$row['name'].'}', ['onclick' => '$(this).select();']); + if (!empty($controller->options['allow_shortcode'])) { + + $columns['tpl_form'] = [ + 'title' => LANG_FORMS_CP_FORMS_SHORTCODE, + 'handler' => function ($v, $row) { + return html_input('text', '', '{forms:' . $row['name'] . '}', ['onclick' => '$(this).select();']); } - ); + ]; } - $actions = array( - array( + $actions = [ + [ 'title' => LANG_VIEW, 'class' => 'view ajax-modal', 'href' => href_to($controller->root_url, 'view', '{id}') - ), - array( + ], + [ 'title' => LANG_EDIT, 'class' => 'edit', 'href' => href_to($controller->root_url, 'edit', '{id}'), - ), - array( + ], + [ 'title' => LANG_CP_CTYPE_FIELDS, 'class' => 'fields', 'href' => href_to($controller->root_url, 'form_fields', '{id}') - ), - array( + ], + [ 'title' => LANG_FORMS_CP_FORMS_COPY, 'class' => 'copy', - 'href' => href_to($controller->root_url, 'copy', array('{id}')), - ), - array( + 'href' => href_to($controller->root_url, 'copy', '{id}'), + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'delete', array('{id}')), + 'href' => href_to($controller->root_url, 'delete', '{id}'), 'confirm' => LANG_FORMS_CP_FORM_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/forms/model.php b/system/controllers/forms/model.php index db28c6c86..972135e0e 100644 --- a/system/controllers/forms/model.php +++ b/system/controllers/forms/model.php @@ -192,15 +192,6 @@ public function deleteFormField($id, $form_id){ return true; } - public function reorderFormFields($fields_ids_list){ - - $this->reorderByList('forms_fields', $fields_ids_list); - - cmsCache::getInstance()->clean('forms.fields'); - - return true; - } - public function deleteController($id) { $this->db->dropTable('forms'); diff --git a/system/controllers/geo/backend/actions/cities.php b/system/controllers/geo/backend/actions/cities.php index 226aea5a2..9ed58fdbc 100755 --- a/system/controllers/geo/backend/actions/cities.php +++ b/system/controllers/geo/backend/actions/cities.php @@ -2,50 +2,47 @@ class actionGeoCities extends cmsAction { - public function run($region_id = null, $country_id = null){ + use icms\traits\controllers\actions\listgrid; - if(!$region_id){ cmsCore::error404(); } + public function __construct($controller, $params = []) { - $region = $this->model->getItemById('geo_regions', $region_id); - if(!$region){ cmsCore::error404(); } - - $grid = $this->loadDataGrid('cities'); - - if($this->request->isAjax()){ - - $this->model->setPerPage(admin::perpage); - - $filter = array(); - $filter_str = $this->request->get('filter', ''); + parent::__construct($controller, $params); - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } + $this->table_name = 'geo_cities'; + $this->grid_name = 'cities'; - $total = $this->model->filterEqual('region_id', $region_id)->getCount('geo_cities'); - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - $pages = ceil($total / $perpage); + $region_id = $params[0] ?? 0; + $country_id = $params[1] ?? 0; - $cities = $this->model->get('geo_cities'); + $country = $this->model->getItemById('geo_countries', $country_id); + if (!$country) { + return cmsCore::error404(); + } - $this->cms_template->renderGridRowsJSON($grid, $cities, $total, $pages); + $region = $this->model->getItemById('geo_regions', $region_id); + if (!$region) { + return cmsCore::error404(); + } - $this->halt(); + $this->list_callback = function ($model) use ($region_id) { - } + $model->filterEqual('region_id', $region_id); - $country = $this->model->getItemById('geo_countries', $country_id); - if(!$country){ cmsCore::error404(); } + return $model; + }; - $this->cms_template->setPageH1(array($country['name'], $region['name'])); + $this->cms_template->setPageH1([$country['name'], $region['name']]); - return $this->cms_template->render('backend/cities', array( - 'grid' => $grid, - 'country' => $country, - 'region' => $region - )); + $this->cms_template->addBreadcrumb($country['name'], $this->cms_template->href_to('regions', $country['id'])); + $this->cms_template->addBreadcrumb($region['name']); + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_GEO_ADD_CITY, + 'href' => $this->cms_template->href_to('city', [0, $region['id']]) + ] + ]; } } diff --git a/system/controllers/geo/backend/actions/cities_reorder.php b/system/controllers/geo/backend/actions/cities_reorder.php deleted file mode 100644 index 5fef34d05..000000000 --- a/system/controllers/geo/backend/actions/cities_reorder.php +++ /dev/null @@ -1,25 +0,0 @@ -request->get('items', array()); - - if (!$items) { cmsCore::error404();} - - $this->model->reorderByList('geo_cities', $items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/geo/backend/actions/countries_reorder.php b/system/controllers/geo/backend/actions/countries_reorder.php deleted file mode 100755 index 93f0c7f3d..000000000 --- a/system/controllers/geo/backend/actions/countries_reorder.php +++ /dev/null @@ -1,25 +0,0 @@ -request->get('items', array()); - if (!$items) { cmsCore::error404();} - - $this->model->reorderByList('geo_countries', $items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/geo/backend/actions/regions.php b/system/controllers/geo/backend/actions/regions.php index b79a0598c..5b8bcde22 100755 --- a/system/controllers/geo/backend/actions/regions.php +++ b/system/controllers/geo/backend/actions/regions.php @@ -2,46 +2,40 @@ class actionGeoRegions extends cmsAction { - public function run($country_id = null){ + use icms\traits\controllers\actions\listgrid; - if(!$country_id){ cmsCore::error404(); } + public function __construct($controller, $params = []) { - $country = $this->model->getItemById('geo_countries', $country_id); - if(!$country){ cmsCore::error404(); } + parent::__construct($controller, $params); - $grid = $this->loadDataGrid('regions'); + $this->table_name = 'geo_regions'; + $this->grid_name = 'regions'; - if($this->request->isAjax()){ + $country_id = $params[0] ?? 0; - $this->model->setPerPage(admin::perpage); - - $filter = array(); - $filter_str = $this->request->get('filter', ''); - - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($grid, $filter); - } - - $total = $this->model->filterEqual('country_id', $country_id)->getCount('geo_regions'); - - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - $pages = ceil($total / $perpage); - - $regions = $this->model->get('geo_regions'); + $country = $this->model->getItemById('geo_countries', $country_id); + if (!$country) { + return cmsCore::error404(); + } - $this->cms_template->renderGridRowsJSON($grid, $regions, $total, $pages); + $this->list_callback = function ($model) use ($country_id) { - $this->halt(); + $model->filterEqual('country_id', $country_id); - } + return $model; + }; $this->cms_template->setPageH1($country['name']); - return $this->cms_template->render('backend/regions', array( - 'grid' => $grid, - 'country' => $country - )); + $this->cms_template->addBreadcrumb($country['name']); + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_GEO_ADD_REGION, + 'href' => $this->cms_template->href_to('region', $country['id']) + ] + ]; } + } diff --git a/system/controllers/geo/backend/actions/regions_reorder.php b/system/controllers/geo/backend/actions/regions_reorder.php deleted file mode 100644 index 086760be4..000000000 --- a/system/controllers/geo/backend/actions/regions_reorder.php +++ /dev/null @@ -1,25 +0,0 @@ -request->get('items', array()); - - if (!$items) { cmsCore::error404();} - - $this->model->reorderByList('geo_regions', $items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/geo/backend/grids/grid_cities.php b/system/controllers/geo/backend/grids/grid_cities.php index 21e6b5e1a..932ed9fa6 100755 --- a/system/controllers/geo/backend/grids/grid_cities.php +++ b/system/controllers/geo/backend/grids/grid_cities.php @@ -2,63 +2,57 @@ function grid_cities($controller) { - $options = array( - 'is_sortable' => true, + $options = [ + 'is_sortable' => false, 'is_filter' => true, 'is_pagination' => true, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('cities_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', 'geo_cities'), 'order_by' => 'ordering', 'order_to' => 'asc', - 'show_id' => true - ); + 'show_id' => false + ]; - $columns = array( - 'id' => array( - 'title' => 'ID', - 'class' => 'd-none d-lg-table-cell', - 'width' => 20, - 'filter' => 'exact' - ), - 'name' => array( + $columns = [ + 'id' => [ + 'title' => 'ID' + ], + 'name' => [ 'title' => LANG_TITLE, - 'href' => href_to($controller->root_url, 'city', array('{id}')), + 'href' => href_to($controller->root_url, 'city', ['{id}']), 'filter' => 'like', - 'editable' => array( - 'table' => 'geo_cities' - ) - ), - 'ordering' => array( - 'title' => LANG_GEO_POSITION, - 'class' => 'd-none d-lg-table-cell', - 'width' => 60 - ), - 'is_enabled' => array( + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 128] + ] + ] + ], + 'is_enabled' => [ 'title' => LANG_IS_ENABLED, 'flag' => true, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'geo_cities', 'is_enabled')), + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'geo_cities', 'is_enabled']), 'width' => 80 - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'city', array('{id}')) - ), - array( + 'href' => href_to($controller->root_url, 'city', ['{id}']) + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'delete', array('city', '{id}')), + 'href' => href_to($controller->root_url, 'delete', ['city', '{id}']), 'confirm' => LANG_GEO_DELETE_CITY - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/geo/backend/grids/grid_countries.php b/system/controllers/geo/backend/grids/grid_countries.php index d6295fae1..7a90e7694 100755 --- a/system/controllers/geo/backend/grids/grid_countries.php +++ b/system/controllers/geo/backend/grids/grid_countries.php @@ -2,72 +2,69 @@ function grid_countries($controller) { - $options = array( - 'is_sortable' => true, + $options = [ + 'is_sortable' => false, 'is_filter' => true, 'is_pagination' => true, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('countries_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', 'geo_countries'), 'order_by' => 'ordering', 'order_to' => 'asc', - 'show_id' => true - ); + 'show_id' => false + ]; - $columns = array( - 'id' => array( - 'title' => 'ID', - 'width' => 20, - 'class' => 'd-none d-lg-table-cell', - 'filter' => 'exact' - ), - 'name' => array( + $columns = [ + 'id' => [ + 'title' => 'ID' + ], + 'name' => [ 'title' => LANG_TITLE, - 'href' => href_to($controller->root_url, 'regions', array('{id}')), + 'href' => href_to($controller->root_url, 'regions', ['{id}']), 'filter' => 'like', - 'editable' => array( - 'table' => 'geo_countries' - ) - ), - 'alpha2' => array( + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 128] + ] + ] + ], + 'alpha2' => [ 'title' => LANG_GEO_ALPHA2, 'class' => 'd-none d-sm-table-cell', 'width' => 250, 'filter' => 'like', - 'editable' => array( - 'table' => 'geo_countries' - ) - ), - 'ordering' => array( - 'title' => LANG_GEO_POSITION, - 'class' => 'd-none d-lg-table-cell', - 'width' => 60 - ), - 'is_enabled' => array( + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 2] + ] + ] + ], + 'is_enabled' => [ 'title' => LANG_IS_ENABLED, 'flag' => true, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'geo_countries', 'is_enabled')), + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'geo_countries', 'is_enabled']), 'width' => 80 - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'country', array('{id}')) - ), - array( + 'href' => href_to($controller->root_url, 'country', ['{id}']) + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'delete', array('country', '{id}')), + 'href' => href_to($controller->root_url, 'delete', ['country', '{id}']), 'confirm' => LANG_GEO_DELETE_COUNTRY - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/geo/backend/grids/grid_regions.php b/system/controllers/geo/backend/grids/grid_regions.php index d1a98f6a9..0607453e2 100755 --- a/system/controllers/geo/backend/grids/grid_regions.php +++ b/system/controllers/geo/backend/grids/grid_regions.php @@ -2,63 +2,57 @@ function grid_regions($controller) { - $options = array( - 'is_sortable' => true, + $options = [ + 'is_sortable' => false, 'is_filter' => true, 'is_pagination' => true, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('regions_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', 'geo_regions'), 'order_by' => 'ordering', 'order_to' => 'asc', - 'show_id' => true - ); + 'show_id' => false + ]; - $columns = array( - 'id' => array( - 'title' => 'ID', - 'class' => 'd-none d-lg-table-cell', - 'width' => 20, - 'filter' => 'exact' - ), - 'name' => array( + $columns = [ + 'id' => [ + 'title' => 'ID' + ], + 'name' => [ 'title' => LANG_TITLE, - 'href' => href_to($controller->root_url, 'cities', array('{id}', '{country_id}')), + 'href' => href_to($controller->root_url, 'cities', ['{id}', '{country_id}']), 'filter' => 'like', - 'editable' => array( - 'table' => 'geo_regions' - ) - ), - 'ordering' => array( - 'title' => LANG_GEO_POSITION, - 'class' => 'd-none d-lg-table-cell', - 'width' => 60 - ), - 'is_enabled' => array( + 'editable' => [ + 'rules' => [ + ['required'], + ['max_length', 64] + ] + ] + ], + 'is_enabled' => [ 'title' => LANG_IS_ENABLED, 'flag' => true, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'geo_regions', 'is_enabled')), + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'geo_regions', 'is_enabled']), 'width' => 80 - ) - ); + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'region', array('{country_id}', '{id}')) - ), - array( + 'href' => href_to($controller->root_url, 'region', ['{country_id}', '{id}']) + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'delete', array('region', '{id}')), + 'href' => href_to($controller->root_url, 'delete', ['region', '{id}']), 'confirm' => LANG_GEO_DELETE_REGION - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/groups/backend.php b/system/controllers/groups/backend.php index 7f77df8e1..3c1da5b4f 100755 --- a/system/controllers/groups/backend.php +++ b/system/controllers/groups/backend.php @@ -8,13 +8,6 @@ class backendGroups extends cmsBackend { public $useSeoOptions = true; public $useItemSeoOptions = true; - public function routeAction($action_name){ - if($action_name == 'index'){ - return 'fields'; - } - return $action_name; - } - public function getBackendMenu(){ return array( array( diff --git a/system/controllers/groups/backend/actions/datasets.php b/system/controllers/groups/backend/actions/datasets.php index 3ef1252ef..863773e75 100755 --- a/system/controllers/groups/backend/actions/datasets.php +++ b/system/controllers/groups/backend/actions/datasets.php @@ -2,42 +2,62 @@ class actionGroupsDatasets extends cmsAction { - public function run($do = false, $id = 0){ + use icms\traits\controllers\actions\listgrid { + run as private traitRun; + } - $admin = cmsCore::getController('admin', $this->request); + public function __construct($controller, $params = []) { - // для добавления/редактирования вызываем экшены админки - if ($do){ + parent::__construct($controller, $params); - $this->cms_template->setContext($admin); + $this->table_name = 'content_datasets'; + $this->grid_name = 'ctype_datasets'; + $this->grid_args = [$this->cms_template->href_to('datasets', ['edit', '{id}'])]; + $this->title = LANG_CP_CTYPE_DATASETS; - $html = $admin->runExternalAction('ctypes_datasets_'.$do, ($do === 'add' ? [$this->name] : [$id])); + $this->tool_buttons = [ + [ + 'class' => 'add', + 'title' => LANG_CP_DATASET_ADD, + 'href' => $this->cms_template->href_to('datasets', 'add') + ], + [ + 'class' => 'help', + 'title' => LANG_HELP, + 'target' => '_blank', + 'href' => LANG_HELP_URL_CTYPES_DATASETS + ], + ]; - $this->cms_template->restoreContext(); + $this->list_callback = function ($model) { - return $html; - } + $model->filterEqual('target_controller', 'groups'); - $grid = $admin->loadDataGrid('ctype_datasets', [href_to('admin', 'ctypes', array('datasets_reorder', 'groups')), $this->cms_template->href_to('datasets', ['edit', '{id}'])]); + return $model; + }; - if ($this->request->isAjax()) { + } - $content_model = cmsCore::getModel('content'); + public function run($do = false, $id = 0){ - $content_model->orderBy('ordering', 'asc'); + $admin = cmsCore::getController('admin', $this->request); + + // для добавления/редактирования вызываем экшены админки + if ($do){ - $datasets = $content_model->getContentDatasets('groups'); + $this->cms_template->setContext($admin); - $this->cms_template->renderGridRowsJSON($grid, $datasets); + $html = $admin->runExternalAction('ctypes_datasets_'.$do, ($do === 'add' ? [$this->name] : [$id])); - $this->halt(); + $this->cms_template->restoreContext(); + return $html; } - return $this->cms_template->render('backend/datasets', array( - 'grid' => $grid - )); + // Меняем контекст контроллера для экшена + $this->controller = $admin; + return $this->traitRun(); } } diff --git a/system/controllers/groups/backend/actions/fields_reorder.php b/system/controllers/groups/backend/actions/fields_reorder.php deleted file mode 100755 index 2f3b8c780..000000000 --- a/system/controllers/groups/backend/actions/fields_reorder.php +++ /dev/null @@ -1,31 +0,0 @@ -request->get('items', []); - if (!$items) { - return cmsCore::error404(); - } - - $content_model = cmsCore::getModel('content'); - - $content_model->setTablePrefix(''); - - $content_model->reorderContentFields('groups', $items); - - if ($this->request->isAjax()) { - - return $this->cms_template->renderJSON([ - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - ]); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - return $this->redirectToAction('fields'); - } - -} diff --git a/system/controllers/groups/backend/actions/fields.php b/system/controllers/groups/backend/actions/index.php similarity index 60% rename from system/controllers/groups/backend/actions/fields.php rename to system/controllers/groups/backend/actions/index.php index 687ac57a2..ddf352594 100755 --- a/system/controllers/groups/backend/actions/fields.php +++ b/system/controllers/groups/backend/actions/index.php @@ -1,6 +1,6 @@ items_callback = function ($items) { + $this->item_callback = function ($item, $model) { - if($items){ - foreach ($items as $key => $item) { + $field_class = 'field' . string_to_camel('_', $item['type']); - $field_class = 'field' . string_to_camel('_', $item['type']); + $handler = new $field_class($item['name']); - $handler = new $field_class($item['name']); + $item['handler_title'] = $handler->getTitle(); - $items[$key]['handler_title'] = $handler->getTitle(); - } - } - - return $items; + return $item; }; } diff --git a/system/controllers/groups/backend/grids/grid_fields.php b/system/controllers/groups/backend/grids/grid_fields.php index 76c0b8117..58c9702f0 100755 --- a/system/controllers/groups/backend/grids/grid_fields.php +++ b/system/controllers/groups/backend/grids/grid_fields.php @@ -7,7 +7,7 @@ function grid_fields($controller){ 'is_filter' => true, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('fields_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', 'groups_fields'), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false @@ -15,15 +15,12 @@ function grid_fields($controller){ $columns = [ 'id' => [ - 'title' => 'id', - 'width' => 30 + 'title' => 'id' ], 'title' => [ 'title' => LANG_CP_FIELD_TITLE, 'href' => href_to($controller->root_url, 'fields_edit', ['groups', '{id}']), - 'editable' => [ - 'table' => 'groups_fields' - ] + 'editable' => [] ], 'fieldset' => [ 'title' => LANG_CP_FIELD_FIELDSET, diff --git a/system/controllers/images/backend/grids/grid_presets.php b/system/controllers/images/backend/grids/grid_presets.php index 2bcb4aef5..3ab000d35 100755 --- a/system/controllers/images/backend/grids/grid_presets.php +++ b/system/controllers/images/backend/grids/grid_presets.php @@ -1,86 +1,89 @@ false, - 'is_filter' => false, + $options = [ + 'is_sortable' => false, + 'is_filter' => false, 'is_pagination' => false, - 'is_draggable' => false, - 'show_id' => false - ); + 'is_draggable' => false, + 'show_id' => false + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'width' => 30, - ), - 'title' => array( - 'title' => LANG_IMAGES_PRESET, - 'href' => href_to($controller->root_url, 'presets_edit', array('{id}')), - 'editable' => array( - 'table' => 'images_presets' - ) - ), - 'name' => array( - 'title' => LANG_SYSTEM_NAME, - 'width' => 200 - ), - 'width' => array( - 'title' => LANG_IMAGES_PRESET_SIZE, - 'width' => 100, - 'handler' => function($val, $row){ - return ($val ? $val : LANG_AUTO) . ' x ' . ($row['height'] ? $row['height'] : LANG_AUTO); - } - ), - 'convert_format' => array( - 'title' => LANG_CP_FORMAT, - 'handler' => function($val, $row){ - return $val ?: LANG_IMAGES_PRESET_OUT_ASIS; - }, - 'width' => 70 - ), - 'quality' => array( - 'title' => LANG_IMAGES_PRESET_QUALITY, - 'handler' => function($val, $row){ - return $val.' %'; - }, - 'width' => 70 - ), - 'is_square' => array( - 'title' => LANG_IMAGES_PRESET_CROP, - 'flag' => true, - 'width' => 120 - ), - 'is_watermark' => array( - 'title' => LANG_IMAGES_PRESET_WM, - 'flag' => true, - 'width' => 100 - ), - ); + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ + 'title' => LANG_IMAGES_PRESET, + 'href' => href_to($controller->root_url, 'presets_edit', ['{id}']), + 'editable' => [] + ], + 'name' => [ + 'title' => LANG_SYSTEM_NAME, + 'switchable' => true + ], + 'width' => [ + 'title' => LANG_IMAGES_PRESET_SIZE, + 'width' => 100, + 'switchable' => true, + 'handler' => function ($val, $row) { + return ($val ? $val : LANG_AUTO) . ' x ' . ($row['height'] ? $row['height'] : LANG_AUTO); + } + ], + 'convert_format' => [ + 'title' => LANG_CP_FORMAT, + 'switchable' => true, + 'handler' => function ($val, $row) { + return $val ?: LANG_IMAGES_PRESET_OUT_ASIS; + } + ], + 'quality' => [ + 'title' => LANG_IMAGES_PRESET_QUALITY, + 'switchable' => true, + 'handler' => function ($val, $row) { + return $val . ' %'; + }, + 'editable' => [], + 'width' => 70 + ], + 'is_square' => [ + 'title' => LANG_IMAGES_PRESET_CROP, + 'switchable' => true, + 'flag' => true, + 'width' => 120 + ], + 'is_watermark' => [ + 'title' => LANG_IMAGES_PRESET_WM, + 'switchable' => true, + 'flag' => true, + 'width' => 100 + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'presets_edit', array('{id}')), - ), - array( - 'title' => LANG_DELETE, - 'class' => 'delete', - 'href' => href_to($controller->root_url, 'presets_delete', array('{id}')), + 'href' => href_to($controller->root_url, 'presets_edit', ['{id}']), + ], + [ + 'title' => LANG_DELETE, + 'class' => 'delete', + 'href' => href_to($controller->root_url, 'presets_delete', ['{id}']), 'confirm' => LANG_IMAGES_PRESET_DELETE_CONFIRM, - 'handler' => function($row){ - if($row['is_internal']){ return false; } - return true; - } - ) - ); + 'handler' => function ($row) { + if ($row['is_internal']) { + return false; + } + return true; + } + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/languages/backend.php b/system/controllers/languages/backend.php index 77bb6f57d..d63537c3b 100644 --- a/system/controllers/languages/backend.php +++ b/system/controllers/languages/backend.php @@ -4,15 +4,11 @@ class backendLanguages extends cmsBackend { public $useDefaultOptionsAction = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - public function getBackendMenu() { return [ [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] diff --git a/system/controllers/menu/model.php b/system/controllers/menu/model.php index c85b162f5..cda540a3f 100755 --- a/system/controllers/menu/model.php +++ b/system/controllers/menu/model.php @@ -306,16 +306,6 @@ public function getMenuItem($id){ //============================================================================// //============================================================================// - public function reorderMenuItems($items_ids_list){ - - $this->reorderByList('menu_items', $items_ids_list); - - cmsCache::getInstance()->clean('menu.items'); - - return true; - - } - public function addMenuItem($item){ $this->filterEqual('parent_id', $item['parent_id']); diff --git a/system/controllers/messages/backend.php b/system/controllers/messages/backend.php index 0d2640d38..8096c218c 100755 --- a/system/controllers/messages/backend.php +++ b/system/controllers/messages/backend.php @@ -2,8 +2,14 @@ class backendMessages extends cmsBackend { + use \icms\controllers\admin\traits\queueActions; + public $useDefaultOptionsAction = true; + /** + * Для трейта queueActions + * @var array + */ public $queue = [ 'queues' => ['email'], 'queue_name' => LANG_EMAIL, @@ -17,7 +23,7 @@ public function __construct(cmsRequest $request) { array_unshift($this->backend_menu, [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] @@ -33,8 +39,4 @@ public function __construct(cmsRequest $request) { } - public function actionIndex() { - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/moderation/backend.php b/system/controllers/moderation/backend.php index dbb5b811b..7a3589006 100755 --- a/system/controllers/moderation/backend.php +++ b/system/controllers/moderation/backend.php @@ -4,15 +4,11 @@ class backendModeration extends cmsBackend { public $useDefaultOptionsAction = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - public function getBackendMenu() { return [ [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] diff --git a/system/controllers/photos/backend.php b/system/controllers/photos/backend.php index 53a66fc5f..725592bf0 100755 --- a/system/controllers/photos/backend.php +++ b/system/controllers/photos/backend.php @@ -7,10 +7,6 @@ class backendPhotos extends cmsBackend { public $maintained_ctype = 'albums'; public $useSeoOptions = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - public function getOptionsToolbar() { cmsCore::loadControllerLanguage('images'); @@ -24,7 +20,6 @@ public function getOptionsToolbar() { ]); return []; - } } diff --git a/system/controllers/rating/backend.php b/system/controllers/rating/backend.php index 4714d0b2a..c0fad70d0 100755 --- a/system/controllers/rating/backend.php +++ b/system/controllers/rating/backend.php @@ -4,8 +4,4 @@ class backendRating extends cmsBackend{ public $useDefaultOptionsAction = true; - public function actionIndex(){ - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/recaptcha/backend.php b/system/controllers/recaptcha/backend.php index 0687d0d1f..45aff9bfe 100755 --- a/system/controllers/recaptcha/backend.php +++ b/system/controllers/recaptcha/backend.php @@ -4,8 +4,4 @@ class backendRecaptcha extends cmsBackend{ public $useDefaultOptionsAction = true; - public function actionIndex(){ - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/redirect/backend.php b/system/controllers/redirect/backend.php index da7338940..6b5fc06de 100755 --- a/system/controllers/redirect/backend.php +++ b/system/controllers/redirect/backend.php @@ -4,8 +4,4 @@ class backendRedirect extends cmsBackend { public $useDefaultOptionsAction = true; - public function actionIndex(){ - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/rss/backend/grids/grid_feeds.php b/system/controllers/rss/backend/grids/grid_feeds.php index 9ba39c6ef..4f05eec30 100755 --- a/system/controllers/rss/backend/grids/grid_feeds.php +++ b/system/controllers/rss/backend/grids/grid_feeds.php @@ -1,50 +1,49 @@ 'title', 'order_to' => 'asc', - ); + ]; - $columns = array( - 'title' => array( - 'title' => LANG_RSS_FEED_TITLE, - 'href' => href_to($controller->root_url, 'edit', array('{id}')), + $columns = [ + 'title' => [ + 'title' => LANG_RSS_FEED_TITLE, + 'href' => href_to($controller->root_url, 'edit', ['{id}']), 'filter' => 'like' - ), - 'is_enabled' => array( - 'title' => LANG_IS_ENABLED, - 'flag' => true, - 'width' => 60, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'rss_feeds', 'is_enabled')) - ), - 'is_cache' => array( - 'title' => LANG_RSS_FEED_IS_CACHE, - 'flag' => true, - 'width' => 60, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', 'rss_feeds', 'is_cache')) - ), - ); + ], + 'is_enabled' => [ + 'title' => LANG_IS_ENABLED, + 'flag' => true, + 'width' => 60, + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'rss_feeds', 'is_enabled']) + ], + 'is_cache' => [ + 'title' => LANG_RSS_FEED_IS_CACHE, + 'flag' => true, + 'width' => 60, + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', 'rss_feeds', 'is_cache']) + ] + ]; - $actions = array( - array( - 'title' => LANG_VIEW, - 'class' => 'rss', - 'href' => href_to('rss', 'feed', '{ctype_name}') - ), - array( + $actions = [ + [ + 'title' => LANG_VIEW, + 'target' => '_blank', + 'class' => 'rss', + 'href' => href_to('rss', 'feed', '{ctype_name}') + ], + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'edit', array('{id}')), - ), - ); + 'href' => href_to($controller->root_url, 'edit', ['{id}']), + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } - diff --git a/system/controllers/search/backend.php b/system/controllers/search/backend.php index 8ed7eec30..4c2687487 100755 --- a/system/controllers/search/backend.php +++ b/system/controllers/search/backend.php @@ -5,8 +5,4 @@ class backendSearch extends cmsBackend{ public $useDefaultOptionsAction = true; public $useSeoOptions = true; - public function actionIndex(){ - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/sitemap/backend.php b/system/controllers/sitemap/backend.php index 99185c5cb..6d49837ee 100755 --- a/system/controllers/sitemap/backend.php +++ b/system/controllers/sitemap/backend.php @@ -5,8 +5,4 @@ class backendSitemap extends cmsBackend { protected $useOptions = true; public $useDefaultOptionsAction = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/subscriptions/backend.php b/system/controllers/subscriptions/backend.php index 1dc608069..879fd232c 100755 --- a/system/controllers/subscriptions/backend.php +++ b/system/controllers/subscriptions/backend.php @@ -2,9 +2,15 @@ class backendSubscriptions extends cmsBackend { + use \icms\controllers\admin\traits\queueActions; + protected $useOptions = true; public $useDefaultOptionsAction = true; + /** + * Для трейта queueActions + * @var array + */ public $queue = [ 'queues' => ['subscriptions'], 'queue_name' => LANG_SBSCR_QUEUE_NAME, @@ -18,7 +24,7 @@ public function __construct(cmsRequest $request) { array_unshift($this->backend_menu, [ 'title' => LANG_OPTIONS, - 'url' => href_to($this->root_url, 'options'), + 'url' => href_to($this->root_url), 'options' => [ 'icon' => 'cog' ] @@ -34,8 +40,4 @@ public function __construct(cmsRequest $request) { } - public function actionIndex() { - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/subscriptions/backend/actions/list.php b/system/controllers/subscriptions/backend/actions/list.php index 2498f9aac..17d9f80f4 100755 --- a/system/controllers/subscriptions/backend/actions/list.php +++ b/system/controllers/subscriptions/backend/actions/list.php @@ -21,19 +21,16 @@ public function __construct($controller, $params = []) { ] ]; - $this->items_callback = function($items){ + $this->item_callback = function ($item, $model) { - if($items){ + $item['params'] = cmsModel::stringToArray($item['params']); - foreach ($items as $key => $item) { - - $items[$key]['params'] = cmsModel::stringToArray($item['params']); - } - } + return $item; + }; - $items = cmsEventsManager::hook('admin_subscriptions_list', $items); + $this->items_callback = function ($items) { - return $items; + return cmsEventsManager::hook('admin_subscriptions_list', $items); }; } diff --git a/system/controllers/subscriptions/backend/grids/grid_subscriptions.php b/system/controllers/subscriptions/backend/grids/grid_subscriptions.php index 6928eb4dd..4dc91a34c 100644 --- a/system/controllers/subscriptions/backend/grids/grid_subscriptions.php +++ b/system/controllers/subscriptions/backend/grids/grid_subscriptions.php @@ -6,7 +6,7 @@ function grid_subscriptions($controller) { $options = [ 'is_sortable' => false, - 'show_id' => true, + 'show_id' => false, 'is_selectable' => true, 'order_by' => 'subscribers_count', 'order_to' => 'desc' @@ -14,22 +14,18 @@ function grid_subscriptions($controller) { $columns = [ 'id' => [ - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30 + 'title' => 'id' ], 'title' => [ 'title' => LANG_TITLE, - 'editable' => [ - 'table' => 'subscriptions' - ], + 'editable' => [], 'filter' => 'like' ], 'controller' => [ 'title' => LANG_EVENTS_LISTENER, 'class' => 'd-none d-lg-table-cell', 'width' => 200, - 'filter' => 'like', + 'filter' => 'exact', 'filter_select' => [ 'items' => function ($name) { @@ -37,7 +33,7 @@ function grid_subscriptions($controller) { $admin_model->join('subscriptions', 's', 's.controller = i.name'); $controllers = $admin_model->groupBy('i.id')->getInstalledControllers(); - $items = ['' => '']; + $items = ['' => LANG_ALL]; foreach ($controllers as $controller) { $items[$controller['name']] = $controller['title']; } @@ -61,9 +57,10 @@ function grid_subscriptions($controller) { $actions = [ [ - 'title' => LANG_VIEW, - 'class' => 'view', - 'href' => rel_to_href('{subject_url}') + 'title' => LANG_VIEW, + 'class' => 'view', + 'target' => '_blank', + 'href' => rel_to_href('{subject_url}') ], [ 'title' => LANG_DELETE, diff --git a/system/controllers/tags/backend/grids/grid_tags.php b/system/controllers/tags/backend/grids/grid_tags.php index 597606374..3116f7ddd 100755 --- a/system/controllers/tags/backend/grids/grid_tags.php +++ b/system/controllers/tags/backend/grids/grid_tags.php @@ -20,9 +20,10 @@ function grid_tags($controller) { $actions = [ [ - 'title' => LANG_VIEW, - 'class' => 'view', - 'href' => href_to('tags', '{tag|string_urlencode}') + 'title' => LANG_VIEW, + 'class' => 'view', + 'target' => '_blank', + 'href' => href_to('tags', '{tag|string_urlencode}') ], [ 'title' => LANG_EDIT, diff --git a/system/controllers/users/backend/actions/fields.php b/system/controllers/users/backend/actions/fields.php index 39bd17c5b..c8274009d 100755 --- a/system/controllers/users/backend/actions/fields.php +++ b/system/controllers/users/backend/actions/fields.php @@ -22,25 +22,20 @@ public function __construct($controller, $params = []) { $this->list_callback = function ($model) { - $model->orderBy('ordering', 'asc'); + $model->selectTranslatedField('i.values', $this->table_name, 'default'); return $model; }; - $this->items_callback = function ($items) { + $this->item_callback = function ($item, $model) { - if($items){ - foreach ($items as $key => $item) { + $field_class = 'field' . string_to_camel('_', $item['type']); - $field_class = 'field' . string_to_camel('_', $item['type']); + $handler = new $field_class($item['name']); - $handler = new $field_class($item['name']); + $item['handler_title'] = $handler->getTitle(); - $items[$key]['handler_title'] = $handler->getTitle(); - } - } - - return $items; + return $item; }; } diff --git a/system/controllers/users/backend/actions/fields_reorder.php b/system/controllers/users/backend/actions/fields_reorder.php deleted file mode 100755 index b8ee7ff1e..000000000 --- a/system/controllers/users/backend/actions/fields_reorder.php +++ /dev/null @@ -1,29 +0,0 @@ -request->get('items', array()); - if (!$items){ cmsCore::error404(); } - - $content_model = cmsCore::getModel('content'); - - $content_model->setTablePrefix(''); - - $content_model->reorderContentFields('{users}', $items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/users/backend/actions/tabs_reorder.php b/system/controllers/users/backend/actions/tabs_reorder.php deleted file mode 100755 index 1b75abe22..000000000 --- a/system/controllers/users/backend/actions/tabs_reorder.php +++ /dev/null @@ -1,25 +0,0 @@ -request->get('items', array()); - if (!$items){ cmsCore::error404(); } - - $this->model->reorderUsersProfilesTabs($items); - - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array( - 'error' => false, - 'success_text' => LANG_CP_ORDER_SUCCESS - )); - } - - cmsUser::addSessionMessage(LANG_CP_ORDER_SUCCESS, 'success'); - - $this->redirectBack(); - - } - -} diff --git a/system/controllers/users/backend/grids/grid_fields.php b/system/controllers/users/backend/grids/grid_fields.php index e6d638978..23b14ae6f 100755 --- a/system/controllers/users/backend/grids/grid_fields.php +++ b/system/controllers/users/backend/grids/grid_fields.php @@ -7,7 +7,7 @@ function grid_fields($controller) { 'is_filter' => true, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('fields_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', '{users}_fields'), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false @@ -21,9 +21,7 @@ function grid_fields($controller) { 'title' => [ 'title' => LANG_CP_FIELD_TITLE, 'href' => href_to($controller->root_url, 'fields_edit', ['users', '{id}']), - 'editable' => [ - 'table' => '{users}_fields' - ] + 'editable' => [] ], 'fieldset' => [ 'title' => LANG_CP_FIELD_FIELDSET, diff --git a/system/controllers/users/backend/grids/grid_migrations.php b/system/controllers/users/backend/grids/grid_migrations.php index dae02869d..7beac8e89 100755 --- a/system/controllers/users/backend/grids/grid_migrations.php +++ b/system/controllers/users/backend/grids/grid_migrations.php @@ -1,73 +1,69 @@ false, 'is_filter' => false - ); + ]; - $columns = array( - 'id' => array( - 'title' => 'id', - 'class' => 'd-none d-lg-table-cell', - 'width' => 30 - ), - 'title' => array( + $columns = [ + 'id' => [ + 'title' => 'id' + ], + 'title' => [ 'title' => LANG_USERS_MIG_TITLE, - 'href' => href_to($controller->root_url, 'migrations_edit', array('{id}')), - 'editable' => array( - 'table' => '{users}_groups_migration' - ) - ), - 'passed_days' => array( + 'href' => href_to($controller->root_url, 'migrations_edit', ['{id}']), + 'editable' => [] + ], + 'passed_days' => [ 'title' => LANG_USERS_MIG_PASSED_DAYS, - 'handler' => function($val) { + 'handler' => function ($val) { return $val ? $val : '—'; }, - 'width' => 80 - ), - 'rating' => array( + 'width' => 80 + ], + 'rating' => [ 'title' => LANG_RATING, 'class' => 'd-none d-lg-table-cell', - 'handler' => function($val) { + 'handler' => function ($val) { return $val ? $val : '—'; }, - 'width' => 80 - ), - 'karma' => array( + 'width' => 80 + ], + 'karma' => [ 'title' => LANG_KARMA, 'class' => 'd-none d-lg-table-cell', - 'handler' => function($val) { + 'handler' => function ($val) { return $val ? $val : '—'; }, 'width' => 80 - ), - 'is_active' => array( - 'title' => LANG_ON, - 'flag' => true, - 'width' => 60, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', '{users}_groups_migration', 'is_active')) - ) - ); + ], + 'is_active' => [ + 'title' => LANG_ON, + 'flag' => true, + 'width' => 60, + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', '{users}_groups_migration', 'is_active']) + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'migrations_edit', array('{id}')) - ), - array( + 'href' => href_to($controller->root_url, 'migrations_edit', ['{id}']) + ], + [ 'title' => LANG_DELETE, 'class' => 'delete', - 'href' => href_to($controller->root_url, 'migrations_delete', array('{id}')), + 'href' => href_to($controller->root_url, 'migrations_delete', ['{id}']), 'confirm' => LANG_USERS_MIG_DELETE_CONFIRM - ) - ); + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/users/backend/grids/grid_tabs.php b/system/controllers/users/backend/grids/grid_tabs.php index 8ea74c6b9..b5d2bdbae 100755 --- a/system/controllers/users/backend/grids/grid_tabs.php +++ b/system/controllers/users/backend/grids/grid_tabs.php @@ -1,55 +1,52 @@ false, 'is_filter' => false, 'is_pagination' => false, 'is_draggable' => true, - 'drag_save_url' => $controller->cms_template->href_to('tabs_reorder'), + 'drag_save_url' => href_to('admin', 'reorder', '{users}_tabs'), 'order_by' => 'ordering', 'order_to' => 'asc', 'show_id' => false - ); + ]; - $columns = array( - 'id' => array( + $columns = [ + 'id' => [ 'title' => 'id', 'width' => 30 - ), - 'title' => array( + ], + 'title' => [ 'title' => LANG_CP_TAB_TITLE, - 'href' => href_to($controller->root_url, 'tabs_edit', array('{id}')), - 'editable' => array( - 'table' => '{users}_tabs' - ) - ), - 'name' => array( + 'href' => href_to($controller->root_url, 'tabs_edit', ['{id}']), + 'editable' => [] + ], + 'name' => [ 'title' => LANG_SYSTEM_NAME, 'class' => 'd-none d-lg-table-cell', 'width' => 150 - ), - 'is_active' => array( - 'title' => LANG_SHOW, - 'flag' => true, - 'width' => 60, - 'flag_toggle' => href_to($controller->root_url, 'toggle_item', array('{id}', '{users}_tabs', 'is_active')) - ) - ); + ], + 'is_active' => [ + 'title' => LANG_SHOW, + 'flag' => true, + 'width' => 60, + 'flag_toggle' => href_to($controller->root_url, 'toggle_item', ['{id}', '{users}_tabs', 'is_active']) + ] + ]; - $actions = array( - array( + $actions = [ + [ 'title' => LANG_EDIT, 'class' => 'edit', - 'href' => href_to($controller->root_url, 'tabs_edit', array('{id}')) - ) - ); + 'href' => href_to($controller->root_url, 'tabs_edit', ['{id}']) + ] + ]; - return array( + return [ 'options' => $options, 'columns' => $columns, 'actions' => $actions - ); - + ]; } diff --git a/system/controllers/users/model.php b/system/controllers/users/model.php index a3f5a47a2..4b3f7698a 100755 --- a/system/controllers/users/model.php +++ b/system/controllers/users/model.php @@ -1187,15 +1187,6 @@ public function getUsersProfilesTabs($only_active = false, $by_field = 'id') { }, $by_field); } - public function reorderUsersProfilesTabs($fields_ids_list) { - - $this->reorderByList('{users}_tabs', $fields_ids_list); - - cmsCache::getInstance()->clean('users.tabs'); - - return true; - } - //============================================================================// //============================== СТАТУСЫ ================================// //============================================================================// diff --git a/system/controllers/wall/backend.php b/system/controllers/wall/backend.php index d5e4c9d30..861e30eef 100755 --- a/system/controllers/wall/backend.php +++ b/system/controllers/wall/backend.php @@ -6,8 +6,4 @@ class backendWall extends cmsBackend { protected $useOptions = true; - public function actionIndex() { - $this->redirectToAction('options'); - } - } diff --git a/system/controllers/wysiwygs/backend/grids/grid_presets.php b/system/controllers/wysiwygs/backend/grids/grid_presets.php index b9b889596..25418f4f3 100755 --- a/system/controllers/wysiwygs/backend/grids/grid_presets.php +++ b/system/controllers/wysiwygs/backend/grids/grid_presets.php @@ -18,10 +18,10 @@ function grid_presets($controller){ 'wysiwyg_name' => [ 'title' => LANG_PARSER_HTML_EDITOR, 'width' => 150, - 'filter' => 'like', + 'filter' => 'exact', 'filter_select' => array( 'items' => function($name){ - $items = ['' => '']; + $items = ['' => LANG_ALL]; $editors = cmsCore::getWysiwygs(); foreach($editors as $editor){ $items[$editor] = $editor; @@ -37,9 +37,7 @@ function grid_presets($controller){ 'title' => LANG_WW_PRESET_TITLE, 'filter' => 'like', 'href' => href_to($controller->root_url, 'presets_edit', ['{id}']), - 'editable' => [ - 'table' => 'wysiwygs_presets' - ] + 'editable' => [] ] ]; diff --git a/system/core/action.php b/system/core/action.php index 0d83087b3..6ea296e99 100755 --- a/system/core/action.php +++ b/system/core/action.php @@ -26,7 +26,7 @@ public function __construct($controller, $params = []) { } } - public function __get($name) { + public function &__get($name) { return $this->controller->$name; } diff --git a/system/core/backend.php b/system/core/backend.php index a0004674a..497bcac16 100755 --- a/system/core/backend.php +++ b/system/core/backend.php @@ -9,12 +9,6 @@ class cmsBackend extends cmsController { protected $backend_menu = []; protected $backend_sub_menu = []; - public $queue = [ - 'queues' => [], - 'queue_name' => '', - 'use_queue_action' => false - ]; - protected $useDefaultModerationAction = false; protected $useModerationTrash = false; @@ -35,16 +29,6 @@ public function __construct(cmsRequest $request) { } $this->setRootURL($admin_controller_url . '/controllers/edit/' . $this->name); - if (!empty($this->queue['use_queue_action'])) { - $this->backend_menu[] = [ - 'title' => sprintf(LANG_CP_QUEUE_TITLE, $this->queue['queue_name']), - 'url' => href_to($this->root_url, 'queue'), - 'options' => [ - 'icon' => 'recycle' - ] - ]; - } - if (!empty($this->useDefaultModerationAction)) { $this->backend_menu[] = [ 'title' => LANG_MODERATORS, @@ -237,6 +221,10 @@ public function actionOptions() { cmsEventsManager::hook("controller_{$this->name}_after_save_options", $options); + if (!$this->isActionExists('index')) { + return $this->redirectToAction(); + } + return $this->redirectToAction('options'); } @@ -363,102 +351,6 @@ public function actionPermsSave($subject = '') { return $this->redirectBack(); } -//============================================================================// -//========= Очереди =========// -//============================================================================// - - /** - * Экшен очереди - * - * @return string - */ - public function actionQueue() { - - if (empty($this->queue['use_queue_action'])) { - return cmsCore::error404(); - } - - $grid = $this->controller_admin->loadDataGrid('queue', ['contex_controller' => $this]); - - if ($this->request->isAjax()) { - - $filter = []; - $filter_str = $this->request->get('filter', ''); - - if ($filter_str) { - parse_str($filter_str, $filter); - } - - $this->controller_admin->model->filterIn('queue', $this->queue['queues']); - - $total = $this->controller_admin->model->getCount(cmsQueue::getTableName()); - - $perpage = isset($filter['perpage']) ? $filter['perpage'] : admin::perpage; - $page = isset($filter['page']) ? intval($filter['page']) : 1; - - $pages = ceil($total / $perpage); - - $this->controller_admin->model->limitPage($page, $perpage); - - $this->controller_admin->model->orderByList([ - ['by' => 'date_started', 'to' => 'asc'], - ['by' => 'priority', 'to' => 'desc'], - ['by' => 'date_created', 'to' => 'asc'] - ]); - - $jobs = $this->controller_admin->model->get(cmsQueue::getTableName()); - - $this->cms_template->renderGridRowsJSON($grid, $jobs, $total, $pages); - - $this->halt(); - } - - return $this->cms_template->getRenderedAsset('ui/grid', [ - 'grid' => $grid, - 'page_title' => sprintf(LANG_CP_QUEUE_TITLE, $this->queue['queue_name']), - 'source_url' => href_to($this->root_url, 'queue'), - ]); - } - - /** - * Экшен рестарта задания очереди - * - * @param integer $job_id - * @return type - */ - public function actionQueueRestart($job_id) { - - if (empty($this->queue['use_queue_action'])) { - return cmsCore::error404(); - } - - cmsQueue::restartJob(['id' => $job_id]); - - return $this->redirectBack(); - } - - /** - * Экшен удаления задания очереди - * - * @param integer $job_id - * @return type - */ - public function actionQueueDelete($job_id) { - - if (empty($this->queue['use_queue_action'])) { - return cmsCore::error404(); - } - - $csrf_token = $this->request->get('csrf_token', ''); - if (!cmsForm::validateCSRFToken($csrf_token)) { - return cmsCore::error404(); - } - - cmsQueue::deleteJob(['id' => $job_id]); - - return $this->redirectBack(); - } - //============================================================================// //========= Модераторы =========// //============================================================================// diff --git a/system/core/controller.php b/system/core/controller.php index 5ea913c7b..4ed1d6917 100755 --- a/system/core/controller.php +++ b/system/core/controller.php @@ -441,36 +441,39 @@ public function afterHook($event_name){ /** * Проверяет существование экшена - * @param string $action_name + * + * @param string $action_name Имя экшена * @return boolean */ - public function isActionExists($action_name){ + public function isActionExists($action_name) { $method_name = 'action' . string_to_camel('_', $action_name); - if(method_exists($this, $method_name)){ + if (method_exists($this, $method_name)) { return true; } $action_file = $this->getExternalActionPath($action_name); - if (is_readable($action_file)){ + if (is_readable($action_file)) { return true; } return false; - } /** * Запускает требуемый экшен - * @param string $action_name - * @param array $params + * + * @param string $action_name Имя экшена + * @param array $params Параметры в метод запуска экшена * @return mixed */ - public function runAction($action_name, $params = array()){ + public function runAction($action_name, $params = []) { - if ($this->before($action_name) === false) { return false; } + if ($this->before($action_name) === false) { + return false; + } $this->current_params = $params; @@ -481,64 +484,61 @@ public function runAction($action_name, $params = array()){ $this->after($action_name); return $result; - } /** * Находит и выполняет требуемый экшен - * @param string $action_name - * @param array $params + * + * @param string $action_name Имя экшена + * @param array $params Параметры в метод запуска экшена * @return mixed */ - public function executeAction($action_name, $params = array()) { + public function executeAction($action_name, $params = []) { $method_name = 'action' . string_to_camel('_', $action_name); // проверяем наличие экшена его в отдельном файле $action_file = $this->getExternalActionPath($action_name); - if(is_readable($action_file)){ + if (is_readable($action_file)) { // вызываем экшен из отдельного файла $result = $this->runExternalAction($action_name, $params); - } else { // Если файла нет, ищем метод класса - if (method_exists($this, $method_name)){ + if (method_exists($this, $method_name)) { - if (!$this->validateParamsCount($this, $method_name, $params)) { cmsCore::error404(); } + if (!$this->validateParamsCount($this, $method_name, $params)) { + return cmsCore::error404(); + } // сохраняем название текущего экшена $this->setCurrentAction($action_name); // если есть нужный экшен, то вызываем его - $result = call_user_func_array(array($this, $method_name), $params); - + $result = call_user_func_array([$this, $method_name], $params); } else { // если нет экшена в отдельном файле, // проверяем метод route() - if(method_exists($this, 'route')){ + if (method_exists($this, 'route')) { $route_uri = $action_name; - if ($params) { $route_uri .= '/' . implode('/', $params); } - $result = call_user_func(array($this, 'route'), $route_uri); - + if ($params) { + $route_uri .= '/' . implode('/', $params); + } + $result = call_user_func([$this, 'route'], $route_uri); } else { // если метода route() тоже нет, // то 404 - cmsCore::error404(); - + return cmsCore::error404(); } - } - } return $result; - } /** @@ -587,27 +587,30 @@ public function setCurrentAction($action_name) { /** * Выполняет экшен, находящийся в отдельном файле + * * @param string $action_name Название экшена * @param array $params Параметры * @return mixed */ - public function runExternalAction($action_name, $params = array()){ + public function runExternalAction($action_name, $params = []) { $action_file = $this->getExternalActionPath($action_name); $class_name = 'action' . string_to_camel('_', $this->name) . string_to_camel('_', $action_name); - if (!is_readable($action_file)){ - cmsCore::error(ERR_FILE_NOT_FOUND . ': '. str_replace(PATH, '', $action_file)); + if (!is_readable($action_file)) { + return cmsCore::error(ERR_FILE_NOT_FOUND . ': ' . str_replace(PATH, '', $action_file)); } include_once $action_file; - if(!class_exists($class_name, false)){ - cmsCore::error(sprintf(ERR_CLASS_NOT_DEFINED, str_replace(PATH, '', $action_file), $class_name)); + if (!class_exists($class_name, false)) { + return cmsCore::error(sprintf(ERR_CLASS_NOT_DEFINED, str_replace(PATH, '', $action_file), $class_name)); } - if (!$this->validateParamsCount($class_name, 'run', $params)) { cmsCore::error404(); } + if (!$this->validateParamsCount($class_name, 'run', $params)) { + return cmsCore::error404(); + } // сохраняем название текущего экшена $this->setCurrentAction($action_name); @@ -615,22 +618,23 @@ public function runExternalAction($action_name, $params = array()){ $action_object = new $class_name($this, $params); // проверяем разрешен ли прямой вызов экшена - if($action_object->lock_explicit_call === true && $this->lock_explicit_call !== false && !$this->request->isInternal()){ - cmsCore::error404(); + if ($action_object->lock_explicit_call === true && $this->lock_explicit_call !== false && !$this->request->isInternal()) { + return cmsCore::error404(); } // проверяем параметры если нужно $params_error = $this->validateRequestParams($action_object); - if($params_error !== false){ - if ($this->request->isAjax()){ - return $this->cms_template->renderJSON(array('error' => true, 'errors' => $params_error, 'message' => sprintf(LANG_REQUEST_PARAMS_ERROR, implode(', ', array_keys($params_error))))); + if ($params_error !== false) { + + if ($this->request->isAjax()) { + + return $this->cms_template->renderJSON(['error' => true, 'errors' => $params_error, 'message' => sprintf(LANG_REQUEST_PARAMS_ERROR, implode(', ', array_keys($params_error)))]); } else { - cmsCore::error(LANG_ERROR, sprintf(LANG_REQUEST_PARAMS_ERROR, implode(', ', array_keys($params_error)))); + return cmsCore::error(LANG_ERROR, sprintf(LANG_REQUEST_PARAMS_ERROR, implode(', ', array_keys($params_error)))); } } - return call_user_func_array(array($action_object, 'run'), $params); - + return call_user_func_array([$action_object, 'run'], $params); } /** @@ -855,143 +859,35 @@ public function getControllerForm($controller_name, $form_name, $params = false, //============================================================================// //============================================================================// - /** - * Возвращает параметры грида - * - * @param string $grid_name - * @param mixed $params - * @return array - */ - public function getDataGrid($grid_name, $params = false) { - - $default_options = [ - 'order_by' => 'id', - 'order_to' => 'asc', - 'show_id' => true, - 'is_auto_init' => true, - 'is_sortable' => true, - 'is_filter' => true, - 'is_actions' => true, - 'is_pagination' => true, - 'perpage' => 30, - 'is_toolbar' => true, - 'is_draggable' => false, - 'drag_save_url' => '', - 'is_selectable' => false, - 'load_columns' => false - ]; - - $grid_file = $this->root_path . 'grids/grid_' . $grid_name . '.php'; - - if (!is_readable($grid_file)) { - return [false, []]; - } - - include_once ($grid_file); - - $args = [$this]; - if ($params) { - if (!is_array($params)) { - $params = [$params]; - } - foreach ($params as $p) { - $args[] = $p; - } - } - - $grid = call_user_func_array('grid_' . $grid_name, $args); - - if (!isset($grid['options'])) { - $grid['options'] = $default_options; - } else { - $grid['options'] = array_merge($default_options, $grid['options']); - } - - return [$grid, $args]; - } - - /** - * Возвращает отключаемые колонки грида - * - * @param string $grid_name - * @param mixed $params - * @return type - */ - public function getDataGridSwitchableColumns($grid_name, $params = false) { - - list($grid, $args) = $this->getDataGrid($grid_name, $params); - - if (!$grid){ - return []; - } - - $columns = []; - - foreach ($grid['columns'] as $key => $item) { - if(!empty($item['switchable'])){ - $columns[$key] = $item['title']; - } - } - - return $columns; - } - /** * Загружает и возвращает описание структуры grid таблицы + * * @param string $grid_name Название - * @param array $params Параметры для передачи в функцию описания grid-а - * @param mixed $ups_key Ключ UPS или готовый массив параметров - * @return array || false + * @param ?array $params Параметры для передачи в функцию описания грида + * @param type $ups_key Ключ UPS + * @return \cmsGrid */ - public function loadDataGrid($grid_name, $params = false, $ups_key = '') { + public function loadDataGrid($grid_name, $params = null, $ups_key = '') : cmsGrid { - list($grid, $args) = $this->getDataGrid($grid_name, $params); + $grid = new cmsGrid($this, $grid_name, $params); - if (!$grid){ - return cmsCore::error(ERR_FILE_NOT_FOUND . ': '. str_replace(PATH, '', $this->root_path . 'grids/grid_' . $grid_name . '.php')); - } + if (!$grid->isLoaded()) { - $grid = cmsEventsManager::hook('grid_' . $this->name . '_' . $grid_name, $grid); - list($grid, $args) = cmsEventsManager::hook('grid_' . $this->name . '_' . $grid_name . '_args', array($grid, $args)); + return cmsCore::error($this->grid->getError()); + } if ($ups_key) { - $filter_str = is_array($ups_key) ? $ups_key : cmsUser::getUPS($ups_key); - if ($filter_str) { - $filter = []; - if(is_array($filter_str)){ - - if(!empty($filter_str['filter'])){ - parse_str($filter_str['filter'], $filter); - } - - if(!empty($filter_str['columns'])){ - foreach ($filter_str['columns'] as $key => $is_enabled) { - if(!$is_enabled && isset($grid['columns'][$key])){ - unset($grid['columns'][$key]); - } - } - $grid['options']['load_columns'] = true; - } - } else { - parse_str($filter_str, $filter); - } - $grid['filter'] = $filter; - } - } - if ($this->request->isAjax() && $this->request->has('heads')) { + $filter = []; - $heads = $this->request->get('heads', array()); - natsort($heads); + $pre_filter = cmsUser::getUPSActual($ups_key, $this->request->get('filter', '')); - $grid_heads = array_keys($grid['columns']); - if ($grid['actions']) { - $grid_heads[] = 'dg_actions'; + if ($pre_filter) { + parse_str($pre_filter, $filter); } - natsort($grid_heads); - if ($heads !== $grid_heads) { - $grid['options']['load_columns'] = true; + if ($filter) { + $grid->addToFilter($filter); } } diff --git a/system/core/grid.php b/system/core/grid.php new file mode 100755 index 000000000..8b6040881 --- /dev/null +++ b/system/core/grid.php @@ -0,0 +1,933 @@ + '', + // Опции списка + 'options' => [ + 'order_by' => 'id', // Поле сортировки + 'order_to' => 'asc', // Направление сортировки + 'show_id' => true, // Показывать id записи + 'is_sortable' => true, // Можно сортировать + 'is_filter' => true, // Поля грида можно фильтровать + 'advanced_filter' => false, // URL для дополнительного фильтра записей + 'is_pagination' => true, // показывать пагинацию + 'perpage' => 30, // записей на странице по умолчанию + 'is_toolbar' => true, // выводить тулбар + 'is_draggable' => false, // строки могут меняться местами мышью + 'drag_save_url' => '', // URL для сохранения при драг-эн-дроп + 'is_selectable' => false, // Строки могут выделяться + /** + * select_actions - это массив действий над выделенными строками + * Пример в system/controllers/admin/grids/grid_content_items.php + 'title' => Название, + 'action' => submit || open, + 'confirm' => Фраза подтверждения действия, + 'url' => URL на который отправлять выделенные записи + */ + 'select_actions' => false + ], + // Колонки параметров + 'columns' => [], + // Действия над записью + 'actions' => [], + // Фильтр записей. Не заполняйте его из функции описания грида + 'filter' => [] + ]; + + /** + * Все значения колонки по умолчанию + * @var array + */ + private $default_column = [ + 'tooltip' => '', // Текст всплывающей подсказки + 'tooltip_handler' => null, // Функция обработчик, возвращающая текст всплывающей подсказки + 'switchable' => false, // Может включаться/выключаться + 'disable' => false, // Если может включаться/выключаться выключение по умолчанию + 'sortable' => true, // Можено сортировать по ней + 'title' => '', // Заголовок + 'class' => '', // CSS класс + 'key_alias' => '', // Псевдоним поля + 'handler' => null, // Функция обработчик значения колонки + 'flag' => false, // Колонка - флаг (включена/выключена) + 'flag_on' => null, // Значение, с которым сравнивается запись, чтобы флажок был включен + 'flag_handler' => null, // Функция обработчик значения для флага + 'flag_toggle' => '', // URL переключения состояния флага + 'href' => '', // Ссылка колонки + 'href_handler' => null, // Функция обработчик, если возвращает true, то ссылка показывается + 'order_by' => '', // Имя поля, по которому нужно сортировать + 'filter_by' => '', // Имя поля, по которому нужно фильтровать + 'filter' => '', // Тип фильтра, см. applyGridFilter + 'filter_select' => ['items' => []], // Массив значений для select тега фильтра + 'filter_attributes' => [], // Атрибуты тега фильтрации + 'editable' => [ // Может редактироваться из списка + 'rules' => [], // Массив правил валидации при сохранении + 'language_context' => false, // Если выключено, будет искать языковое поле для текущей локали + 'save_action' => '', // URL для сохранения + 'attributes' => [] // Атрибуты тега быстрого редактирования + ] + ]; + + /** + * Колонки, которые нужно показывать + * + * @var ?array + */ + private $visible_columns = null; + + /** + * Имена колонок ключи, включена/выключена значение + * + * @var array + */ + private $visible_columns_names = []; + + /** + * Колонки, которые можно отключать + * + * @var ?array|boolean + */ + private $switchable_columns = null; + + /** + * Маппинг имя фильтра => компонент (vuejs) отрисовки + * @var array + */ + private $filter_component_map = [ + 'range_date' => 'form-date-range', + 'range' => 'form-range', + 'zero' => 'form-checkbox', + 'nn' => 'form-checkbox', + 'ni' => 'form-checkbox', + 'in' => 'form-multiselect', + 'filled' => 'form-select', + 'exact' => 'form-select', + 'like' => 'form-input', + 'ip' => 'form-input', + 'date' => 'form-date' + ]; + + /** + * Объект контроллера + * @var cmsController + */ + private $controller; + + /** + * Имя грида + * @var string + */ + private $grid_name = ''; + + /** + * Параметры, передающиеся в функцию грида + * @var array + */ + private $grid_params = []; + + /** + * Грид успешно загружен? + * @var boolean + */ + private $is_loaded = false; + + /** + * Текст ошибки при инициализации + * @var ?string + */ + private $error = null; + + /** + * + * @param cmsController|cmsAction $controller Объект контроллера (cmsAction с магией тоже), для которого строим грид + * @param string $grid_name Имя грида + * @param ?array $grid_params Параметры инициализации + */ + public function __construct($controller, $grid_name, $grid_params = null) { + + $this->controller = $controller; + + $this->grid_name = $grid_name; + + if($grid_params) { + + $this->grid_params = !is_array($grid_params) ? [$grid_params] : $grid_params; + } + + $this->is_loaded = $this->load(); + } + + public function &__get($name) { + return $this->grid[$name]; + } + + public function __set($name, $value) { + $this->grid[$name] = $value; + } + + public function __isset($name) { + return isset($this->grid[$name]); + } + + public function __unset($name) { + unset($this->grid[$name]); + } + + /** + * Грид успешно загружен? + * + * @return boolean + */ + public function isLoaded() { + return $this->is_loaded; + } + + /** + * Возвращает последнюю ошибку + * + * @return ?string + */ + public function getError() { + return $this->error; + } + + /** + * Загружает и подготовливает параметры грида + * + * @return bool + */ + private function load() { + + $grid_file = $this->controller->root_path . 'grids/grid_' . $this->grid_name . '.php'; + + if (!is_readable($grid_file)) { + + $this->error = ERR_FILE_NOT_FOUND . ': '. str_replace(PATH, '', $grid_file); + + return false; + } + + include_once $grid_file; + + $grid_func_name = 'grid_' . $this->grid_name; + + if(!function_exists($grid_func_name)){ + + $this->error = $grid_func_name.' function not found in '. str_replace(PATH, '', $grid_file); + + return false; + } + + $args = [$this->controller]; + + foreach ($this->grid_params as $p) { + $args[] = $p; + } + + $grid = call_user_func_array($grid_func_name, $args); + + foreach ($grid as $key => $data) { + + $this->grid[$key] = array_merge(($this->grid[$key] ?? []), $data); + } + + // Фильтр по умолчанию + $this->setDefaultFilter(); + + $this->grid = cmsEventsManager::hook('grid_' . $this->controller->name . '_' . $this->grid_name, $this->grid); + + if($this->grid['options']['select_actions']){ + array_unshift($this->grid['options']['select_actions'], [ + 'title' => 'Действия над выбранными', + 'url' => '' + ]); + } + + list($this->grid, $args) = cmsEventsManager::hook( + 'grid_' . $this->controller->name . '_' . $this->grid_name . '_args', + [$this->grid, $args] + ); + + return true; + } + + /** + * Возвращает массив грида целиком + * @return array + */ + public function getGrid() { + return $this->grid; + } + + /** + * Возвращает значение описания грида + * + * @param string $path Путь до ключа, например columns:name:title + * @return mixed + */ + public function getGridValue($path) { + return array_value_recursive($path, $this->grid); + } + + /** + * Валидация значения колонки + * аналогично как в формах + * + * @param string $field_name + * @param mixed $value + * @return boolean + */ + public function validateColumnValue($field_name, $value) { + + $rules = $this->grid['columns'][$field_name]['editable']['rules'] ?? []; + + if(!$rules){ + return true; + } + + foreach ($rules as $rule) { + + if (!$rule) { continue; } + + $validate_function = "validate_{$rule[0]}"; + + $rule[] = $value; + + unset($rule[0]); + + $result = call_user_func_array([$this->controller, $validate_function], $rule); + + // ошибка уже найдена + if ($result !== true) { + return $result; + } + } + + return true; + } + + /** + * Подготоваливает видимые колонки + */ + private function getVisibleColumns() { + + if ($this->visible_columns === null) { + + foreach ($this->grid['columns'] as $name => $column) { + + $is_disabled = false; + + if (!empty($column['disable'])) { + $is_disabled = true; + } + if (array_key_exists($name, $this->visible_columns_names)) { + $is_disabled = !$this->visible_columns_names[$name]; + } + if(empty($column['switchable'])){ + $is_disabled = false; + } + if ($is_disabled) { + continue; + } + + $this->visible_columns[$name] = $column; + } + } + + return $this->visible_columns; + } + + /** + * Отключаемые колонки + * + * @return array + */ + public function getSwitchableColumns() { + + if ($this->switchable_columns === null) { + + $columns = []; + + foreach ($this->grid['columns'] as $key => $item) { + if (!empty($item['switchable'])) { + $columns[$key] = $item['title']; + } + } + + $this->switchable_columns = $columns ?: false; + } + + return $this->switchable_columns; + } + + /** + * Отключает колонку для вывода + * + * @param string $name Имя колонки + * @return void + */ + public function disableColumn($name) { + $this->visible_columns_names[$name] = false; + } + + /** + * Включает колонку для вывода + * + * @param string $name Имя колонки + * @return void + */ + public function enableColumn($name) { + $this->visible_columns_names[$name] = true; + } + + /** + * Устанавливает параметры выборки из БД по умолчанию + * + * @return void + */ + private function setDefaultFilter() { + + $this->grid['filter'] = [ + 'page' => 1, + 'columns' => [], + 'advanced_filter' => '', + 'perpage' => $this->grid['options']['perpage'] + ]; + + if ($this->grid['options']['order_by']) { + $this->grid['filter']['order_by'] = $this->grid['options']['order_by']; + } + + if ($this->grid['options']['order_to']) { + $this->grid['filter']['order_to'] = $this->grid['options']['order_to']; + } + } + + /** + * Добавляет данные в фильтр + * + * @param array $filter + * @return void + */ + public function addToFilter($filter) { + $this->grid['filter'] = array_replace_recursive($this->grid['filter'], $filter); + } + + /** + * Применяет фильтр к модели выборки + * + * @param cmsModel $model Объект модели, где выбираем записи + * @param array $filter Массив фильтрации + * @return cmsModel + */ + public function applyGridFilter(cmsModel $model, $filter) { + + // применяем сортировку + if (!empty($filter['order_by']) && !empty($filter['order_to'])) { + + // Есть ли вообще такой столбец + if(empty($this->grid['columns'][$filter['order_by']])){ + $filter['order_by'] = $this->grid['options']['order_by']; + } + + $order_by = $filter['order_by']; + + // Есть отдельный столбец для сортировки + if (!empty($this->grid['columns'][$order_by]['order_by'])) { + $order_by = $this->grid['columns'][$order_by]['order_by']; + } + + $model->orderBy($order_by, $filter['order_to']); + } + + // устанавливаем страницу + if (!empty($filter['page'])) { + + $filter['perpage'] = !empty($filter['perpage']) ? (int) $filter['perpage'] : 30; + $filter['page'] = (int) ($filter['page'] <= 0 ? 1 : $filter['page']); + + $model->limitPage($filter['page'], $filter['perpage']); + } + + // + // проходим по каждой колонке таблицы + // и проверяем не передан ли фильтр для нее + // + foreach ($this->getVisibleColumns() as $field => $column) { + + if (empty($column['filter']) || + $column['filter'] === 'none' || + !array_key_exists($field, $filter) || + is_empty_value($filter[$field])) { + continue; + } + + if (!empty($column['filter_by'])) { + $filter_field = $column['filter_by']; + } else { + $filter_field = $field; + } + + switch ($column['filter']) { + case 'range_date': + if (isset($filter[$field]['from']) && !is_empty_value($filter[$field]['from'])) { + $date_from = date('Y-m-d', strtotime($filter[$field]['from'])); + $model->filterGtEqual($filter_field, $date_from); + } + if (isset($filter[$field]['to']) && !is_empty_value($filter[$field]['to'])) { + $date_to = date('Y-m-d', strtotime($filter[$field]['to'])); + $model->filterLtEqual($filter_field, $date_to); + } + case 'range': + if (isset($filter[$field]['from']) && !is_empty_value($filter[$field]['from'])) { + $model->filterGtEqual($filter_field, $filter[$field]['from']); + } + if (isset($filter[$field]['to']) && !is_empty_value($filter[$field]['to'])) { + $model->filterLtEqual($filter_field, $filter[$field]['to']); + } + break; + case 'zero': + if($filter[$field]) { + $model->filterEqual($filter_field, 0); + } + case 'nn': + if($filter[$field]) { + $model->filterNotNull($filter_field); + } + break; + case 'ni': + if($filter[$field]) { + $model->filterIsNull($filter_field); + } + break; + case 'in': $model->filterIn($filter_field, !is_array($filter[$field]) ? explode(',', $filter[$field]) : $filter[$field]); + break; + case 'filled': ($filter[$field] ? $model->filterNotNull($filter_field) : $model->filterIsNull($filter_field)); + break; + case 'exact': $model->filterEqual($filter_field, $filter[$field]); + break; + case 'ip': $model->filterEqual($filter_field, string_iptobin($filter[$field]), true); + break; + case 'like': $model->filterLike($filter_field, "%{$filter[$field]}%"); + break; + case 'date': + $date = date('Y-m-d', strtotime($filter[$field])); + $model->filterLike($filter_field, "%{$date}%"); + break; + } + } + + // Запоминаем + $this->grid['filter'] = array_merge($this->grid['filter'], $filter); + + // Дополнительный фильтр + if (!empty($filter['advanced_filter']) && is_string($filter['advanced_filter'])) { + + parse_str($filter['advanced_filter'], $dataset_filters); + + $model->applyDatasetFilters($dataset_filters); + } + + return $model; + } + + /** + * Собирает все данные таблицы + * + * @param array|false $dataset Данные из базы + * @param integer $total Сколько всего записей + * @return array + */ + public function makeGridRows($dataset = false, $total = 0) { + + $rows = []; + + if(is_array($dataset)){ + foreach($dataset as $row){ + $rows[] = [ + 'columns' => $this->makeRowColumns($row), + 'id' => $row['id'], + 'selected' => false, + 'edited' => false + ]; + } + } + + return [ + 'dragging' => -1, + 'is_loading' => false, + 'need_load' => $dataset === false, + 'source_url' => $this->grid['source_url'] !== '' ? $this->grid['source_url'] : cmsCore::getInstance()->uri_absolute, + 'options' => $this->grid['options'], + 'filter' => $this->grid['filter'], + 'rows' => $rows, + 'total' => $total ? $total : count(($dataset ?: [])), + 'switchable' => [ + 'title' => LANG_GRID_COLYMNS_SETTINGS, + 'columns' => $this->getSwitchableColumns() + ], + 'columns' => $this->makeColumns() + ]; + } + + /** + * Собирает строку таблицы + * + * @param array $row + * @return array + */ + private function makeRowColumns($row) { + + $columns = []; + + $is_set_dragged_class = false; + + foreach ($this->getVisibleColumns() as $field => $column) { + + if (isset($column['key_alias'])){ + $field = $column['key_alias']; + } + + $class = []; + + if (!empty($column['class'])) { + $class[] = $column['class']; + } + + if ($field === 'id') { + if (!$this->grid['options']['show_id']) { + + $class[] = 'd-none'; + } else { + + $class[] = 'dragged_handle'; + + $is_set_dragged_class = true; + } + } else if (!$is_set_dragged_class) { + + $class[] = 'dragged_handle'; + + $is_set_dragged_class = true; + } + + $row_column = [ + 'row_id' => $row['id'], + 'tooltip' => $column['tooltip'] ?? '', + 'name' => $field, + 'value' => '', + 'class' => implode(' ', $class), + 'editable' => $this->getEditableParams($row, $column, $field), + 'href' => false, + 'renderer' => 'basic' // basic, flag, html, actions + ]; + + // Это скорее чтобы не было ошибки при рендере + if (!array_key_exists($field, $row)) { + + $columns[] = $row_column; + + continue; + } + + // тултип колонки + if (isset($column['tooltip_handler'])) { + $row_column['tooltip'] = $column['tooltip_handler']($row); + } + + // null - значит будет пустая строка + $row_column['value'] = $row[$field] ?? ''; + + if (isset($column['href_handler'])) { + $is_active_href = $column['href_handler']($row); + } else { + $is_active_href = true; + } + + // если из значения нужно сделать ссылку, то парсим шаблон + // адреса, заменяя значения полей + if (isset($column['href'])) { + if ($is_active_href) { + $row_column['href'] = string_replace_keys_values_extended($column['href'], $row); + } + } + + // Тип флаг + if (!empty($column['flag'])) { + + if (isset($column['flag_handler'])) { + + $row_column['value'] = $column['flag_handler']($row_column['value'], $row); + } + + // Есть предустановленное значение для "включенности" флага + if (isset($column['flag_on'])) { + + $row_column['value'] = $row_column['value'] == $column['flag_on'] ? 1 : 0; + } else { + + $row_column['value'] = (int) $row_column['value']; + } + + // URL для смены состояния флага + $flag_toggle_url = $column['flag_toggle'] ?? false; + if ($flag_toggle_url) { + $flag_toggle_url = string_replace_keys_values($flag_toggle_url, $row); + } + + $row_column['flag_class'] = $column['flag'] === true ? 'flag' : $column['flag']; + $row_column['href'] = $is_active_href ? $flag_toggle_url : false; + $row_column['confirm'] = $column['flag_confirm'] ?? false; + $row_column['renderer'] = 'flag'; + + $columns[] = $row_column; + + continue; + } + + // Есть функция обработчик, предполагаем, что вернёт готовый HTML + if (isset($column['handler'])) { + + $row_column['renderer'] = 'html'; + $row_column['value'] = $column['handler']($row_column['value'], $row); + + $columns[] = $row_column; + + continue; + } + + // Массивы отдаём на откуп разработчикам + if (is_array($row_column['value'])) { + + if (isset($column['renderer'])) { + + // Можно в колонке указать компонент отрисовки (vue) колонки + $row_column['renderer'] = $column['renderer']; + + } else { + $row_column['value'] = '!error grid value!'; + } + } + + $columns[] = $row_column; + } + + // если есть колонка действий, то формируем набор ссылок + if ($this->grid['actions']) { + + $row_column = [ + 'row_id' => $row['id'], + 'value' => [], + 'editable' => false, + 'class' => false, + 'href' => false, + 'renderer' => 'actions' + ]; + + foreach($this->grid['actions'] as $action){ + + if (isset($action['handler'])) { + + $is_active = $action['handler']($row); + + unset($action['handler']); + } else { + $is_active = true; + } + + if (!$is_active) { + continue; + } + + // парсим шаблон адреса, заменяя значения полей + if (isset($action['href'])){ + $action['href'] = string_replace_keys_values_extended($action['href'], $row); + } + + // парсим шаблон запроса подтверждения, заменяя значения полей + if (isset($action['confirm'])) { + + $action['confirm'] = string_replace_keys_values_extended($action['confirm'], $row); + } + + // все действия с подтверждением снабжаем csrf_token + if (isset($action['confirm']) && !empty($action['href'])) { + + $action['href'] .= (strpos($action['href'], '?') !== false ? '&' : '?') . 'csrf_token=' . cmsForm::getCSRFToken(); + } + + if (!empty($action['icon'])) { + + $icon_params = explode(':', $action['icon']); + + if (!isset($icon_params[1])) { + array_unshift($icon_params, 'solid'); + } + + $action['icon'] = html_svg_icon($icon_params[0], $icon_params[1], 16, false); + } + + $row_column['value'][] = $action; + } + + $columns[] = $row_column; + } + + return $columns; + } + + /** + * Собирает заголовки таблицы + * + * @return array + */ + private function makeColumns() { + + $columns = []; + + foreach ($this->getVisibleColumns() as $name => $column) { + + $column = array_merge($this->default_column, $column); + + $class = []; + + if (!empty($column['class'])) { + $class[] = $column['class']; + } + + if ($name === 'id' && !$this->grid['options']['show_id']) { + $class[] = 'd-none'; + } + + $filter = false; + + if($column['filter'] && $column['filter'] !== 'none'){ + + $filter = [ + 'component' => $this->filter_component_map[$column['filter']], + 'params' => [ + 'attributes' => array_merge($column['filter_attributes'], [ + 'name' => $name + ]) + ] + ]; + + switch ($filter['component']) { + case 'form-date-range': + case 'form-range': + $filter['params']['lang_from'] = LANG_FROM; + $filter['params']['lang_to'] = LANG_TO; + break; + case 'form-input': + $filter['params']['attributes']['type'] = 'search'; + break; + case 'form-checkbox': + $filter['params']['title'] = $column['filter_checkbox'] ?? false; + break; + case 'form-multiselect': + case 'form-select': + $filter['params']['items'] = is_array($column['filter_select']['items']) ? $column['filter_select']['items'] : $column['filter_select']['items']($name); + if(!$filter['params']['items']){ + $filter['component'] = 'form-input'; + } + break; + } + } + + $columns[] = [ + 'width' => $column['width'] ?? '', + 'title' => $column['title'] ?? '', + 'name' => $name, + 'filter' => $filter, + 'class' => implode(' ', $class), + 'sortable' => $this->grid['options']['is_sortable'] && $column['sortable'], + ]; + } + + if ($this->grid['actions']) { + + $filter = [ + 'component' => 'form-filter', + 'params' => [ + 'href' => $this->grid['options']['advanced_filter'], + 'lang_filter' => LANG_FILTER, + 'lang_cancel' => LANG_CANCEL, + 'icon_filter' => html_svg_icon('solid', 'search-plus', 16, false), + 'icon_cancel' => html_svg_icon('solid', 'search-minus', 16, false) + ] + ]; + + $columns[] = [ + 'sortable' => false, + 'width' => count($this->grid['actions']) * 30, + 'title' => LANG_CP_ACTIONS, + 'class' => 'text-right align-middle', + 'name' => 'advanced_filter', + 'filter' => $this->grid['options']['advanced_filter'] ? $filter : false + ]; + } + + return $columns; + } + + private function getEditableParams($row, $column, $field) { + + if (!array_key_exists('editable', $column) || empty($row['id'])) { + return false; + } + + $save_action_query = [ + 'csrf_token' => cmsForm::getCSRFToken(), + 'name' => $field, + 'id' => $row['id'] + ]; + + // Экшен списка записей должен реализовывать и сохранение поля столбца + $save_action = $this->grid['source_url']; + + // @deprecated Передача таблицы устарела + if (!empty($column['editable']['table'])) { + $save_action = href_to('admin', 'inline_save', [urlencode($column['editable']['table']), $row['id']]); + } + + if (!empty($column['editable']['save_action'])) { + $save_action = string_replace_keys_values_extended($column['editable']['save_action'], $row); + } + + if(!isset($save_action)){ + return false; + } + + $attributes = ['autocomplete' => 'off']; + + if (!empty($column['editable']['attributes'])) { + foreach ($column['editable']['attributes'] as $akey => $avalue) { + if (is_string($avalue)) { + $attributes[$akey] = string_replace_keys_values_extended($avalue, $row); + } else { + $attributes[$akey] = $avalue; + } + } + } + + return [ + 'component' => $column['editable']['renderer'] ?? 'form-input', + 'edit_icon' => html_svg_icon('solid', 'pen', 16, false), + 'value' => $row[$field] ?? '', + 'attributes' => $attributes, + 'lang_edit' => LANG_EDIT, + 'lang_save' => LANG_SAVE, + 'save_action' => $save_action . '?' . http_build_query($save_action_query) + ]; + } + +} diff --git a/system/core/model.php b/system/core/model.php index b27d29c5f..10cfc0f7c 100755 --- a/system/core/model.php +++ b/system/core/model.php @@ -2143,86 +2143,47 @@ public function getNextOrdering($table){ /** * Пересчитывает порядковые номера в таблице - * @param string $table_name - * @param string $where - * @return bool + * + * @param string $table_name Таблица БД + * @return boolean */ - public function reorder($table_name){ - - $sql = "SELECT i.id as id, i.ordering as ordering - FROM {#}{$table_name} i - "; - - if ($this->where){ $sql .= 'WHERE '.$this->where.PHP_EOL; } - - $sql .= 'ORDER BY ordering'; - - $result = $this->db->query($sql); - - $this->resetFilters(); - - if (!$this->db->numRows($result)){ - $this->db->freeResult($result); - return false; - } + public function reorder($table_name) { - $ordering = 0; - - while($item = $this->db->fetchAssoc($result)){ - - $ordering += 1; - $this->db->query("UPDATE {#}{$table_name} SET ordering = {$ordering} WHERE id = '{$item['id']}'"); - - } - - $this->db->freeResult($result); - - return true; + $list = $this->limit(false)-> + orderBy('ordering', 'asc')->selectOnly('id')-> + get($table_name, function ($item, $model) { + return $item['id']; + }, false) ?: []; + return $this->reorderByList($table_name, $list); } /** * Расставляет порядковые номера для списка из ID записей - * @param string $table_name - * @param string $list + * + * @param string $table_name Таблица БД + * @param array $list Массив id записей в нужном порядке * @param array $additional_fields Список дополнительных полей и их значений, которые нужно обновлять вместе с ordering - * @return bool + * @return boolean */ - public function reorderByList($table_name, $list, $additional_fields=false){ + public function reorderByList($table_name, $list, $additional_fields = []) { $ordering = 0; - $additional_set = array(); - - if (is_array($additional_fields)){ - foreach($additional_fields as $field=>$value){ - $value = $this->db->escape($value); - $additional_set[] = "{$field} = '{$value}'"; - } - } + $update_data = []; - if ($additional_set){ - $additional_set = ', ' . implode(', ', $additional_set); - } else { - $additional_set = ''; - } + foreach ($list as $id) { - foreach($list as $id){ + if (is_array($id) || !is_numeric($id)) { + continue; + } $ordering += 1; - $id = $this->db->escape($id); - - $query = "UPDATE {#}{$table_name} - SET ordering = '{$ordering}' {$additional_set} - WHERE id = '{$id}'"; - - $this->db->query($query); - + $this->update($table_name, $id, array_merge($additional_fields, ['ordering' => $ordering])); } - return true; - + return $ordering > 0 ? true : false; } //============================================================================// @@ -2231,62 +2192,14 @@ public function reorderByList($table_name, $list, $additional_fields=false){ /** * Применяет к модели фильтры, переданные из просмотра * таблицы со списком записей - * @param array $grid + * + * @param cmsGrid $grid Объект грида * @param array $filter - * @return boolean + * @return $this */ - public function applyGridFilter($grid, $filter) { + public function applyGridFilter(cmsGrid $grid, $filter) { - // применяем сортировку - if (!empty($filter['order_by'])) { - if (!empty($grid['columns'][$filter['order_by']]['order_by'])) { - $filter['order_by'] = $grid['columns'][$filter['order_by']]['order_by']; - } - $this->orderBy($filter['order_by'], $filter['order_to']); - } - - // устанавливаем страницу - if (!empty($filter['page'])) { - $perpage = !empty($filter['perpage']) ? (int) $filter['perpage'] : $this->perpage; - $this->limitPage((int) $filter['page'], $perpage); - } - - // - // проходим по каждой колонке таблицы - // и проверяем не передан ли фильтр для нее - // - foreach ($grid['columns'] as $field => $column) { - if (!empty($column['filter']) && $column['filter'] !== 'none' && isset($filter[$field])) { - - if (!is_empty_value($filter[$field])) { - - if (!empty($column['filter_by'])) { - $filter_field = $column['filter_by']; - } else { - $filter_field = $field; - } - - switch ($column['filter']) { - case 'nn': $this->filterNotNull($filter_field); - break; - case 'ni': $this->filterIsNull($filter_field); - break; - case 'in': $this->filterIn($filter_field, explode(',', $filter[$field])); - break; - case 'filled': ($filter[$field] ? $this->filterNotNull($filter_field) : $this->filterIsNull($filter_field)); - break; - case 'exact': $this->filterEqual($filter_field, $filter[$field]); - break; - case 'like': $this->filterLike($filter_field, "%{$filter[$field]}%"); - break; - case 'date': - $date = date('Y-m-d', strtotime($filter[$field])); - $this->filterLike($filter_field, "%{$date}%"); - break; - } - } - } - } + $grid->applyGridFilter($this, $filter); return $this; } diff --git a/system/core/template.php b/system/core/template.php index 367728fde..c87373066 100755 --- a/system/core/template.php +++ b/system/core/template.php @@ -2186,7 +2186,7 @@ public function renderJSON($data, $with_header = false) { header('Content-type: application/json; charset=utf-8'); } - $json = json_encode($data); + $json = json_encode($data, JSON_UNESCAPED_UNICODE); if ($json === false) { $json = json_encode([ @@ -2448,252 +2448,33 @@ public function renderForm($form, $data, $attributes = [], $errors = false) { /** * Печатает шаблон Grid таблицы + * И загружает данные по ajax * - * @param string $source_url URL ajax запроса списка данных - * @param array $grid Данные Grid таблицы + * @param string|false $source_url URL ajax запроса списка данных + * @param cmsGrid $grid Данные Grid таблицы */ - public function renderGrid($source_url, $grid) { + public function renderGrid($source_url, cmsGrid $grid) { - $this->addTplJSName('datagrid'); - - if ($grid['options']['is_pagination']) { - $this->addTplJSName('datagrid-pagination'); - } - - if ($grid['options']['is_draggable']) { - $this->addTplJSName('datagrid-drag'); - } + $grid->source_url = $source_url; - $grid['source_url'] = $source_url; - - $this->renderAsset('ui/grid-data', $grid); - } - - public function renderGridRowsJSON($grid, $dataset, $total = 1, $pages_count = 1) { - echo json_encode($this->getGridRows($grid, $dataset, $total, $pages_count)); + $this->renderAsset('ui/grid-data', [ + 'grid' => $grid, + 'rows' => $grid->makeGridRows() // без данных + ]); } - public function getGridRows($grid, $dataset, $total = 1, $pages_count = 1) { - - $rows = $titles = $classes = []; - $row_index = 0; - - // - // проходим по всем строкам из набора данных - // - if ($total && $dataset){ - foreach($dataset as $row){ - - $cell_index = 0; - $editable_index = 1; - $editable_count = count(array_filter($grid['columns'], function($element) { return isset($element['editable']); })); - - // вычисляем содержимое для каждой колонки таблицы - foreach($grid['columns'] as $field => $column){ - - $titles[$cell_index] = isset($column['title']) ? $column['title'] : ''; - $classes[$cell_index] = isset($column['class']) ? $column['class'] : ''; - - if (isset($column['key_alias'])){ - $field = $column['key_alias']; - } - - if(isset($row[$field])){ - if (!is_array($row[$field]) && !isset($column['handler'])){ - $value = html($row[$field], false); - } else { - $value = $row[$field]; - } - if ($value === null) { $value = ''; } - } else { - $value = ''; - } - - if (isset($column['flag']) && $column['flag']){ - - if (isset($column['flag_handler'])){ - $value = $column['flag_handler']($value, $row); - } - - if (isset($column['flag_on'])){ - $is_flag_on = $value == $column['flag_on']; - } else { - $is_flag_on = (int)$value; - } - - $flag_class = $column['flag']===true ? 'flag' : $column['flag']; - - $flag_toggle_url = isset($column['flag_toggle']) ? $column['flag_toggle'] : false; - - if ($flag_toggle_url){ - $flag_toggle_url = string_replace_keys_values($flag_toggle_url, $row); - } - - $flag_content = $flag_toggle_url ? '' : ''; - - $value = '
'.$flag_content.'
'; - - } - - if (isset($column['handler'])){ - $value = $column['handler']($value, $row); - } - - // если из значения нужно сделать ссылку, то парсим шаблон - // адреса, заменяя значения полей - if (isset($column['href'])){ - if (isset($column['href_handler'])){ - $is_active = $column['href_handler']($row); - } else { - $is_active = true; - } - if($is_active){ - $column['href'] = string_replace_keys_values_extended($column['href'], $row); - $value = ''.$value.''; - } - } - - if (isset($column['editable'])) { - - if (!empty($row['id']) && !empty($column['editable']['table'])) { - $save_action = href_to('admin', 'inline_save', [urlencode($column['editable']['table']), $row['id']]); - } - - if (!empty($column['editable']['save_action'])) { - $save_action = string_replace_keys_values_extended($column['editable']['save_action'], $row); - } - - $attributes = ['autocomplete' => 'off']; - - if (!empty($column['editable']['attributes'])) { - foreach ($column['editable']['attributes'] as $akey => $avalue) { - if (is_string($avalue)) { - $attributes[$akey] = string_replace_keys_values_extended($avalue, $row); - } else { - $attributes[$akey] = $avalue; - } - } - } - if (!empty($save_action)) { - - $save_action .='?csrf_token='.cmsForm::getCSRFToken(); - - $value = '
' . $value . '
'; - $value .= '
' . html_input('text', $field, $row[$field], $attributes); - if ($editable_index == $editable_count) { - $value .= html_button(LANG_SAVE, '', '', ['data-action' => $save_action, 'class' => 'inline_submit btn-primary']); - } - $value .= '
'; - - $editable_index++; - } - } - - $rows[$row_index][] = $value; - - $cell_index++; - } - - // если есть колонка действий, то формируем набор ссылок - // для текущей строки - if ($grid['actions']){ - - $titles[$cell_index] = LANG_CP_ACTIONS; - $classes[$cell_index] = ''; - - $actions_html = '
'; - - foreach($grid['actions'] as $action){ - - $confirm_attr = ''; - - if (isset($action['handler'])){ - $is_active = $action['handler']($row); - } else { - $is_active = true; - } - - if ($is_active){ - - // парсим шаблон адреса, заменяя значения полей - if (isset($action['href'])){ - $action['href'] = string_replace_keys_values_extended($action['href'], $row); - } - - // парсим шаблон запроса подтверждения, заменяя значения полей - if (isset($action['confirm'])){ - $action['confirm'] = string_replace_keys_values_extended($action['confirm'], $row); - $confirm_attr = 'onclick="if(!confirm(\''.html($action['confirm'], false).'\')){ return false; }"'; - } - - // все действия с подтверждением снабжаем csrf_token - if ($confirm_attr && !empty($action['href'])){ - $action['href'] .= (strpos($action['href'], '?') !== false ? '&' : '?').'csrf_token='.cmsForm::getCSRFToken(); - } - - $actions_html .= ''; - - } - - } - - $actions_html .= '
'; - - $rows[$row_index][] = $actions_html; - - $cell_index++; - - } - - $row_index++; - } - } - - $columns = array(); - if($grid['options']['load_columns']){ - $clear_filter = ''; - foreach($grid['columns'] as $name=>$column){ - if(!empty($column['filter']) && $column['filter'] !== 'none'){ - $filter_attributes = !empty($column['filter_attributes']) ? $column['filter_attributes'] : array(); - if(strpos($name, 'date_') === 0){ - $filter = html_datepicker('filter_'.$name, (isset($grid['filter'][$name]) ? $grid['filter'][$name] : ''), array_merge($filter_attributes, array('id'=>'filter_'.$name, 'rel'=>$name, 'class' => 'input form-control-sm')), array('minDate'=>date(cmsConfig::get('date_format'), 86400))).$clear_filter; - } - elseif(!empty($column['filter_select'])){ - $filter = html_select('filter_'.$name, (is_array($column['filter_select']['items']) ? $column['filter_select']['items'] : $column['filter_select']['items']($name)), (isset($grid['filter'][$name]) ? $grid['filter'][$name] : ''), array_merge($filter_attributes, array('id'=>'filter_'.$name, 'rel'=>$name, 'class'=>'custom-select custom-select-sm'))); - } else { - $filter = html_input('text', 'filter_'.$name, (isset($grid['filter'][$name]) ? $grid['filter'][$name] : ''), array_merge($filter_attributes, array('id'=>'filter_'.$name, 'rel'=>$name, 'class' => 'form-control-sm'))).$clear_filter; - } - } else { - $filter = ''; - } - $columns[] = array( - 'sortable' => $grid['options']['is_sortable'], - 'width' => isset($column['width']) ? $column['width'] : '', - 'title' => isset($column['title']) ? $column['title'] : '', - 'name' => $name, - 'filter' => $filter, - 'order_to' => !empty($grid['filter']['order_by']) && $grid['filter']['order_by'] === $name && !empty($grid['filter']['order_to']) ? $grid['filter']['order_to'] : '' - ); - } - if($grid['actions']){ - $columns[] = array( - 'sortable' => false, - 'width' => count($grid['actions']) * 30, - 'title' => LANG_CP_ACTIONS, - 'name' => 'dg_actions', - 'filter' => '' - ); - } - } + /** + * Печатает JSON сформированные данные грида + * + * @param cmsGrid $grid Объект грида + * @param array $dataset Данные из таблицы БД + * @param integer $total Сколько всего записей + * @param integer $pages_count @deprecated + * @return void + */ + public function renderGridRowsJSON(cmsGrid $grid, $dataset, $total = 0, $pages_count = 1) { - return [ - 'classes' => $classes, - 'titles' => $titles, - 'rows' => $rows, - 'pages_count' => $pages_count, - 'total' => $total, - 'columns' => $columns - ]; + $this->renderJSON($grid->makeGridRows(($dataset ?: []), $total)); } /** diff --git a/system/fields/age.php b/system/fields/age.php index 9e46d9a2c..60abc0244 100755 --- a/system/fields/age.php +++ b/system/fields/age.php @@ -5,6 +5,7 @@ class fieldAge extends cmsFormField { public $title = LANG_PARSER_AGE; public $sql = 'datetime NULL DEFAULT NULL'; public $filter_type = 'date'; + public $filter_hint = LANG_PARSER_DATE_FILTER_HINT; public $var_type = 'string'; public function getOptions() { diff --git a/system/languages/en/controllers/admin/admin.php b/system/languages/en/controllers/admin/admin.php index 5e58b5e44..36b995753 100755 --- a/system/languages/en/controllers/admin/admin.php +++ b/system/languages/en/controllers/admin/admin.php @@ -71,7 +71,6 @@ define('LANG_CP_CTYPE_DATASETS', 'Datasets'); define('LANG_CP_CTYPE_FILTERS', 'Filters'); define('LANG_CP_CTYPE_DATASET', 'Dataset'); - define('LANG_CP_GRID_COLYMNS_SETTINGS', 'Columns settings'); define('LANG_CP_GRID_COLYMNS_SYSTEM', 'System'); define('LANG_CP_GRID_COLYMNS_USER', 'User'); define('LANG_CP_GRID_COLYMNS_FILTER', 'Filter'); @@ -81,7 +80,6 @@ define('LANG_CP_GRID_COLYMNS_DATE', 'Date'); define('LANG_CP_GRID_COLYMNS_SELECT', 'Select'); define('LANG_CP_GRID_COLYMNS_FLAG', 'Switch'); - define('LANG_CP_GRID_COLYMNS_RESET', 'Reset'); define('LANG_CP_GRID_COLYMNS_CUT_TEXT', 'First 100 symbols'); define('LANG_CP_GRID_COLYMNS_IMAGES_NMB', 'Number of images'); define('LANG_CP_GRID_COLYMNS_PREVIEW', 'Preview'); @@ -107,7 +105,6 @@ define('LANG_CP_CONTENT_CATS_TITLES', 'Category title or categories tree'); define('LANG_CP_CONTENT_CATS_TITLES_HINT', 'Enter one item per line to create multiple categories
Add a hyphen before the title to make a nested category
Detailed Manual'); define('LANG_CP_CONTENT_CATS_BIND', 'Bind parent category properties'); - define('LANG_CP_SELECT_HINT', 'Click on a row to select or '); define('LANG_CP_BASIC', 'Basic settings'); define('LANG_CP_IS_COLLAPSED', 'Collapsible blocks in the add/edit item form'); define('LANG_CP_PUBLICATION', 'Publication'); diff --git a/system/languages/en/language.php b/system/languages/en/language.php index f094e2a0f..3dbc6b71a 100755 --- a/system/languages/en/language.php +++ b/system/languages/en/language.php @@ -43,7 +43,6 @@ define('LANG_FILTER_IS_NULL', 'not filled'); define('LANG_FILTER_APPLY', 'Apply'); define('LANG_FILTER_URL', 'URL'); - define('LANG_FILTER_SAVE_DIFF_ORDER', 'Save different order'); define('LANG_SORTING_FIELD', 'Sort by field'); define('LANG_SORTING', 'Sort'); define('LANG_SORTING_ADD', 'New rule'); @@ -420,6 +419,9 @@ define('LANG_UPLOAD_ERR_EXTENSION', 'File upload was cancelled'); define('LANG_UPLOAD_ERR_MIME', 'File has wrong format'); + define('LANG_GRID_SELECT_HINT', 'Click on a row to select or '); + define('LANG_GRID_COLYMNS_SETTINGS', 'Displaying columns'); + //MONEY define('LANG_CURRENCY', '$'); diff --git a/system/languages/ru/controllers/admin/admin.php b/system/languages/ru/controllers/admin/admin.php index 904b669d5..e1935c9ed 100755 --- a/system/languages/ru/controllers/admin/admin.php +++ b/system/languages/ru/controllers/admin/admin.php @@ -80,7 +80,6 @@ define('LANG_CP_CTYPE_FILTERS', 'Фильтры'); define('LANG_CP_CTYPE_DATASET', 'Набор'); - define('LANG_CP_GRID_COLYMNS_SETTINGS', 'Настройки столбцов'); define('LANG_CP_GRID_COLYMNS_SYSTEM', 'Системные'); define('LANG_CP_GRID_COLYMNS_USER', 'Пользовательские'); define('LANG_CP_GRID_COLYMNS_FILTER', 'Фильтр'); @@ -90,7 +89,6 @@ define('LANG_CP_GRID_COLYMNS_DATE', 'Дата'); define('LANG_CP_GRID_COLYMNS_SELECT', 'Список'); define('LANG_CP_GRID_COLYMNS_FLAG', 'Переключатель'); - define('LANG_CP_GRID_COLYMNS_RESET', 'Сбросить'); define('LANG_CP_GRID_COLYMNS_CUT_TEXT', 'Первые 100 символов'); define('LANG_CP_GRID_COLYMNS_IMAGES_NMB', 'Кол-во изображений'); define('LANG_CP_GRID_COLYMNS_PREVIEW', 'Превью'); @@ -118,7 +116,6 @@ define('LANG_CP_CONTENT_CATS_TITLES', 'Название категории или дерево категорий'); define('LANG_CP_CONTENT_CATS_TITLES_HINT', 'Для создания сразу нескольких категорий каждая из них должна быть на новой строке.
Дополнительная вложенность задается знаком дефис перед названием категории
Подробная инструкция'); define('LANG_CP_CONTENT_CATS_BIND', 'Привязать все свойства родительской категории'); - define('LANG_CP_SELECT_HINT', 'Кликните на строку, чтобы выделить или '); define('LANG_CP_BASIC', 'Общие настройки'); define('LANG_CP_IS_COLLAPSED', 'Сворачиваемые блоки в форме создания/редактирования записи'); diff --git a/system/languages/ru/language.php b/system/languages/ru/language.php index 47300b510..47a72b237 100755 --- a/system/languages/ru/language.php +++ b/system/languages/ru/language.php @@ -42,7 +42,6 @@ define('LANG_FILTER_IS_NULL', 'не заполнено'); define('LANG_FILTER_APPLY', 'Фильтровать'); define('LANG_FILTER_URL', 'Ссылка'); - define('LANG_FILTER_SAVE_DIFF_ORDER', 'Сохранять различную сортировку'); define('LANG_SORTING_FIELD', 'Сортировка по полю'); define('LANG_SORTING', 'Сортировка'); define('LANG_SORTING_ADD', 'Добавить правило'); @@ -419,6 +418,9 @@ define('LANG_UPLOAD_ERR_EXTENSION', 'Загрузка файла была прервана'); define('LANG_UPLOAD_ERR_MIME', 'Файл имеет неподходящий формат'); + define('LANG_GRID_SELECT_HINT', 'Кликните на строку, чтобы выделить или '); + define('LANG_GRID_COLYMNS_SETTINGS', 'Отображение столбцов'); + //MONEY define('LANG_CURRENCY', 'руб.'); diff --git a/system/libs/spyc.class.php b/system/libs/spyc.class.php index 5426a6d04..7970aa48b 100755 --- a/system/libs/spyc.class.php +++ b/system/libs/spyc.class.php @@ -236,7 +236,7 @@ private function _yamlize($key, $value, $indent, $previous_key = -1, $first_key $indent += $this->_dumpIndent; // Yamlize the array $string .= $this->_yamlizeArray($value, $indent); - } elseif (!is_array($value)) { + } else { // It doesn't have children. Yip. $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); } diff --git a/system/traits/controllers/actions/listgrid.php b/system/traits/controllers/actions/listgrid.php index e0a8479d7..c99df4f74 100644 --- a/system/traits/controllers/actions/listgrid.php +++ b/system/traits/controllers/actions/listgrid.php @@ -2,7 +2,7 @@ namespace icms\traits\controllers\actions; -use cmsUser; +use cmsUser, cmsGrid, cmsForm; /** * Трейт для экшена вывода грида @@ -11,6 +11,7 @@ * @property \cmsUser $cms_user * @property \cmsRequest $request * @property \cmsModel $model + * @property \cmsGrid $grid * */ trait listgrid { @@ -53,6 +54,12 @@ trait listgrid { */ protected $tool_buttons = []; + /** + * Имя хука для тулбара + * @var ?string + */ + protected $toolbar_hook = null; + /** * Коллбэк для модели где получается список данных * @var callable @@ -61,10 +68,22 @@ trait listgrid { /** * Коллбэк для полученого списка записей - * @var callable + * @var ?callable */ protected $items_callback = null; + /** + * Коллбэк, передаваемый в метод get модели + * @var ?callable + */ + protected $item_callback = null; + + /** + * Коллбэк для фильтра + * @var callable + */ + protected $filter_callback = null; + /** * Префикс действия, если надо передать управление другому экшену * @var string @@ -75,7 +94,7 @@ trait listgrid { * Ключ UPS * @var string */ - protected $ups_key; + protected $ups_key = ''; /** * Грид @@ -89,7 +108,19 @@ trait listgrid { */ protected $default_perpage = 30; - public function run($do = false){ + /** + * Запускается перед логикой в run + */ + public function prepareRun() {} + + /** + * Основной метод запуска экшена + * + * @param mixed $do + * @param mixed $param_two + * @return string + */ + public function run($do = null, $param_two = null){ // если нужно, передаем управление другому экшену if ($do && !is_numeric($do)) { @@ -98,35 +129,155 @@ public function run($do = false){ return; } + $this->prepareRun(); + $this->setListGridParams(); if ($this->request->isAjax()) { - return $this->getListItems(); + header('X-Frame-Options: DENY'); + + // Если надо сохранить значение из строки + if ($this->request->has('save_row_field')) { + + return $this->cms_template->renderJSON($this->saveRowField($this->request->getAll())); + } + + // Вывод всего списка + return $this->cms_template->renderJSON($this->getListItems()); } return $this->renderListItemsGrid(); } + /** + * Сохраняет значение ячейки строки грида + * + * @param array $field_data + * @return array + */ + public function saveRowField($field_data) { + + if (empty($field_data['csrf_token']) || !cmsForm::validateCSRFToken($field_data['csrf_token'])) { + return ['error' => LANG_ERROR . ' #csrf_token']; + } + + if (!$field_data) { + return ['error' => LANG_ERROR . ' #empty data']; + } + + if (empty($field_data['name']) || !is_string($field_data['name'])) { + + return $this->cms_template->renderJSON([ + 'error' => LANG_ERROR . ' #empty data name' + ]); + } + + if (!array_key_exists('value', $field_data) || is_array($field_data['value'])) { + + return $this->cms_template->renderJSON([ + 'error' => LANG_ERROR . ' #empty data value' + ]); + } + + if (empty($field_data['id']) || !is_numeric($field_data['id'])) { + return ['error' => LANG_ERROR . ' #empty id']; + } + + $i = $this->model->getItemByField($this->table_name, 'id', $field_data['id']); + if (!$i) { + return ['error' => LANG_ERROR . ' #404']; + } + + if (!array_key_exists($field_data['name'], $i)) { + return ['error' => LANG_ERROR . ' #no field']; + } + + $error = $this->grid->validateColumnValue($field_data['name'], $field_data['value']); + + if ($error !== true) { + return ['error' => $error]; + } + + $field_name = $field_data['name']; + + $disable_language_context = $this->grid->getGridValue('columns:' . $field_name . ':editable:language_context'); + + if (!$disable_language_context) { + + // Ищем поле на текущем языке + $field_name = $this->model->getTranslatedFieldName($field_name, $this->table_name); + + // Могло быть не включено в настройках + if (!array_key_exists($field_name, $i)) { + return ['error' => LANG_ERROR . ' #no translated field']; + } + } + + $this->model->update($this->table_name, $i['id'], [ + $field_name => strip_tags($field_data['value']) + ]); + + $this->model->limit(1)->filterEqual('id', $field_data['id']); + + $row_data = $this->getListItems(true); + + if (empty($row_data['rows'][0])) { + return ['error' => LANG_ERROR . ' #no row data']; + } + + return [ + 'error' => false, + 'row' => $row_data['rows'][0] + ]; + } + + /** + * Загружает грид + * + * @return void + */ public function setListGridParams() { - $this->ups_key = 'grid_filter.' . $this->name .'_'. $this->grid_name; + $this->ups_key = 'grid_filter.' . $this->ups_key . $this->name . '_' . $this->grid_name; - $this->grid = $this->loadDataGrid($this->grid_name, $this->grid_args, $this->ups_key); + $this->grid = new cmsGrid($this->controller, $this->grid_name, $this->grid_args); + if (!$this->grid->isLoaded()) { + + return cmsCore::error($this->grid->getError()); + } + + $this->grid->source_url = $this->grid_url ? $this->grid_url : $this->cms_template->href_to($this->current_action, $this->params); } + /** + * Возвращает HTML грида + * + * @return string + */ public function getListItemsGridHtml(){ $this->cms_template->addToolButtons($this->tool_buttons); - return $this->cms_template->getRenderedAsset('ui/grid', [ + if ($this->toolbar_hook) { + + $this->cms_template->applyToolbarHook($this->toolbar_hook); + } + + return $this->cms_template->getRenderedAsset('ui/grid-data', [ 'grid' => $this->grid, - 'page_title' => $this->title, - 'source_url' => $this->grid_url ? $this->grid_url : $this->cms_template->href_to($this->current_action) + 'rows' => $this->getListItems(), + 'page_title' => $this->title ]); } + /** + * Печатает грид и подключает при необходимости + * CSS контроллера контекста вызова + * + * @return string + */ public function renderListItemsGrid(){ $html = $this->getListItemsGridHtml(); @@ -144,16 +295,50 @@ public function renderListItemsGrid(){ return $html; } - public function getListItems(){ + /** + * Возвращает подготовленные данные записей для грида + * + * @param boolean $ignore_field Игнорировать фильтр + * @return type + */ + public function getListItems($ignore_field = false){ - $this->model->setPerPage($this->default_perpage); + if (!$ignore_field) { - $filter = []; - $filter_str = cmsUser::getUPSActual($this->ups_key, $this->request->get('filter', '')); + $this->model->setPerPage($this->default_perpage); - if ($filter_str){ - parse_str($filter_str, $filter); - $this->model->applyGridFilter($this->grid, $filter); + $visible_columns = cmsUser::getUPSActual($this->ups_key.'.visible_columns', $this->request->get('visible_columns', [])); + + if ($visible_columns) { + + $switchable_columns = $this->grid->getSwitchableColumns(); + + if ($switchable_columns) { + foreach ($switchable_columns as $name => $column) { + if (!in_array($name, $visible_columns)) { + $this->grid->disableColumn($name); + } else { + $this->grid->enableColumn($name); + } + } + } + } + + $filter = $this->grid->filter; + $pre_filter = cmsUser::getUPSActual($this->ups_key, $this->request->get('filter', '')); + + if ($pre_filter) { + parse_str($pre_filter, $filter); + } + + if ($filter) { + + if ($this->filter_callback) { + $filter = call_user_func_array($this->filter_callback, [$filter]); + } + + $this->grid->applyGridFilter($this->model, $filter); + } } if($this->list_callback){ @@ -162,17 +347,14 @@ public function getListItems(){ $total = $this->model->getCount($this->table_name); $perpage = isset($filter['perpage']) ? $filter['perpage'] : $this->default_perpage; - $pages = ceil($total / $perpage); - $data = $this->model->get($this->table_name); + $data = $this->model->get($this->table_name, $this->item_callback) ?: []; if($this->items_callback){ $data = call_user_func_array($this->items_callback, [$data]); } - $this->cms_template->renderGridRowsJSON($this->grid, $data, $total, $pages); - - return $this->halt(); + return $this->grid->makeGridRows($data, $total, $perpage); } } diff --git a/templates/admincoreui/controllers/admin/addons_list.tpl.php b/templates/admincoreui/controllers/admin/addons_list.tpl.php index 155c125a9..6c0aa6a75 100755 --- a/templates/admincoreui/controllers/admin/addons_list.tpl.php +++ b/templates/admincoreui/controllers/admin/addons_list.tpl.php @@ -42,7 +42,7 @@
-
-