Files
comment/class/comment.php

1452 lines
59 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Класс, включающий все свойства и методы для управления комментариями как в
* Публичной части сайта, так и в Панели управления.
*
* @package AVE.cms
* @subpackage module_Comment
* @since 1.4
* @filesource
*/
class Comment
{
/**
* Свойства класса
*/
/**
* Идентификатор записи с настройками модуля Комментарии
*
* @var int
*/
private $_config_id = 1;
/**
* Количество комментариев на странице в административной части
*
* @var int
*/
private $_limit = 15;
/**
* Имя файла с шаблоном для вывода блока комментариев
*
* @var string
*/
public $_comments_tree_tpl = 'comments_tree.tpl';
/**
* Имя файла с шаблоном для рекурсивного вывода иерархии комментариев
*
* @var string
*/
public $_comments_tree_sub_tpl = 'comments_tree_sub.tpl';
/**
* Имя файла с шаблоном формы добавления комментария
*
* @var string
*/
public $_comment_form_tpl = 'comment_form.tpl';
/**
* Имя файла с шаблоном нового комментария
*
* @var string
*/
public $_comment_new_tpl = 'comment_new.tpl';
/**
* Имя файлаа с шаблоном уведомляющим о успешном выполнении операции
*
* @var string
*/
public $_comment_thankyou_tpl = 'comment_thankyou.tpl';
/**
* Имя файла с шаблоном редактирования шаблона в административной части
*
* @var string
*/
public $_admin_edit_link_tpl = 'admin_edit.tpl';
/**
* Имя файла с шаблоном списка комментариев в административной части
*
* @var string
*/
public $_admin_comments_tpl = 'admin_comments.tpl';
/**
* Имя файла с шаблоном редактирования настроек модуля в административной части
*
* @var string
*/
public $_admin_settings_tpl = 'admin_settings.tpl';
/**
* Имя файла с шаблоном редактирования шаблона в публичной части
*
* @var string
*/
public $_edit_link_tpl = 'comment_edit.tpl';
/**
* Имя файла с шаблоном для вывода информации об авторе комментария
*
* @var string
*/
public $_postinfo_tpl = 'comment_info.tpl';
/**
* Настройки времени (подгружаются из БД)
*/
public $conf_edit_time;
public $conf_cookie_life;
private $_anon_cookie_name = 'ave_anon_comment_key';
/**
* Конструктор класса
* Срабатывает автоматически при создании объекта Comment
*/
function __construct()
{
// Как только класс создан, мы ПЕРВЫМ ДЕЛОМ лезем в базу за настройками
$this->_commentSettingsGet();
}
/**
* Внутренние методы класса
*/
/**
* Получение или создание уникального ключа для анонимного пользователя
*/
private function _getAnonKey()
{
if (isset($_COOKIE[$this->_anon_cookie_name])) {
return preg_replace('/[^a-f0-9]/', '', $_COOKIE[$this->_anon_cookie_name]);
} else {
$new_key = md5(uniqid(rand(), true));
// Устанавливаем куку на заданный срок
setcookie($this->_anon_cookie_name, $new_key, time() + (86400 * $this->conf_cookie_life), "/");
$_COOKIE[$this->_anon_cookie_name] = $new_key; // Чтобы сразу было доступно в текущем скрипте
return $new_key;
}
}
function _commentSettingsGet($param = '')
{
global $AVE_DB;
static $settings = null;
if ($settings === null)
{
$settings = $AVE_DB->Query("
SELECT *
FROM " . PREFIX . "_module_comments
WHERE Id = '" . $this->_config_id . "'
")->FetchAssocArray();
// ОБНОВЛЯЕМ ПЕРЕМЕННЫЕ КЛАССА ЗНАЧЕНИЯМИ ИЗ БАЗЫ
if ($settings) {
// Если в базе есть настройка, перезаписываем стандартные 60 секунд
if (isset($settings['comment_edit_time'])) {
$this->conf_edit_time = (int)$settings['comment_edit_time'];
}
// Если в базе есть настройка куки, перезаписываем стандартные 30 дней
if (isset($settings['comment_cookie_life'])) {
$this->conf_cookie_life = (int)$settings['comment_cookie_life'];
}
}
}
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 - путь к шаблонам модуля
*/
function commentListShow($tpl_dir)
{
global $AVE_DB, $AVE_Template, $AVE_Core;
$document_id = (int)($_REQUEST['id'] ?? 0);
$artpage = $_REQUEST['artpage'] ?? null;
$apage = $_REQUEST['apage'] ?? null;
$user_group = (int)(UGROUP ?? 0);
// --- ОПРЕДЕЛЯЕМ ТЕКУЩЕГО ПОЛЬЗОВАТЕЛЯ ---
$current_user_id = (int)($_SESSION['user_id'] ?? 0);
$anon_key = $this->_getAnonKey();
// Получаем ВСЕ настройки модуля разом (из БД)
$settings = $this->_commentSettingsGet();
// Проверяем, что в настройках модуля разрешено комментирование
if (isset($settings['comment_active']) && $settings['comment_active'] == 1)
{
$read_groups = explode(',', $settings['comment_user_groups_read']);
$assign['no_read_permission'] = 0;
if (!in_array($user_group, $read_groups))
{
$assign['no_read_permission'] = 1;
}
$assign['display_comments'] = 1;
if (in_array($user_group, explode(',', $settings['comment_user_groups'])))
{
$assign['cancomment'] = 1;
}
if ($assign['no_read_permission'] == 0)
{
$assign['comment_max_chars'] = $settings['comment_max_chars'];
$assign['im'] = $settings['comment_use_antispam'];
$assign['comment_allowed_extensions'] = $settings['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif';
$assign['comment_max_file_size'] = $settings['comment_max_file_size'] ?? 2048;
$assign['comment_max_files'] = (int)($settings['comment_max_files'] ?? 5);
$comments = array();
if ($settings['comment_use_page_nav'] == 1)
{
$limit = $settings['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 " . (int)$start . "," . (int)$limit . "
");
if ($num > $limit)
{
// 1. Формируем базовый шаблон ссылки
$page_nav = '<a class="page_nav" href="index.php?id=' . $AVE_Core->curentdoc->Id
. '&amp;doc=' . (empty($AVE_Core->curentdoc->document_alias) ? prepare_url($AVE_Core->curentdoc->document_title) : $AVE_Core->curentdoc->document_alias)
. ((isset($artpage) && is_numeric($artpage)) ? '&amp;artpage=' . $artpage : '')
. ((isset($apage) && is_numeric($apage)) ? '&amp;apage=' . $apage : '')
. '&amp;page={s}">{t}</a> ';
// 2. Генерируем стандартную пагинацию системы
$page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav, get_settings('navi_box'));
// 3. ПРИМЕНЯЕМ КОСТЫЛИ ДЛЯ ЧПУ
// Прогоняем через rewrite_link и чистим двойные/тройные слеши
$page_nav = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($page_nav)));
$page_nav = preg_replace('/(?<!:)\/\//', '/', $page_nav);
// 4. Регистрируем пагинацию в глобальном массиве системы (без этого на главной может не работать)
$GLOBALS['page_id'][$document_id]['page'] = ($GLOBALS['page_id'][$document_id]['page'] > 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');
$now = time();
// ГАРАНТИРУЕМ получение лимита времени из настроек БД
$conf_limit = (int)($settings['comment_edit_time'] ?? 0);
while ($row = $sql->FetchAssocArray())
{
// 1. Получаем аватар через стандартную функцию системы
if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0)
{
$row['avatar'] = getAvatar($row['comment_author_id'], 48);
}
else
{
$row['avatar'] = '';
}
// 2. ПРОВЕРКА: Если функция вернула системную заглушку, считаем, что аватара нет
if (!empty($row['avatar']) && strpos($row['avatar'], 'user.png') !== false)
{
$row['avatar'] = '';
}
// 3. ЛОГИКА БУКВ: Если аватара нет (пусто или мы его обнулили выше)
if (empty($row['avatar']))
{
// Берем имя автора (если пусто — 'Guest')
$name = !empty($row['comment_author_name']) ? stripslashes($row['comment_author_name']) : 'Guest';
// Получаем первую букву имени (в верхнем регистре)
$row['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8');
// Вычисляем индекс цвета (от 1 до 8) на основе имени
$row['avatar_color_index'] = (abs(crc32($name)) % 12) + 1;
}
// --- ИСПРАВЛЕННАЯ ЛОГИКА ТАЙМЕРА И ПРАВ (УЧЕТ АДМИНА) ---
$row['can_edit'] = 0;
$is_admin = ($user_group === 1);
// Проверяем авторство
$is_author = ($current_user_id > 0 && $current_user_id == $row['comment_author_id']) ||
($row['comment_author_id'] == 0 && !empty($row['anon_key']) && $row['anon_key'] == $anon_key);
if ($is_admin) {
$row['can_edit'] = 1;
// Для админа таймер не нужен, ставим 0, чтобы JS его игнорировал
$row['edit_time_left'] = 0;
} else {
// Рассчитываем остаток времени только для простых смертных
$elapsed = $now - (int)$row['comment_published'];
$time_left = $conf_limit - $elapsed;
$row['edit_time_left'] = ($time_left > 0) ? $time_left : 0;
if ($is_author && $row['edit_time_left'] > 0) {
$row['can_edit'] = 1;
}
}
$row['is_my_own'] = $is_author;
// -------------------------------------------------------
$row['comment_published_raw'] = $row['comment_published'];
$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('anon_key', $anon_key);
$AVE_Template->assign($settings);
$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;
$page = $_REQUEST['page'] ?? '';
$ajax = (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == 1);
$user_group = UGROUP ?? 0;
$secure_code = $_POST['securecode'] ?? '';
$session_captcha = $_SESSION['captcha_keystring'] ?? null;
$settings = $this->_commentSettingsGet();
// --- ПОЛУЧАЕМ КЛЮЧ АНОНИМА ---
$anon_key = $this->_getAnonKey();
if (! $ajax)
{
$link = rewrite_link(base64_decode($page));
}
// --- ПРОВЕРКА ОБЯЗАТЕЛЬНЫХ ПОЛЕЙ ---
if ($settings['comment_show_f1'] == 1 && $settings['comment_req_f1'] == 1 && empty($_POST['comment_author_website']))
{
if ($ajax) { echo 'error_req_f1'; exit; }
else { header('Location:' . $link . '#end'); exit; }
}
if ($settings['comment_show_f2'] == 1 && $settings['comment_req_f2'] == 1 && empty($_POST['comment_author_city']))
{
if ($ajax) { echo 'error_req_f2'; exit; }
else { header('Location:' . $link . '#end'); exit; }
}
// --- АНТИСПАМ ---
if ($settings['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 = ($settings['comment_need_approve'] == 1) ? 0 : 1;
if ($settings['comment_active'] == 1
&& !empty($_POST['comment_text'])
&& !empty($_POST['comment_author_name'])
&& in_array($user_group, explode(',', $settings['comment_user_groups'])))
{
// --- ОБРАБОТКА ЗАГРУЗКИ ИЗОБРАЖЕНИЯ (С ЗАЩИТОЙ ОТ ДУБЛЕЙ) ---
$uploaded_files = [];
if ($settings['comment_allow_files'] == 1 && isset($_FILES['comment_image']))
{
// --- ДОБАВЛЯЕМ ПРОВЕРКУ ЛИМИТА КОЛИЧЕСТВА ---
$max_files_limit = (int)($settings['comment_max_files'] ?? 5);
$total_incoming = 0;
if (is_array($_FILES['comment_image']['name'])) {
foreach($_FILES['comment_image']['name'] as $fname) if(!empty($fname)) $total_incoming++;
} elseif(!empty($_FILES['comment_image']['name'])) {
$total_incoming = 1;
}
if ($total_incoming > $max_files_limit) {
if ($ajax) { echo 'error_max_files'; exit; }
else { header('Location:' . $link . '#end'); exit; }
}
// --- КОНЕЦ ПРОВЕРКИ ---
$upload_path = BASE_DIR . '/uploads/comments/';
if (!is_dir($upload_path)) {
@mkdir($upload_path, 0775, true);
$index_content = "<?php\n/**\n * Файл-заглушка...\n */\nheader('Location:/');\nexit;\n?>";
@file_put_contents($upload_path . 'index.php', $index_content);
}
$files_to_process = [];
if (is_array($_FILES['comment_image']['name'])) {
foreach ($_FILES['comment_image']['name'] as $k => $v) {
if (!empty($v) && $_FILES['comment_image']['error'][$k] == UPLOAD_ERR_OK) {
$files_to_process[] = [
'name' => $_FILES['comment_image']['name'][$k],
'tmp_name' => $_FILES['comment_image']['tmp_name'][$k],
'size' => $_FILES['comment_image']['size'][$k]
];
}
}
} elseif (!empty($_FILES['comment_image']['name']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK) {
$files_to_process[] = $_FILES['comment_image'];
}
$allowed_ext_str = $settings['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp';
$allowed_extensions = array_map('trim', explode(',', strtolower($allowed_ext_str)));
$max_file_size_bytes = (int)($settings['comment_max_file_size'] ?? 2048) * 1024;
// Защита: не даем загрузить одно и то же содержимое дважды в одном запросе
$processed_hashes = [];
foreach ($files_to_process as $file) {
$file_hash = md5_file($file['tmp_name']);
if (in_array($file_hash, $processed_hashes)) continue;
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (in_array($ext, $allowed_extensions)
&& $file['size'] > 0
&& $file['size'] <= $max_file_size_bytes
&& strpos($mime, 'image/') === 0)
{
$new_name = time() . '_' . rand(100, 999) . '.' . $ext;
if (move_uploaded_file($file['tmp_name'], $upload_path . $new_name)) {
$uploaded_files[] = $new_name;
$processed_hashes[] = $file_hash;
}
}
}
}
// --- ПОДГОТОВКА ДАННЫХ ДЛЯ БД ---
$parent_id = (int)($_POST['parent_id'] ?? 0);
if ($parent_id > 0) {
$parent_exists = $AVE_DB->Query("SELECT Id FROM " . PREFIX . "_module_comment_info WHERE Id = '" . $parent_id . "'")->GetCell();
if (!$parent_exists) $parent_id = 0;
}
$new_comment['parent_id'] = $parent_id;
$new_comment['document_id'] = (int)($_POST['doc_id'] ?? 0);
$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['anon_key'] = ($new_comment['comment_author_id'] == 0) ? $anon_key : '';
$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;
// Пишем список файлов
$new_comment['comment_file'] = !empty($uploaded_files) ? implode(',', $uploaded_files) : '';
$user_rating = (int)($_POST['comment_user_rating'] ?? 0);
if ($parent_id > 0 && (!isset($settings['comment_show_user_rating_replies']) || $settings['comment_show_user_rating_replies'] == 0)) {
$user_rating = 0;
}
if ($user_rating < 0) $user_rating = 0; if ($user_rating > 5) $user_rating = 5;
$new_comment['user_rating'] = $user_rating;
$comment_text_raw = $_POST['comment_text'] ?? '';
$comment_text_clean = strip_tags(stripslashes($comment_text_raw));
$new_comment['comment_text'] = addslashes($comment_text_clean);
$AVE_DB->Query("INSERT INTO " . PREFIX . "_module_comment_info (`" . implode('`,`', array_keys($new_comment)) ."`) VALUES ('" . implode("','", $new_comment) . "')");
$new_comment['Id'] = $AVE_DB->InsertId();
// --- УВЕДОМЛЕНИЕ АДМИНА ---
$mail_from = get_settings('mail_from');
$mail_from_name = get_settings('mail_from_name');
$page_link = get_home_link() . urldecode(base64_decode($page)) . '&comment_id=' . $new_comment['Id'] . '#' . $new_comment['Id'];
$mail_text = "Новый комментарий:\n" . stripslashes($new_comment['comment_text']) . "\n\nСсылка: " . $page_link;
send_mail($mail_from, $mail_text, "Новый комментарий на сайте", $mail_from, $mail_from_name, 'text');
if ($ajax)
{
$new_comment['avatar'] = (isset($new_comment['comment_author_id']) && $new_comment['comment_author_id'] > 0) ? getAvatar($new_comment['comment_author_id'], 48) : '';
if (empty($new_comment['avatar']) || strpos($new_comment['avatar'], 'user.png') !== false) {
$name = !empty($new_comment['comment_author_name']) ? stripslashes($new_comment['comment_author_name']) : 'Guest';
$new_comment['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8');
$new_comment['avatar_color_index'] = (abs(crc32($name)) % 12) + 1;
}
$new_comment['comment_changed'] = 0;
$new_comment['can_edit'] = 1;
$new_comment['edit_time_left'] = $this->conf_edit_time;
$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->display($tpl_dir . $this->_comments_tree_sub_tpl);
}
}
if (! $ajax) header('Location:' . str_replace("//", "", $link) . '#end');
exit;
}
function commentPostEdit($comment_id)
{
global $AVE_DB;
// 1. Инициализация данных
$comment_id = (int)$comment_id;
$user_id = (int)($_SESSION['user_id'] ?? 0);
$user_group = (int)(defined('UGROUP') ? UGROUP : 0);
$anon_key = $this->_getAnonKey();
if ($comment_id <= 0 || $user_group <= 0) exit('INVALID_ID');
// 2. Получаем данные комментария и настройки модуля (JOIN)
// ДОБАВЛЕНО: cmnt.comment_max_files в выборку
$row = $AVE_DB->Query("
SELECT
msg.*,
cmnt.comment_max_chars,
cmnt.comment_need_approve,
cmnt.comment_user_groups,
cmnt.comment_edit_time,
cmnt.comment_allowed_extensions,
cmnt.comment_max_file_size,
cmnt.comment_max_files
FROM " . PREFIX . "_module_comment_info AS msg
JOIN " . PREFIX . "_module_comments AS cmnt ON cmnt.Id = 1
WHERE msg.Id = '" . $comment_id . "'
LIMIT 1
")->FetchAssocArray();
if (!$row) exit('NOT_FOUND');
// 3. Проверка прав (БЕЗОПАСНОСТЬ)
$is_admin = ($user_group == 1);
$is_author = ($user_id > 0 && $user_id == $row['comment_author_id']) ||
($row['comment_author_id'] == 0 && !empty($row['anon_key']) && $row['anon_key'] == $anon_key);
$time_limit = (isset($row['comment_edit_time'])) ? (int)$row['comment_edit_time'] : 60;
$time_passed = time() - (int)$row['comment_published'];
$is_time_ok = ($time_passed < $time_limit);
if (!$is_admin) {
if (!$is_author) exit('NOT_AUTHOR');
if (!$is_time_ok) {
echo "TIME_EXPIRED";
exit;
}
}
// 4. Обработка текста
$comment_text = $_POST['text'] ?? '';
$comment_text = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', function($matches) { return chr(hexdec($matches[1])); }, $comment_text);
$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("<br>\n", "<br />\n", "<br/>\n", "<br>", "<br />"), "\n", $comment_text);
$comment_text = strip_tags($comment_text);
$max = ($row['comment_max_chars'] > 10) ? (int)$row['comment_max_chars'] : 1000;
$comment_text_cut = mb_substr($comment_text, 0, $max);
if (mb_strlen($comment_text) > $max) $comment_text_cut .= '…';
// 5. Работа с изображениями (МУЛЬТИЗАГРУЗКА И УДАЛЕНИЕ)
$upload_dir = BASE_DIR . '/uploads/comments/';
// Получаем текущие файлы из БД в массив
$current_files = !empty($row['comment_file']) ? explode(',', $row['comment_file']) : [];
// --- А. Обработка выборочного удаления ---
if (!empty($_POST['delete_files'])) {
$files_to_remove = explode(',', $_POST['delete_files']);
foreach ($files_to_remove as $rem_file) {
$rem_file = trim($rem_file);
if (empty($rem_file)) continue;
// Удаляем физически
if (file_exists($upload_dir . $rem_file)) {
@unlink($upload_dir . $rem_file);
}
// Удаляем из нашего массива для БД
$current_files = array_filter($current_files, function($v) use ($rem_file) {
return trim($v) !== $rem_file;
});
}
}
// --- Б. Загрузка новых файлов (с проверкой лимита) ---
if (isset($_FILES['comment_image']) && is_array($_FILES['comment_image']['name'])) {
// 1. Считаем, сколько реально новых файлов пытаются загрузить
$new_files_to_upload_count = 0;
foreach ($_FILES['comment_image']['name'] as $k => $fname) {
if (!empty($fname) && $_FILES['comment_image']['error'][$k] == UPLOAD_ERR_OK) {
$new_files_to_upload_count++;
}
}
// 2. Проверка лимита: (Оставшиеся старые + Новые) не должно быть больше MAX
$max_limit = (int)($row['comment_max_files'] ?? 5);
if ((count($current_files) + $new_files_count) > $max_limit) {
echo "MAX_FILES_LIMIT_EXCEEDED"; // Это поймает JS
exit;
}
$allowed_ext_str = $row['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp';
$allowed_extensions = array_map('trim', explode(',', strtolower($allowed_ext_str)));
$max_kb = (int)($row['comment_max_file_size'] ?? 2048);
// Перебираем загруженные файлы
foreach ($_FILES['comment_image']['name'] as $i => $fname) {
if ($_FILES['comment_image']['error'][$i] == UPLOAD_ERR_OK) {
$tmp_name = $_FILES['comment_image']['tmp_name'][$i];
$file_ext = strtolower(pathinfo($fname, PATHINFO_EXTENSION));
$file_size = $_FILES['comment_image']['size'][$i];
// Проверка MIME-типа
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmp_name);
finfo_close($finfo);
if (in_array($file_ext, $allowed_extensions)
&& $file_size > 0
&& $file_size <= ($max_kb * 1024)
&& strpos($mime, 'image/') === 0)
{
if (!is_dir($upload_dir)) @mkdir($upload_dir, 0775, true);
$new_file_name = 'comm_' . time() . '_' . rand(1000, 9999) . '.' . $file_ext;
if (move_uploaded_file($tmp_name, $upload_dir . $new_file_name)) {
$current_files[] = $new_file_name; // Добавляем новый файл к списку
}
}
}
}
}
// Собираем итоговую строку файлов для БД через запятую
$final_files_str = implode(',', array_unique(array_filter($current_files)));
$user_rating = isset($_POST['user_rating']) ? (int)$_POST['user_rating'] : (int)$row['user_rating'];
// 6. Обновление базы данных
$new_status = $is_admin ? (int)$row['comment_status'] : ($row['comment_need_approve'] == '1' ? 0 : 1);
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET
comment_changed = '" . time() . "',
comment_text = '" . addslashes($comment_text_cut) . "',
comment_status = '" . $new_status . "',
user_rating = '" . $user_rating . "',
comment_file = '" . addslashes($final_files_str) . "'
WHERE
Id = '" . $comment_id . "'
");
echo htmlspecialchars($comment_text_cut, ENT_QUOTES);
exit;
}
function commentPostDelete($comment_id)
{
global $AVE_DB;
if (ob_get_level()) ob_end_clean();
$comment_id = (int)$comment_id;
if ($comment_id <= 0) die('Ошибка: Неверный ID');
// --- ШАГ 0. ПОЛУЧЕНИЕ ДАННЫХ И ПРОВЕРКА ПРАВ ---
$this->_commentSettingsGet();
$comment_data = $AVE_DB->Query("
SELECT comment_author_id, anon_key, comment_published, comment_file
FROM " . PREFIX . "_module_comment_info
WHERE Id = '" . $comment_id . "'
")->FetchAssocArray();
if (!$comment_data) die('Ошибка: Комментарий не найден');
$current_user_id = (int)($_SESSION['user_id'] ?? 0);
$user_group = (int)($_SESSION['user_group'] ?? (defined('UGROUP') ? UGROUP : 0));
$anon_key = $this->_getAnonKey();
$can_delete = false;
if ($user_group === 1) {
$can_delete = true;
} else {
$is_author = ($current_user_id > 0 && $current_user_id == $comment_data['comment_author_id']) ||
($comment_data['comment_author_id'] == 0 && !empty($comment_data['anon_key']) && $comment_data['anon_key'] == $anon_key);
$is_time_ok = (time() - (int)$comment_data['comment_published'] < (int)$this->conf_edit_time);
if ($is_author && $is_time_ok) {
$can_delete = true;
}
}
if (!$can_delete) {
header('HTTP/1.1 403 Forbidden');
die('Доступ запрещен');
}
$has_children = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE parent_id = '" . $comment_id . "'")->GetCell();
$upload_dir = BASE_DIR . '/uploads/comments/';
// --- ВАРИАНТ А: МЯГКОЕ УДАЛЕНИЕ (если есть ответы и удаляет не админ) ---
if ($has_children > 0 && $user_group != 1) {
// Удаляем файлы физически, если они есть
if (!empty($comment_data['comment_file'])) {
$files_to_del = explode(',', $comment_data['comment_file']);
foreach ($files_to_del as $f_name) {
$f_path = $upload_dir . trim($f_name);
if (!empty($f_name) && file_exists($f_path)) @unlink($f_path);
}
}
$del_text = "<span class='comment-deleted'>Комментарий удален автором.</span>";
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET comment_text = '" . addslashes($del_text) . "',
comment_file = '',
anon_key = '',
comment_changed = '" . time() . "'
WHERE Id = '" . $comment_id . "'
");
echo "OK_SOFT";
}
else {
// --- ВАРИАНТ Б: ПОЛНОЕ УДАЛЕНИЕ (Админ или нет вложенных ответов) ---
$ids_to_delete = [$comment_id];
// Если админ — собираем всю ветку детей для удаления
if ($user_group == 1) {
$all_child_ids = [];
$parent_ids = [$comment_id];
while (!empty($parent_ids)) {
$ids_string = implode(',', array_map('intval', $parent_ids));
$res = $AVE_DB->Query("SELECT Id FROM " . PREFIX . "_module_comment_info WHERE parent_id IN ($ids_string)");
$parent_ids = [];
while ($row = $res->FetchAssocArray()) {
$all_child_ids[] = (int)$row['Id'];
$parent_ids[] = (int)$row['Id'];
}
}
$ids_to_delete = array_merge($ids_to_delete, $all_child_ids);
}
$final_ids_str = implode(',', $ids_to_delete);
// Массовое удаление всех файлов во всех удаляемых комментариях
$files_res = $AVE_DB->Query("SELECT comment_file FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_ids_str)");
while ($f = $files_res->FetchAssocArray()) {
if (!empty($f['comment_file'])) {
$files_to_del = explode(',', $f['comment_file']);
foreach ($files_to_del as $f_name) {
$f_path = $upload_dir . trim($f_name);
if (!empty($f_name) && file_exists($f_path)) @unlink($f_path);
}
}
}
// Удаляем записи из БД
$AVE_DB->Query("DELETE FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_ids_str)");
echo "OK";
}
die();
}
/**
* Метод для обработки голосования за комментарий
* Защита: ID для залогиненных, Пара (Ключ + IP) для анонимов.
* Добавлена проверка глобальной настройки прав для анонимов.
*/
function commentVote()
{
global $AVE_DB;
// Принимаем данные
$comment_id = (int)($_POST['comment_id'] ?? 0);
$vote_value = (int)($_POST['vote'] ?? 0);
$ajax = (isset($_POST['ajax']) && $_POST['ajax'] == 1);
// IP пользователя
$user_ip = $_SERVER['REMOTE_ADDR'] ?? '';
// Базовая валидация
if ($comment_id <= 0 || $vote_value < 1 || $vote_value > 5) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'error';
exit;
}
return;
}
// 1. Идентификация текущего голосующего
$user_id = empty($_SESSION['user_id']) ? 0 : (int)$_SESSION['user_id'];
$anon_key = $this->_getAnonKey();
// 1.5 ПРОВЕРКА ПРАВ ГОЛОСОВАНИЯ (Новое)
// Получаем настройки модуля, чтобы узнать, разрешено ли анонимам голосовать
$settings = $this->_commentSettingsGet();
if (empty($user_id) && empty($settings['comment_rating_anon_vote'])) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'forbidden_anon'; // Специальный статус для JS
exit;
}
return;
}
// 2. Получаем данные о комментарии, за который голосуют
$comment_row = $AVE_DB->Query("
SELECT comment_author_id, anon_key, comment_author_ip
FROM " . PREFIX . "_module_comment_info
WHERE Id = '" . $comment_id . "'
")->FetchRow();
if (!$comment_row) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'error';
exit;
}
return;
}
$c_author_id = (int)$comment_row->comment_author_id;
// 3. ПРОВЕРКА АВТОРСТВА (Запрет голосовать за свой же комментарий)
$is_author = false;
if ($user_id > 0) {
// Если залогинен — проверяем только по ID
if ($user_id === $c_author_id) {
$is_author = true;
}
} else {
// Если аноним — проверяем парой (Ключ + IP)
// И только если автор комментария тоже был анонимом
if ($c_author_id === 0 &&
$anon_key === $comment_row->anon_key &&
$user_ip === $comment_row->comment_author_ip) {
$is_author = true;
}
}
if ($is_author) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'own_comment';
exit;
}
return;
}
// 4. ПРОВЕРКА ПОВТОРНОГО ГОЛОСОВАНИЯ
// Ищем в истории, голосовал ли уже этот человек
if ($user_id > 0) {
// Для авторизованных поиск по ID
$sql_check = "SELECT id FROM " . PREFIX . "_module_comment_votes
WHERE comment_id = '" . $comment_id . "'
AND user_id = '" . $user_id . "'";
} else {
// Для анонимов поиск по связке Ключ + IP
$sql_check = "SELECT id FROM " . PREFIX . "_module_comment_votes
WHERE comment_id = '" . $comment_id . "'
AND anon_key = '" . $anon_key . "'
AND remote_addr = '" . $user_ip . "'";
}
if ($AVE_DB->Query($sql_check)->GetCell()) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'already_voted';
exit;
}
return;
}
// 5. ЗАПИСЬ ГОЛОСА В ЛОГ
$AVE_DB->Query("
INSERT INTO " . PREFIX . "_module_comment_votes
(comment_id, user_id, anon_key, remote_addr, vote_value, date_voted)
VALUES
('" . $comment_id . "',
'" . $user_id . "',
'" . $AVE_DB->escape($anon_key) . "',
'" . $AVE_DB->escape($user_ip) . "',
'" . $vote_value . "',
'" . time() . "')
");
// 6. ОБНОВЛЕНИЕ АГРЕГАТОВ В ТАБЛИЦЕ INFO
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET rating_sum = rating_sum + " . $vote_value . ",
rating_count = rating_count + 1
WHERE Id = '" . $comment_id . "'
");
// 7. ФИНАЛ: Чистый ответ для JS
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'success';
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'] != '')
? '<a target="_blank" href="http://' . $row['comment_author_website'] . '">' . $row['comment_author_website'] .'</a>'
: '';
// Выполняем запрос к БД на получение количества всех комментариев, оставленных данным пользователем
$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 = ' <a class="pnav" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=' . $session_id . '&page={s}' . $def_nav . '">{t}</a> ';
$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 '<script>window.opener.location.reload();window.close();</script>';
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, $sess;
$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;
// Настройки рейтинга и файлов
$post_allow_files = $_POST['comment_allow_files'] ?? 0;
$post_allow_files_anon = $_POST['comment_allow_files_anon'] ?? 0;
/* НОВОЕ: Настройки расширений и максимального размера файла */
$post_allowed_extensions = $_POST['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif';
$post_max_file_size = $_POST['comment_max_file_size'] ?? 2048;
$post_rating_type = $_POST['comment_rating_type'] ?? 0;
$post_show_user_rating = $_POST['comment_show_user_rating'] ?? 0;
/* НОВОЕ: Настройка показа авторской оценки в ответах */
$post_show_user_rating_replies = $_POST['comment_show_user_rating_replies'] ?? 0;
$post_rating_anon_vote = $_POST['comment_rating_anon_vote'] ?? 0;
$post_rating_anon_set = $_POST['comment_rating_anon_set'] ?? 0;
// Новые настройки времени и куки
$post_edit_time = $_POST['comment_edit_time'] ?? 60;
$post_cookie_life = $_POST['comment_cookie_life'] ?? 30;
// Дополнительные поля
$post_show_f1 = $_POST['comment_show_f1'] ?? 0;
$post_req_f1 = $_POST['comment_req_f1'] ?? 0;
$post_name_f1 = $_POST['comment_name_f1'] ?? '';
$post_show_f2 = $_POST['comment_show_f2'] ?? 0;
$post_req_f2 = $_POST['comment_req_f2'] ?? 0;
$post_name_f2 = $_POST['comment_name_f2'] ?? '';
// Обработка сохранения
if ($request_sub == 'save' || $request_sub == 'apply')
{
$max_chars = (empty($post_max_chars) || $post_max_chars < 50) ? 50 : $post_max_chars;
// Подготовка имен полей и настроек файлов
$clean_name_f1 = htmlspecialchars(stripslashes($post_name_f1), ENT_QUOTES);
$clean_name_f2 = htmlspecialchars(stripslashes($post_name_f2), ENT_QUOTES);
// Очищаем строку расширений от пробелов и лишних запятых
$clean_extensions = implode(',', array_filter(array_map('trim', explode(',', $post_allowed_extensions))));
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comments
SET
comment_max_chars = '" . (int)$max_chars . "',
comment_user_groups = '" . addslashes(implode(',', $post_user_groups)) . "',
comment_user_groups_read = '" . addslashes(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 . "',
comment_allow_files = '" . (int)$post_allow_files . "',
comment_allow_files_anon = '" . (int)$post_allow_files_anon . "',
/* СОХРАНЕНИЕ НОВЫХ ПОЛЕЙ */
comment_allowed_extensions = '" . addslashes($clean_extensions) . "',
comment_max_file_size = '" . (int)$post_max_file_size . "',
comment_rating_type = '" . (int)$post_rating_type . "',
comment_show_user_rating = '" . (int)$post_show_user_rating . "',
comment_show_user_rating_replies = '" . (int)$post_show_user_rating_replies . "',
comment_rating_anon_vote = '" . (int)$post_rating_anon_vote . "',
comment_rating_anon_set = '" . (int)$post_rating_anon_set . "',
comment_edit_time = '" . (int)$post_edit_time . "',
comment_cookie_life = '" . (int)$post_cookie_life . "',
comment_show_f1 = '" . (int)$post_show_f1 . "',
comment_req_f1 = '" . (int)$post_req_f1 . "',
comment_name_f1 = '" . addslashes($clean_name_f1) . "',
comment_show_f2 = '" . (int)$post_show_f2 . "',
comment_req_f2 = '" . (int)$post_req_f2 . "',
comment_name_f2 = '" . addslashes($clean_name_f2) . "'
WHERE
Id = 1
");
if ($request_sub == 'apply') {
@ob_clean();
echo "success";
exit;
}
if ($request_sub == 'save') {
header("Location: index.php?do=modules&cp=" . $sess);
exit;
}
}
// Получаем данные для отображения в шаблоне
$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));
}
}
?>