1328 lines
52 KiB
PHP
1328 lines
52 KiB
PHP
<?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'];
|
||
|
||
$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)
|
||
{
|
||
$page_nav = '<a class="page_nav" href="index.php?id=' . $AVE_Core->curentdoc->Id
|
||
. '&doc=' . (empty($AVE_Core->curentdoc->document_alias) ? prepare_url($AVE_Core->curentdoc->document_title) : $AVE_Core->curentdoc->document_alias)
|
||
. ((isset($artpage) && is_numeric($artpage)) ? '&artpage=' . $artpage : '')
|
||
. ((isset($apage) && is_numeric($apage)) ? '&apage=' . $apage : '')
|
||
. '&page={s}">{t}</a> ';
|
||
$page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav, get_settings('navi_box'));
|
||
$page_nav = preg_replace('/(?<!:)\/\//', '/', $page_nav);
|
||
}
|
||
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())
|
||
{
|
||
if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0)
|
||
{
|
||
$row['avatar'] = getAvatar($row['comment_author_id'], 48);
|
||
}
|
||
else
|
||
{
|
||
$row['avatar'] = '';
|
||
}
|
||
|
||
// --- ИСПРАВЛЕННАЯ ЛОГИКА ТАЙМЕРА И ПРАВ (УЧЕТ АДМИНА) ---
|
||
$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'])))
|
||
{
|
||
// --- ОБРАБОТКА ЗАГРУЗКИ ИЗОБРАЖЕНИЯ ---
|
||
$comment_file_name = '';
|
||
if ($settings['comment_allow_files'] == 1 && isset($_FILES['comment_image']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK)
|
||
{
|
||
$upload_path = BASE_DIR . '/uploads/comments/';
|
||
|
||
// Создаем папку, если её нет
|
||
if (!is_dir($upload_path)) {
|
||
@mkdir($upload_path, 0775, true);
|
||
|
||
// Содержимое для защитного файла index.php
|
||
$index_content = "<?php
|
||
/**
|
||
* Файл-заглушка, предназначенный для запрета показа списка файлов в текущей директории,
|
||
* если через адресную строку браузера было прямое обращение к данной директории.
|
||
*/
|
||
header('Location:/');
|
||
exit;
|
||
?>";
|
||
|
||
// Создаем index.php для безопасности (запрет листинга папки и редирект)
|
||
@file_put_contents($upload_path . 'index.php', $index_content);
|
||
}
|
||
|
||
$allowed_mime = ['image/jpeg', 'image/png', 'image/gif'];
|
||
$file_info = @getimagesize($_FILES['comment_image']['tmp_name']);
|
||
$file_size = $_FILES['comment_image']['size'];
|
||
|
||
// Проверка: это реально картинка и её размер не более 2Мб
|
||
if ($file_info && in_array($file_info['mime'], $allowed_mime) && $file_size <= 2 * 1024 * 1024)
|
||
{
|
||
$ext = pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION);
|
||
$comment_file_name = time() . '_' . rand(100, 999) . '.' . $ext;
|
||
|
||
if (!move_uploaded_file($_FILES['comment_image']['tmp_name'], $upload_path . $comment_file_name)) {
|
||
$comment_file_name = ''; // Сбрасываем, если не удалось переместить
|
||
}
|
||
}
|
||
}
|
||
|
||
// --- ПОДГОТОВКА ДАННЫХ ДЛЯ БД ---
|
||
|
||
// ПРОВЕРКА РОДИТЕЛЯ: Если родитель не найден в БД, сбрасываем в 0 (корень)
|
||
$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'] = $comment_file_name;
|
||
|
||
// --- ВОТ ЭТИ ТРИ СТРОЧКИ: ПОЛУЧАЕМ РЕЙТИНГ ИЗ ФОРМЫ ---
|
||
$user_rating = (int)($_POST['comment_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_max_chars = $settings['comment_max_chars'];
|
||
$comment_max_chars = (!empty($comment_max_chars) && $comment_max_chars > 10) ? $comment_max_chars : 200;
|
||
|
||
$comment_text_clean = strip_tags(stripslashes($comment_text_raw));
|
||
$comment_text_cut = mb_substr($comment_text_clean, 0, $comment_max_chars);
|
||
$comment_text_cut .= (mb_strlen($comment_text_clean) > $comment_max_chars) ? '…' : '';
|
||
$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();
|
||
|
||
// --- УВЕДОМЛЕНИЕ АДМИНА ---
|
||
$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'];
|
||
|
||
$mail_text = $AVE_Template->get_config_vars('COMMENT_MESSAGE_ADMIN');
|
||
$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');
|
||
|
||
if ($ajax)
|
||
{
|
||
$new_comment['avatar'] = (isset($new_comment['comment_author_id']) && $new_comment['comment_author_id'] > 0) ? getAvatar($new_comment['comment_author_id'], 48) : '';
|
||
$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']);
|
||
$new_comment['settings'] = $settings;
|
||
|
||
$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);
|
||
}
|
||
}
|
||
|
||
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_edit_time в выборку SQL
|
||
$row = $AVE_DB->Query("
|
||
SELECT
|
||
msg.*,
|
||
cmnt.comment_max_chars,
|
||
cmnt.comment_need_approve,
|
||
cmnt.comment_user_groups,
|
||
cmnt.comment_edit_time
|
||
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);
|
||
|
||
// ИСПРАВЛЕНО: Теперь берем лимит времени ПРЯМО из БД ($row), а не из переменной класса
|
||
$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. Работа с изображениями (без изменений...)
|
||
$new_file_sql = "";
|
||
$upload_dir = BASE_DIR . '/uploads/comments/';
|
||
|
||
if (isset($_FILES['comment_image']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK) {
|
||
if (!is_dir($upload_dir)) @mkdir($upload_dir, 0775, true);
|
||
|
||
if (!empty($row['comment_file']) && file_exists($upload_dir . $row['comment_file'])) {
|
||
@unlink($upload_dir . $row['comment_file']);
|
||
}
|
||
|
||
$file_ext = strtolower(pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION));
|
||
$new_file_name = 'comm_' . time() . '_' . rand(100, 999) . '.' . $file_ext;
|
||
|
||
if (move_uploaded_file($_FILES['comment_image']['tmp_name'], $upload_dir . $new_file_name)) {
|
||
$new_file_sql = ", comment_file = '" . addslashes($new_file_name) . "'";
|
||
}
|
||
}
|
||
elseif (isset($_POST['delete_image']) && $_POST['delete_image'] == 1) {
|
||
if (!empty($row['comment_file']) && file_exists($upload_dir . $row['comment_file'])) {
|
||
@unlink($upload_dir . $row['comment_file']);
|
||
}
|
||
$new_file_sql = ", comment_file = ''";
|
||
}
|
||
|
||
$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 . "'
|
||
$new_file_sql
|
||
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);
|
||
|
||
// Теперь $this->conf_edit_time точно содержит значение из БД (благодаря вызову выше)
|
||
$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('Доступ запрещен');
|
||
}
|
||
|
||
// --- ШАГ 1. ПРОВЕРКА НАЛИЧИЯ ОТВЕТОВ (без изменений) ---
|
||
$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'])) {
|
||
if (file_exists($upload_dir . $comment_data['comment_file'])) @unlink($upload_dir . $comment_data['comment_file']);
|
||
}
|
||
|
||
$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'])) {
|
||
$f_path = $upload_dir . $f['comment_file'];
|
||
if (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_rating_type = $_POST['comment_rating_type'] ?? 0;
|
||
$post_show_user_rating = $_POST['comment_show_user_rating'] ?? 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;
|
||
|
||
// Подготовка имен полей (оставляем твою логику с htmlspecialchars)
|
||
$clean_name_f1 = htmlspecialchars(stripslashes($post_name_f1), ENT_QUOTES);
|
||
$clean_name_f2 = htmlspecialchars(stripslashes($post_name_f2), ENT_QUOTES);
|
||
|
||
$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_rating_type = '" . (int)$post_rating_type . "',
|
||
comment_show_user_rating = '" . (int)$post_show_user_rating . "',
|
||
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));
|
||
}
|
||
|
||
}
|
||
|
||
?>
|