scope('questions', $this->langAdmin('Questions Management')) ->method('questions') ->scope('categories', $this->langAdmin('Category Management')) ->methods(['categories', 'categories_delete']) ->seoTemplates() ; } public function questions() { if (!$this->haveAccessTo('questions')) { return $this->showAccessDenied(); } $lang = $this->locale->current(); $publicator = $this->initPublicator(); $action = $this->input->postget('act', TYPE_STR); if (! empty($action) || $this->isPOST()) { $response = []; switch ($action) { case 'add': { $submit = $this->input->post('save', TYPE_BOOL); $data = $this->validateQuestionData(0, $submit, $publicator); if ($submit) { if ($this->errors->no('help.admin.question.submit', ['id' => 0, 'data' => &$data, 'publicator' => $publicator])) { $questionID = $this->model->questionSave(0, $data); if ($questionID > 0) { # переносим фотографии в постоянную папку $publicator->dataUpdate($data['content'], $questionID); # link $this->model->questionSave($questionID, [ 'link' => $this->url('view', [ 'id' => $questionID, 'title' => $data['title'][$lang]], true), ]); } } break; } $data['id'] = 0; $data['publicator'] = $publicator; $data['cats'] = $this->model->categoriesOptionsByLevel( $this->model->categoryParentsID($data['cat_id']), ['empty' => $this->langAdmin('Select')] ); $response['form'] = $this->template('admin/questions.form', $data); } break; case 'edit': { $submit = $this->input->post('save', TYPE_BOOL); $questionID = $this->input->postget('id', TYPE_UINT); if (! $questionID) { $this->errors->unknownRecord(); break; } if ($submit) { $data = $this->validateQuestionData($questionID, $submit, $publicator); if ($this->errors->no('help.admin.question.submit', ['id' => $questionID, 'data' => &$data, 'publicator' => $publicator])) { $data['link'] = $this->url('view', [ 'id' => $questionID, 'title' => $data['title'][$lang], ], true); $this->model->questionSave($questionID, $data); } $data['id'] = $questionID; break; } else { $data = $this->model->questionData($questionID); if (empty($data)) { $this->errors->unknownRecord(); break; } } $data['publicator'] = $publicator; $data['cats'] = $this->model->categoriesOptionsByLevel( $this->model->categoryParentsID($data['cat_id']), ['empty' => $this->langAdmin('Select')] ); $response['form'] = $this->template('admin/questions.form', $data); } break; case 'toggle': { $questionID = $this->input->postget('id', TYPE_UINT); if (! $questionID) { $this->errors->unknownRecord(); break; } $toggleType = $this->input->get('type', TYPE_STR); $this->model->questionToggle($questionID, $toggleType); } break; case 'category-data': { $categoryID = $response['id'] = $this->input->post('cat_id', TYPE_UINT); if (empty($categoryID)) { $this->errors->unknownRecord(); break; } $response['subs'] = $this->model->categorySubCount($categoryID); if ($response['subs'] > 0) { $response['cats'] = $this->model->categorySubOptions($categoryID, [ 'sel' => 0, 'empty' => $this->langAdmin('Select'), ]); } } break; case 'rotate': { $tab = $this->input->post('tab', TYPE_INT); switch ($tab) { case 0: { # сортировка в категории $catID = $this->input->post('cat', TYPE_UINT); if ($catID) { $this->model->questionsRotate('num', 'cat_id = ' . $catID); } } break; case 1: { # сортировка "Избранные" $this->model->questionsRotate('fav', 'fav > 0'); } break; } } break; case 'delete': { $questionID = $this->input->postget('id', TYPE_UINT); if (! $questionID) { $this->errors->impossible(); break; } $data = $this->model->questionData($questionID); if (empty($data)) { $this->errors->impossible(); break; } $deleted = $this->model->questionDelete($questionID); if ($deleted) { # удаляем фотографии $publicator->dataDelete($data['content'], $questionID); } else { $this->errors->impossible(); break; } } break; default: $response = false; } if ($response !== false && $this->isAJAX()) { return $this->ajaxResponseForm($response); } } $f = $this->input->postgetm([ 'page' => TYPE_UINT, 'cat' => TYPE_UINT, 'tab' => TYPE_INT, ]); # формируем фильтр списка вопросов $filter = []; $orderBy = 'created DESC'; $perPage = 15; $data['pgn'] = ''; $data['rotate'] = ($f['tab'] == 1 || ($f['cat'] && !$this->model->categorySubCount($f['cat']))); switch ($f['tab']) { case 0: # Все { if ($data['rotate']) { $orderBy = 'num'; } } break; case 1: # Избранные { $perPage = false; $filter[':fav'] = 'fav>0'; $orderBy = 'fav'; } break; } if ($f['cat'] > 0) { $filter[':cat_id'] = ['(Q.cat_id2 = :cat OR Q.cat_id1 = :cat)', ':cat' => $f['cat']]; } if ($perPage !== false) { $count = $this->model->questionsListing($filter, true); $pages = new Pagination($count, $perPage, '#', 'jHelpQuestionsList.page(' . Pagination::PAGE_ID . '); return false;'); $data['pgn'] = $pages->view(['arrows' => false]); $data['list'] = $this->model->questionsListing($filter, false, $pages->getLimitOffset(), $orderBy); } else { $data['list'] = $this->model->questionsListing($filter, false, '', $orderBy); } $data['list'] = $this->template('admin/questions.listing.ajax', $data); if ($this->isAJAX()) { return $this->ajaxResponseForm([ 'list' => $data['list'], 'pgn' => $data['pgn'], ]); } $data['f'] = & $f; $data['id'] = $this->input->get('id', TYPE_UINT); $data['act'] = $action; $data['cats'] = $this->model->categoriesOptions($f['cat'], [$this->langAdmin('All Categories')]); return $this->template('admin/questions.listing', $data); } public function categories() { if (! $this->haveAccessTo('categories')) { return $this->showAccessDenied(); } $action = $this->input->postget('act', TYPE_STR); if (!empty($action) || $this->isPOST()) { $response = []; switch ($action) { case 'add': { $submit = $this->input->post('save', TYPE_BOOL); $data = $this->validateCategoryData(0, $submit); if ($submit) { if ($this->errors->no('help.admin.category.submit', ['id' => 0, 'data' => &$data])) { $this->model->categorySave(0, $data); } break; } $data['id'] = 0; $response['form'] = $this->template('admin/categories.form', $data); } break; case 'edit': { $submit = $this->input->post('save', TYPE_BOOL); $categoryID = $this->input->postget('id', TYPE_UINT); if (!$categoryID) { $this->errors->unknownRecord(); break; } if ($submit) { $dataPrev = $this->model->categoryData($categoryID); $data = $this->validateCategoryData($categoryID, $submit); if ($this->errors->no('help.admin.category.submit', ['id' => $categoryID,'data' => &$data, 'before' => $dataPrev])) { $res = $this->model->categorySave($categoryID, $data); if (!empty($res) && $data['keyword_edit'] != $dataPrev['keyword_edit'] && $dataPrev['subs']) { # если keyword был изменен и есть вложенные подкатегории: # > перестраиваем полный путь подкатегорий $this->model->categoryRebuildSubsKeyword($categoryID, $dataPrev['keyword_edit']); } } $data['id'] = $categoryID; break; } else { $data = $this->model->categoryData($categoryID, true); if (empty($data)) { $this->errors->unknownRecord(); break; } } $data['pid_path'] = $this->model->categoryParentsTitle($categoryID); $response['form'] = $this->template('admin/categories.form', $data); } break; case 'expand': { $categoryID = $this->input->postget('id', TYPE_UINT); if (! $categoryID) { $this->errors->unknownRecord(); break; } $data['list'] = $this->model->categoriesListing(['pid' => $categoryID]); $data['skip_norecords'] = false; $response['list'] = $this->template('admin/categories.listing.ajax', $data); $response['cnt'] = sizeof($data['list']); } break; case 'toggle': { $categoryID = $this->input->postget('id', TYPE_UINT); if (!$categoryID) { $this->errors->unknownRecord(); break; } $sToggleType = $this->input->get('type', TYPE_STR); $this->model->categoryToggle($categoryID, $sToggleType); } break; case 'rotate': { $this->model->categoriesRotate(); } break; case 'dev-delete-all': { if (! $this->isAdminFordev()) { return $this->showAccessDenied(); } $this->model->categoriesDeleteAll(); return $this->adminRedirect(Errors::SUCCESS, 'categories'); } case 'dev-treevalidate': { # валидация целостности NestedSets категорий if (! $this->isAdminFordev()) { return $this->showAccessDenied(); } return $this->model->treeCategories()->validate(true); } default: $response = false; } if ($response !== false && $this->isAJAX()) { return $this->ajaxResponseForm($response); } } $f = []; # формируем фильтр списка категорий $sql = []; $orderBy = 'numleft'; $data['pgn'] = ''; $expandState = $this->input->cookie($this->app->cookieKey('help_categories_expand')); $expandID = (!empty($expandState) ? explode('.', $expandState) : []); $expandID = array_map('intval', $expandID); $expandID[] = $this->model->categoryRootID(); $sql[] = 'pid IN (' . join(',', $expandID) . ')'; $data['list'] = $this->model->categoriesListing($sql, false, '', $orderBy); $data['list'] = $this->template('admin/categories.listing.ajax', $data); if ($this->isAJAX()) { return $this->ajaxResponseForm([ 'list' => $data['list'], 'pgn' => $data['pgn'], ]); } $data['f'] = $f; $data['id'] = $this->input->get('id', TYPE_UINT); $data['act'] = $action; return $this->template('admin/categories.listing', $data); } public function categories_delete() { if (! $this->haveAccessTo('categories')) { return $this->showAccessDenied(); } $categoryID = $this->input->getpost('id', TYPE_UINT); if (! $categoryID) { return $this->adminRedirect(Errors::IMPOSSIBLE, 'categories'); } $data = $this->model->categoryData($categoryID, true); if (! $data) { return $this->adminRedirect(Errors::IMPOSSIBLE, 'categories'); } if ($this->isPOST()) { $nextCategoryID = $this->input->post('next', TYPE_UINT); if ($nextCategoryID > 0) { # проверяем наличие категории $dataNext = $this->model->categoryData($nextCategoryID); if (empty($dataNext) || $nextCategoryID == $categoryID || $dataNext['subs']) { return $this->adminRedirect(Errors::IMPOSSIBLE, 'categories'); } # перемещаем вопросы $moved = $this->model->questionsMoveToCategory($nextCategoryID, $categoryID); if (! empty($moved)) { # удаляем категорию $this->model->categoryDelete($categoryID); } } else { if (! $data['questions']) { # удаляем категорию $this->model->categoryDelete($categoryID); } } return $this->adminRedirect(Errors::SUCCESS, 'categories'); } $data['categories'] = $this->model->categoriesOptions(0, $this->langAdmin('Select'), 2); return $this->template('admin/categories.delete', $data); } /** * Обрабатываем параметры запроса * @param int $questionID ID вопроса или 0 * @param bool $submit выполняем сохранение/редактирование * @param Publicator $publicator или FALSE * @return array параметры */ protected function validateQuestionData(int $questionID, bool $submit, Publicator $publicator) { $data = []; $this->input->postm_lang($this->model->langQuestions, $data); $this->input->postm([ 'cat_id' => TYPE_UINT, # Категория 'content' => TYPE_ARRAY, # Описание 'content_no' => TYPE_BOOL, # Без подробного описания 'enabled' => TYPE_BOOL, # Включен 'mtemplate' => TYPE_BOOL, # Использовать общий шаблон SEO ], $data); if ($submit) { # Категория $categoryID = $data['cat_id']; if (! $categoryID) { $this->errors->set($this->langAdmin('Select Сategory')); } else { # проверяем наличие подкатегорий $subsCnt = $this->model->categorySubCount($categoryID); if ($subsCnt > 0) { $this->errors->set($this->langAdmin('The selected category should not contain subcategories')); } else { # сохраняем ID категорий(parent и текущей), для возможности дальнейшего поиска по ним $parentsID = $this->model->categoryParentsID($categoryID, true); foreach ($parentsID as $lvl => $id) { $data['cat_id' . $lvl] = $id; } } } # Описание if ($this->errors->no()) { $publicatorData = $publicator->dataPrepare($data['content'], $questionID); $data['content'] = $publicatorData['content']; $data['content_search'] = $publicatorData['content_search']; } } else { if (! $questionID) { $data['mtemplate'] = 1; } } return $data; } /** * Обрабатываем параметры запроса * @param int $categoryID ID категории или 0 * @param bool $submit выполняем сохранение/редактирование * @return array параметры */ protected function validateCategoryData(int $categoryID, bool $submit) { $data = []; $this->input->postm_lang($this->model->langCategories, $data); $this->input->postm([ 'pid' => TYPE_UINT, # Основной раздел 'keyword_edit' => TYPE_NOTAGS, # URL-Keyword 'enabled' => TYPE_BOOL, # Включен 'mtemplate' => TYPE_BOOL, # Использовать общий шаблон SEO ], $data); $lang = $this->locale->current(); if ($submit) { do { # URL-Keyword $keyword = $data['keyword_edit']; if (empty($keyword) && !empty($data['title'][$lang])) { $keyword = func::translit($data['title'][$lang]); } $keyword = preg_replace('/[^\p{L}\w0-9_\-]/iu', '', mb_strtolower($keyword)); $keyword = mb_substr(trim($keyword, ' -'), 0, 100); if (empty($keyword)) { $this->errors->set($this->langAdmin('Incorrect Keyword')); break; } # проверяем уникальность keyword'a в пределах основной категории if ($this->model->categoryKeywordExists($keyword, $categoryID, $data['pid'])) { $this->errors->set($this->langAdmin('The specified keyword is already in use. Please choose another')); break; } $data['keyword_edit'] = $keyword; # строим полный путь "parent-keyword / ... / keyword" $keywordsPath = []; if ($data['pid'] > $this->model->categoryRootID()) { $parentCatData = $this->model->categoryData($data['pid']); if (empty($parentCatData)) { $this->errors->set($this->langAdmin('Main category is incorrect')); break; } else { $keywordsPath = explode('/', $parentCatData['keyword']); } } $keywordsPath[] = $keyword; $keywordsPath = join('/', $keywordsPath); $data['keyword'] = $keywordsPath; } while (false); } else { if (! $categoryID) { $data['mtemplate'] = 1; } } return $data; } public function ajax() { $action = $this->input->getpost('act', TYPE_STR); switch ($action) { case 'empty': { // } break; default: { $this->app->hook('help.admin.ajax.default.action', $action, $this); $this->errors->impossible(); } } return $this->ajaxResponseForm(); } }