Query(" SELECT * FROM " . PREFIX . "_module_comments WHERE Id = '" . $this->_config_id . "' ")->FetchAssocArray(); } if ($param == '') return $settings; // В противном случае возвращаем уже имеющиеся значения return (isset($settings[$param]) ? $settings[$param] : null); } /** * Метод, предназначенный для получения количества комментариев для определенного документа. * * @param int $document_id - идентификатор документа * @return int - количество комментариев */ function _commentPostCountGet($document_id) { global $AVE_DB; // Определяем статический массив, который будет хранить количество комментариев для документов на // протяжении всего срока жизни объекта. static $comments = array(); // Если в массиве не найден ключ, который соответствует запрашиваемому документу, тогда выполняем // запрос к БД на получение количества комментариев if (! isset($comments[$document_id])) { $comments[$document_id] = $AVE_DB->Query(" SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . (int)$document_id . "' ")->GetCell(); } // Возвращаем количество комментариев для запрашиваемого документа return $comments[$document_id]; } /** * Внешние методы класса */ /** * Следующие методы описывают работу модуля в Публичной части сайта. */ /** * Метод, предназначенный для получения из БД всех комментариев, относящихся к указанному * документу с последующим выводом в Публичной части. * * @param string $tpl_dir - путь к шаблонам модуля * * @todo Вывод информации о авторе комментария */ function commentListShow($tpl_dir) { global $AVE_DB, $AVE_Template, $AVE_Core; // Используем оператор объединения с null для PHP 8.4 $document_id = (int)($_REQUEST['id'] ?? 0); $artpage = $_REQUEST['artpage'] ?? null; $apage = $_REQUEST['apage'] ?? null; $user_group = UGROUP ?? 0; // Проверяем, что в настройках модуля разрешено комментирование документов if ($this->_commentSettingsGet('comment_active') == 1) { // ================================================================================= // НОВОЕ: ПРОВЕРКА ПРАВ НА ПРОСМОТР КОММЕНТАРИЕВ (Read Permission) // ================================================================================= $read_groups = explode(',', $this->_commentSettingsGet('comment_user_groups_read')); $assign['no_read_permission'] = 0; // Флаг: 0 = права есть // Если группа текущего пользователя НЕ в списке разрешенных для ЧТЕНИЯ, if (!in_array($user_group, $read_groups)) { // Устанавливаем флаг, что прав на чтение нет $assign['no_read_permission'] = 1; } // ================================================================================= $assign['display_comments'] = 1; // Если группа пользователя, который в текущий момент просматривает документ попадает в список // разрешенных (в настройках модуля), тогда создаем флаг, который будет разрешать к показу // форму для добавления нового комментария if (in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups')))) { $assign['cancomment'] = 1; } // ЕСЛИ ЕСТЬ ПРАВА НА ЧТЕНИЕ, ПРОДОЛЖАЕМ ВЫБОРКУ И ВЫВОД if ($assign['no_read_permission'] == 0) { $assign['comment_max_chars'] = $this->_commentSettingsGet('comment_max_chars'); $assign['im'] = $this->_commentSettingsGet('comment_use_antispam'); // Выполняем запрос к БД на получение количества комментариев для текущего документа $comments = array(); if ($this->_commentSettingsGet('comment_use_page_nav') == 1) { $limit = $this->_commentSettingsGet('comment_page_nav_count'); $start = get_current_page() * $limit - $limit; $num = $AVE_DB->Query(" SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' ")->GetCell(); $sql = $AVE_DB->Query(" SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . ($user_group == 1 ? '' : "AND comment_status = '1'") . " ORDER BY comment_published ASC LIMIT " . $start . "," . $limit . " "); $pages = @ceil($num / $limit); if ($num > $limit) { $page_nav = '{t} '; $page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav, get_settings('navi_box')); // *** ПРИМЕНЯЕМ КОСТЫЛИ ИЗ РЕАЛИЗАЦИИ ЗАПРОСОВ ДЛЯ ЧПУ *** // 1. Применяем rewrite_link и очищаем от тройных/двойных слешей $page_nav = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($page_nav))); // 2. Очищаем от URL_SUFF, если он есть (хотя это, возможно, не нужно для комментариев) // (Я опущу эту строку, так как она специфична для главной страницы.) // $page_nav = str_ireplace('"//' . URL_SUFF . '"', '"/"', $page_nav); // 3. Запускаем более общую очистку, если там есть Query (GET-параметры), // что гарантирует удаление двойных слешей, которые могут появиться в пути $page_nav = preg_replace('/(?ceil($num / $limit) ? $GLOBALS['page_id'][$document_id]['page'] : ceil($num / $limit)); } else { $page_nav = ''; } } else { $sql = $AVE_DB->Query(" SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . ($user_group == 1 ? '' : "AND comment_status = '1'") . " ORDER BY comment_published ASC "); $page_nav = ''; } // Получаем формат даты, который указан в общих настройках системы и // приводим дату создания комментария и дату редактирования к этому формату $date_time_format = $AVE_Template->get_config_vars('COMMENT_DATE_TIME_FORMAT'); while ($row = $sql->FetchAssocArray()) { // ----------------------------------------------------- // !!! НАЧАЛО: ВНЕДРЕНИЕ АВАТАРА !!! // ----------------------------------------------------- if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0) { // Вызываем глобальную функцию getAvatar с нужным размером (48px) // и сохраняем результат в поле 'avatar' для Smarty: $row['avatar'] = getAvatar($row['comment_author_id'], 48); } else { // Для гостей (comment_author_id = 0) или неавторизованных: // Передаем пустую строку, чтобы Smarty использовал заглушку. $row['avatar'] = ''; } // ----------------------------------------------------- // !!! КОНЕЦ: ВНЕДРЕНИЕ АВАТАРА !!! // ----------------------------------------------------- $row['comment_published'] = ave_date_format($date_time_format, $row['comment_published']); $row['comment_changed'] = ave_date_format($date_time_format, $row['comment_changed']); $comments[$row['parent_id']][] = $row; } } else { // Если нет прав, то эти переменные остаются пустыми/неопределенными $comments = array(); $page_nav = ''; } // Формируем ряд переменных для использования в шаблоне $assign['closed'] = @$comments[0][0]['comments_close']; $assign['comments'] = $comments; $assign['theme'] = defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER; $assign['doc_id'] = $document_id; $assign['page'] = base64_encode(get_redirect_link()); $assign['subtpl'] = $tpl_dir . $this->_comments_tree_sub_tpl; $AVE_Template->assign($assign); $AVE_Template->assign('page_nav', $page_nav); // Отображаем шаблон $AVE_Template->display($tpl_dir . $this->_comments_tree_tpl); } } /** * Метод, предназначенный для отображения формы при добавлении нового комментария. * * @param string $tpl_dir - путь к шаблонам модуля */ function commentPostFormShow($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $docid = (int)($_REQUEST['docid'] ?? 0); $user_group = UGROUP ?? 0; // Получаем список комментариев на которые запрещены ответы $geschlossen = $AVE_DB->Query(" SELECT comments_close FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $docid . "' LIMIT 1 ")->GetCell(); // Формируем ряд переменных для использования в шаблоне $AVE_Template->assign('closed', $geschlossen); $AVE_Template->assign('cancomment', ($this->_commentSettingsGet('comment_active') == 1 && in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups'))))); $AVE_Template->assign('comment_max_chars', $this->_commentSettingsGet('comment_max_chars')); $AVE_Template->assign('theme', defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER); // Отображаем форму для добавления комментария $AVE_Template->display($tpl_dir . $this->_comment_form_tpl); } /** * Метод, предназначенный для записи в БД нового комментария. * * @param string $tpl_dir - путь к шаблонам модуля * */ function commentPostNew($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $page = $_REQUEST['page'] ?? ''; $ajax = (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == 1); $user_group = UGROUP ?? 0; $secure_code = $_POST['securecode'] ?? ''; $session_captcha = $_SESSION['captcha_keystring'] ?? null; // Если запрос пришел не ajax запросом, тогда формируем ссылку для последующего редиректа if (! $ajax) { $link = rewrite_link(base64_decode($page)); } // Если в настройках модуля включено использование защитного кода, тогда if ($this->_commentSettingsGet('comment_use_antispam') == 1) { // Если введенный пользователем защитный код неверен, тогда выполняем обновление кода if (! (isset($session_captcha) && $session_captcha == $secure_code)) { unset($_SESSION['captcha_keystring']); if ($ajax) { echo 'wrong_securecode'; } else { if(isset($GLOBALS['tmpl']))$GLOBALS['tmpl']->assign("wrongSecureCode", 1); header('Location:' . $link . '#end'); } exit; } unset($_SESSION['captcha_keystring']); } // Определяем флаг модерации комментариев $comment_status = ($this->_commentSettingsGet('comment_need_approve') == 1) ? 0 : 1; // Если комментарии разрешены, тогда получаем все данные, который пользователь указал в форме if ($this->_commentSettingsGet('comment_active') == 1 && !empty($_POST['comment_text']) && !empty($_POST['comment_author_name']) && in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups')))) { // --- !!! НАЧАЛО БЕЗОПАСНОСТИ: Санитаризация и Экранирование !!! --- $new_comment['parent_id'] = (int)($_POST['parent_id'] ?? 0); $new_comment['document_id'] = (int)($_POST['doc_id'] ?? 0); // Экранирование для предотвращения SQLi: // Санитаризация для предотвращения XSS в строковых полях: $new_comment['comment_author_name'] = addslashes(strip_tags($_POST['comment_author_name'] ?? '')); $new_comment['comment_author_id'] = empty($_SESSION['user_id']) ? 0 : (int)$_SESSION['user_id']; $new_comment['comment_author_email'] = addslashes(strip_tags($_POST['comment_author_email'] ?? '')); $new_comment['comment_author_city'] = addslashes(strip_tags($_POST['comment_author_city'] ?? '')); $new_comment['comment_author_website'] = addslashes(strip_tags($_POST['comment_author_website'] ?? '')); $new_comment['comment_author_ip'] = $_SERVER['REMOTE_ADDR']; $new_comment['comment_published'] = time(); $new_comment['comment_status'] = $comment_status; // Текст комментария до очистки $comment_text_raw = $_POST['comment_text'] ?? ''; // Определяем максимальную длину символов для комментария $comment_max_chars = $this->_commentSettingsGet('comment_max_chars'); $comment_max_chars = (!empty($comment_max_chars) && $comment_max_chars > 10) ? $comment_max_chars : 200; // 1. Убираем HTML-теги для предотвращения XSS $comment_text_clean = strip_tags(stripslashes($comment_text_raw)); // 2. Обрезка $comment_text_cut = mb_substr($comment_text_clean, 0, $comment_max_chars); $comment_text_cut .= (mb_strlen($comment_text_clean) > $comment_max_chars) ? '…' : ''; // 3. Экранирование текста перед вставкой в SQL $new_comment['comment_text'] = addslashes($comment_text_cut); // --- !!! КОНЕЦ БЕЗОПАСНОСТИ !!! --- // Выполняем запрос к БД на добавление комментария $AVE_DB->Query(" INSERT INTO " . PREFIX . "_module_comment_info (`" . implode('`,`', array_keys($new_comment)) ."`) VALUES ('" . implode("','", $new_comment) . "') "); $new_comment['Id'] = $AVE_DB->InsertId(); // Получаем e-mail адрес из Общих настроек системы и формируем ссылку на комментарий в Публичной части $mail_from = get_settings('mail_from'); $mail_from_name = get_settings('mail_from_name'); $page_link = get_home_link() . urldecode(base64_decode($page)) . '&subaction=showonly&comment_id=' . $new_comment['Id'] . '#' . $new_comment['Id']; // Формируем текст уведомления для отправки на e-mail $mail_text = $AVE_Template->get_config_vars('COMMENT_MESSAGE_ADMIN'); // Используем stripslashes для очистки текста, который будет отправлен по почте $mail_text = str_replace('%COMMENT%', stripslashes($new_comment['comment_text']), $mail_text); $mail_text = str_replace('%N%', "\n", $mail_text); $mail_text = str_replace('%PAGE%', $page_link, $mail_text); $mail_text = str_replace('&', '&', $mail_text); // Отправляем уведомление send_mail( $mail_from, $mail_text, $AVE_Template->get_config_vars('COMMENT_SUBJECT_MAIL'), $mail_from, $mail_from_name, 'text' ); // Если данные были отправлены ajax-запросом, тогда выполняем автоматический показ комментария // на странице. if ($ajax) { // --------------------------------------------------------------------- // !!! НАЧАЛО: ИСПРАВЛЕНИЕ ДЛЯ AJAX-ОТВЕТА (ПОЛУЧЕНИЕ АВАТАРА) !!! // --------------------------------------------------------------------- if (isset($new_comment['comment_author_id']) && $new_comment['comment_author_id'] > 0) { // Вызываем глобальную функцию getAvatar с нужным размером (48px) $new_comment['avatar'] = getAvatar($new_comment['comment_author_id'], 48); } else { // Для гостей $new_comment['avatar'] = ''; } // --------------------------------------------------------------------- // !!! КОНЕЦ: ИСПРАВЛЕНИЕ ДЛЯ AJAX-ОТВЕТА !!! // ---- $new_comment['comment_changed'] = 0; $new_comment['comment_published'] = ave_date_format($AVE_Template->get_config_vars('COMMENT_DATE_TIME_FORMAT'), $new_comment['comment_published']); $subcomments[] = $new_comment; $AVE_Template->assign('subcomments', $subcomments); $AVE_Template->assign('theme', defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER); $AVE_Template->display($tpl_dir . $this->_comments_tree_sub_tpl); } } // Если же данные пришли НЕ ajax-запросом, тогда полностью обновляем страницу. if (! $ajax) header('Location:' . str_replace("//", "", $link) . '#end'); exit; } /** * Метод, предназначенный для редактирования комментария в Публичной части * * @param int $comment_id - идентификатор комментария */ function commentPostEdit($comment_id) { global $AVE_DB; $user_id = $_SESSION['user_id'] ?? null; $user_group = UGROUP ?? 0; $post_text = $_POST['text'] ?? ''; if (empty($user_id)) exit; $comment_id = intval(preg_replace('/\D/', '', $comment_id)); // Выполняем запрос к БД и получаем всю информацию о комментарии, а также ряд значений из настроек модуля $row = $AVE_DB->Query(" SELECT msg.parent_id, msg.comment_text, cmnt.comment_user_groups, cmnt.comment_max_chars, cmnt.comment_need_approve FROM " . PREFIX . "_module_comment_info AS msg, " . PREFIX . "_module_comments AS cmnt WHERE comment_active = '1' AND msg.Id = '" . $comment_id . "' " . (($user_group != 1) ? "AND comment_author_id = " . $user_id : '') . " ")->FetchAssocArray(); // Если данные получены if ($row !== false) { $comment_max_chars = ($row['comment_max_chars'] != '' && $row['comment_max_chars'] > 10) ? $row['comment_max_chars'] : 20; $comment_text = $post_text; // --- !!! НАЧАЛО ИСПРАВЛЕНИЯ УСТАРЕВШИХ ОПЕРАТОРОВ (/e) !!! --- // Безопасная замена: преобразуем hex-сущности $comment_text = preg_replace_callback('/&#x([0-9a-f]{1,7});/', function($matches) { return chr(hexdec($matches[1])); }, $comment_text); // Безопасная замена: преобразуем dec-сущности $comment_text = preg_replace_callback('/&#([0-9]{1,7});/', function($matches) { return chr($matches[1]); }, $comment_text); // --- !!! КОНЕЦ ИСПРАВЛЕНИЯ УСТАРЕВШИХ ОПЕРАТОРОВ !!! --- $comment_text = stripslashes($comment_text); $comment_text = str_replace(array("
\n", "
\n", "
\n"), "\n", $comment_text); // Санитаризация: убираем теги перед обрезкой $comment_text = strip_tags($comment_text); $comment_text = mb_substr($comment_text, 0, $comment_max_chars-1); $message_length = mb_strlen($comment_text); $comment_text .= ($message_length > $comment_max_chars) ? '…' : ''; // Если группа текущего пользователя совпадает с разрешенной группой в настройках модуля, тогда // выполняем запрос к БД на обновление информации. if (in_array($user_group, explode(',', $row['comment_user_groups'])) && $message_length > 3) { $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comment_info SET comment_changed = '" . time() . "', comment_status = '" . intval(!(bool)$row['comment_need_approve']) . "', comment_text = '" . addslashes($comment_text) . "' WHERE Id = '" . $comment_id . "' "); // Преобразуем HTML теги в HTML сущности перед выводом (для XSS) echo htmlspecialchars($comment_text, ENT_QUOTES); exit; } // Если редактирование не прошло, выводим оригинальный текст (экранированный) echo htmlspecialchars($row['comment_text'], ENT_QUOTES); } exit; } /** * Метод, предназначенный для удаления комментария. Если комментарий содержал какие-либо ответы на него, * то все ответы также будут удалены вместе с родительским комментарием. * * @param int $comment_id - идентификатор комментария */ function commentPostDelete($comment_id) { global $AVE_DB; $comment_id = (int)$comment_id; // Убедимся, что это целое число // Выполняем запрос к БД на удаление родительского комментария $AVE_DB->Query(" DELETE FROM " . PREFIX . "_module_comment_info WHERE Id = '" . $comment_id . "' "); // Выполняем запрос к БД на удаление дочерних комментариев (ответов) $AVE_DB->Query(" DELETE FROM " . PREFIX . "_module_comment_info WHERE parent_id = '" . $comment_id . "' AND parent_id != 0 "); exit; } function commentAdminDelete($comment_id) { global $AVE_DB; $comment_id = (int)$comment_id; // Убедимся, что это целое число // Выполняем запрос к БД на удаление родительского комментария $AVE_DB->Query(" DELETE FROM " . PREFIX . "_module_comment_info WHERE Id = '" . $comment_id . "' "); // Выполняем запрос к БД на удаление дочерних комментариев (ответов) $AVE_DB->Query(" DELETE FROM " . PREFIX . "_module_comment_info WHERE parent_id = '" . $comment_id . "' AND parent_id != 0 "); // Используем оператор объединения с null для PHP 8.4 $session_id = SESSION ?? ''; header('Location:index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=' . $session_id); exit; } /** * Метод, предназначенный для вывода детальной информации об авторе комментария * * @param string $tpl_dir - путь к шаблонам модуля */ function commentPostInfoShow($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $comment_id = (int)($_REQUEST['Id'] ?? 0); // Получаем полную информацию о комментарии $row = $AVE_DB->Query(" SELECT * FROM " . PREFIX . "_module_comment_info WHERE Id = '" . $comment_id . "' ")->FetchAssocArray(); // Преобразуем адрес сайта к формату ссылки $row['comment_author_website'] = str_replace('http://', '', $row['comment_author_website']); $row['comment_author_website'] = ($row['comment_author_website'] != '') ? '' . $row['comment_author_website'] .'' : ''; // Выполняем запрос к БД на получение количества всех комментариев, оставленных данным пользователем $row['num'] = $AVE_DB->Query(" SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE comment_author_id = '" . $row['comment_author_id'] . "' AND comment_author_id != 0 ")->GetCell(); // Отображаем окно с информацией $AVE_Template->assign('c', $row); $AVE_Template->display($tpl_dir . $this->_postinfo_tpl); } /** * Метод, предназначенный для управления запретом или разрешением отвечать на комментарии * * @param int $comment_id - идентификатор комментария * @param string $comment_status - {lock|unlock} признак запрета/разрешения */ function commentReplyStatusSet($comment_id, $comment_status = 'lock') { global $AVE_DB; $comment_id = (int)$comment_id; $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comment_info SET comment_status = '" . (($comment_status == 'lock') ? 0 : 1) . "' WHERE Id = '" . $comment_id . "' "); exit; } /** * Метод, предназначенный для управления запретом или разрешением комментировать документ * * @param int $document_id - идентификатор документа * @param string $comment_status - {close|open} признак запрета/разрешения */ function commentStatusSet($document_id, $comment_status = 'open') { global $AVE_DB; $document_id = (int)$document_id; $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comment_info SET comments_close = '" . (($comment_status == 'open') ? 0 : 1) . "' WHERE document_id = '" . $document_id . "' "); exit; } /** * Следующие методы описывают работу модуля в Административной части сайта. */ /** * Метод, предназначенный для вывода списка всех комментариев в Административной части. * * @param string $tpl_dir - путь к шаблонам модуля */ function commentAdminListShow($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $request_sort = $_REQUEST['sort'] ?? ''; $session_id = SESSION ?? ''; // Получаем общее количество комментариев $num = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info")->GetCell(); // Определяем количество страниц, учитывая параметр _limit, который опроеделяет количество // комментариев отображаемых на одной странице @$seiten = @ceil($num / $this->_limit); $start = get_current_page() * $this->_limit - $this->_limit; $docs = array(); $def_sort = 'ORDER BY doc.Id DESC'; $def_nav = ''; // Определяем условия сортировки комментариев if (!empty($request_sort)) { switch ($request_sort) { case 'document_desc': $def_sort = 'ORDER BY doc.Id ASC'; // Предполагаю, что document_desc должен быть ASC $def_nav = '&sort=document_desc'; break; case 'document': $def_sort = 'ORDER BY doc.Id DESC'; $def_nav = '&sort=document'; break; case 'comment_desc': $def_sort = 'ORDER BY cmnt.comment_text ASC'; $def_nav = '&sort=comment_desc'; break; case 'comment': $def_sort = 'ORDER BY cmnt.comment_text DESC'; $def_nav = '&sort=comment'; break; case 'created_desc': $def_sort = 'ORDER BY cmnt.comment_published ASC'; $def_nav = '&sort=created_desc'; break; case 'created': $def_sort = 'ORDER BY cmnt.comment_published DESC'; $def_nav = '&sort=created'; break; } } // Выполняем запрос к БД на получение комметариев с учетом параметров сортировки и лимита. $sql = $AVE_DB->Query(" SELECT doc.Id, doc.document_title, cmnt.Id AS CId, cmnt.document_id, cmnt.comment_text, cmnt.comment_published, cmnt.comment_status FROM " . PREFIX . "_module_comment_info AS cmnt JOIN " . PREFIX . "_documents AS doc ON doc.Id = cmnt.document_id " . $def_sort . " LIMIT " . $start . "," . $this->_limit ); while ($row = $sql->FetchAssocArray()) { $row['Comments'] = $this->_commentPostCountGet($row['Id']); array_push($docs, $row); } // Если количество комментариев полученных из БД превышает допустимое на странице, тогда формируем // меню постраницной навигации if ($num > $this->_limit) { $page_nav = ' {t} '; $page_nav = get_pagination($seiten, 'page', $page_nav); $AVE_Template->assign('page_nav', $page_nav); } // Передаем данные в шаблон для вывода и отображаем шаблон $AVE_Template->assign('docs', $docs); $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_comments_tpl)); } /** * Метод, предназначенный для редактирования комментариев в Административной части. * * @param string $tpl_dir - путь к шаблонам модуля */ function commentAdminPostEdit($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $post_sub = $_POST['sub'] ?? ''; $request_id = (int)($_REQUEST['Id'] ?? 0); $request_docid = (int)($_REQUEST['docid'] ?? 0); // Выполняем запрос к БД на получение информации о редактируемом комментарии $row = $AVE_DB->Query(" SELECT * FROM " . PREFIX . "_module_comment_info WHERE Id = '" . $request_id . "' LIMIT 1 ")->FetchAssocArray(); // Если в запросе содержится подзапрос на сохранение данных (пользователь уже отредактировал комментарий // и нажал кнопку сохранить изменения), тогда выполняем запрос к БД на обновление информации. if ($post_sub == 'send' && false != $row) { // --- !!! БЕЗОПАСНОСТЬ: Экранирование данных перед сохранением !!! --- $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comment_info SET comment_author_name = '" . addslashes(htmlspecialchars($_POST['comment_author_name'] ?? '')) . "', comment_author_email = '" . addslashes(htmlspecialchars($_POST['comment_author_email'] ?? '')) . "', comment_author_city = '" . addslashes(htmlspecialchars($_POST['comment_author_city'] ?? '')) . "', comment_author_website = '" . addslashes(htmlspecialchars($_POST['comment_author_website'] ?? '')) . "', comment_text = '" . addslashes(htmlspecialchars($_POST['comment_text'] ?? '')) . "', comment_changed = '" . time() . "' WHERE Id = '" . (int)($_POST['Id'] ?? 0) . "' "); echo ''; return; } // Если в первой выборке из БД мы получили нулевой результат, тогда генерируем сообщение с ошибкой if ($row == false) { $AVE_Template->assign('editfalse', 1); } // в противном случае получаем список комментариев, у которых стоит запрет на ответы else { $closed = $AVE_DB->Query(" SELECT comments_close FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $request_docid . "' LIMIT 1 ")->GetCell(); $AVE_Template->assign('closed', $closed); $AVE_Template->assign('row', $row); $AVE_Template->assign('comment_max_chars', $this->_commentSettingsGet('comment_max_chars')); } // Отображаем шаблон $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_edit_link_tpl)); } /** * Метод, предназначенный для управления настройками модуля * * @param string $tpl_dir - путь к шаблонам модуля */ function commentAdminSettingsEdit($tpl_dir) { global $AVE_DB, $AVE_Template; // Используем оператор объединения с null для PHP 8.4 $request_sub = $_REQUEST['sub'] ?? ''; $post_max_chars = $_POST['comment_max_chars'] ?? 0; $post_user_groups = $_POST['comment_user_groups'] ?? array(); // НОВОЕ: Получение данных для групп, которым разрешен просмотр $post_user_groups_read = $_POST['comment_user_groups_read'] ?? array(); // КОНЕЦ НОВОГО $post_need_approve = $_POST['comment_need_approve'] ?? 0; $post_active = $_POST['comment_active'] ?? 0; $post_use_antispam = $_POST['comment_use_antispam'] ?? 0; $post_use_page_nav = $_POST['comment_use_page_nav'] ?? 0; $post_page_nav_count = $_POST['comment_page_nav_count'] ?? 0; // Если в запросе содержится подзапрос на сохранение данных (пользователь нажал кнопку // сохранить изменения), тогда выполняем запрос к БД на обновление информации. if ($request_sub == 'save') { $max_chars = (empty($post_max_chars) || $post_max_chars < 50) ? 50 : $post_max_chars; $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comments SET comment_max_chars = '" . (int)$max_chars . "', comment_user_groups = '" . implode(',', $post_user_groups) . "', comment_user_groups_read = '" . implode(',', $post_user_groups_read) . "', /* <-- СОХРАНЕНИЕ НОВОГО ПОЛЯ */ comment_need_approve = '" . (int)$post_need_approve . "', comment_active = '" . (int)$post_active . "', comment_use_antispam = '" . (int)$post_use_antispam . "', comment_use_page_nav = '" . (int)$post_use_page_nav . "', comment_page_nav_count = '" . (int)$post_page_nav_count . "' WHERE Id = 1 "); } // Получаем список всех настроек модуля $row = $this->_commentSettingsGet(); // Преобразуем поля с правами в массивы для удобства отображения в шаблоне $row['comment_user_groups'] = explode(',', $row['comment_user_groups']); $row['comment_user_groups_read'] = explode(',', $row['comment_user_groups_read']); /* <-- ПОЛУЧЕНИЕ НОВОГО ПОЛЯ */ // Передаем данные в шаблон и показываем страницу с настройками модуля $AVE_Template->assign($row); $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_settings_tpl)); } } ?>