Files
comment/class/comment.php

1029 lines
39 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';
/**
* Внутренние методы класса
*/
/**
* Метод, предназначенный для получения основных настроек модуля,которые задаются в Панели управления.
*
* @param string $param название параметра
* @return mixed значение настройки
*/
function _commentSettingsGet($param = '')
{
global $AVE_DB;
// Определяем статическую переменную, которая будет хранить полученные настройки на протяжении всего
// срока жизни объекта.
static $settings = null;
// Если переменная $settings еще не имеет значений, тогда выполняем запрос к БД на получение данных
if ($settings === null)
{
$settings = $AVE_DB->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;
$document_id = (int)($_REQUEST['id'] ?? 0);
$artpage = $_REQUEST['artpage'] ?? null;
$apage = $_REQUEST['apage'] ?? null;
$user_group = UGROUP ?? 0;
// Получаем ВСЕ настройки модуля разом
$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
. '&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> ';
$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');
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['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($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();
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.html для безопасности (запрет листинга папки)
@file_put_contents($upload_path . 'index.html', '');
}
$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 = ''; // Сбрасываем, если не удалось переместить
}
}
}
// --- ПОДГОТОВКА ДАННЫХ ДЛЯ БД ---
$new_comment['parent_id'] = (int)($_POST['parent_id'] ?? 0);
$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['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; // НАША НОВАЯ КОЛОНКА
$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('&amp;', '&', $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['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. ОПРЕДЕЛЯЕМ ПОЛЬЗОВАТЕЛЯ ---
// Используем (int), чтобы гарантированно иметь число для SQL
$user_id = (int)($_SESSION['user_id'] ?? 0);
$user_group = (int)(defined('UGROUP') ? UGROUP : 0);
// Разрешаем вход всем системным группам (1, 2, 3, 4).
// Если группа не определена (0), значит это "неопознанная сущность" — выходим.
if ($user_group <= 0) exit;
$post_text = $_POST['text'] ?? '';
$delete_file = (isset($_POST['delete_image']) && $_POST['delete_image'] == 1);
// Очищаем ID комментария
$comment_id = (int)$comment_id;
if ($comment_id <= 0) exit;
// --- 2. ПОЛУЧАЕМ ДАННЫЕ С ПРОВЕРКОЙ ПРАВ ---
// Если не админ (группа 1), то база вернет результат ТОЛЬКО если автор совпадает.
// Для анонимов (группа 2) здесь подставится автор_id = 0, что корректно.
$sql_author_check = ($user_group !== 1) ? "AND msg.comment_author_id = '" . $user_id . "'" : "";
$row = $AVE_DB->Query("
SELECT
msg.parent_id,
msg.comment_text,
msg.comment_file,
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 cmnt.comment_active = '1'
AND msg.Id = '" . $comment_id . "'
" . $sql_author_check . "
")->FetchAssocArray();
if ($row !== false)
{
$comment_max_chars = ($row['comment_max_chars'] != '' && $row['comment_max_chars'] > 10) ? $row['comment_max_chars'] : 200;
// --- ТВОЯ ОРИГИНАЛЬНАЯ ОБРАБОТКА ТЕКСТА ---
$comment_text = $post_text;
$comment_text = preg_replace_callback('/&#x([0-9a-f]{1,7});/', 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"), "\n", $comment_text);
$comment_text = strip_tags($comment_text);
$comment_text_cut = mb_substr($comment_text, 0, $comment_max_chars);
$message_length = mb_strlen($comment_text_cut);
if (mb_strlen($comment_text) > $comment_max_chars) $comment_text_cut .= '…';
$is_admin = ($user_group == 1);
// Проверяем, разрешено ли группе (2 или 4) редактирование в настройках модуля
$is_allowed_group = in_array($user_group, explode(',', $row['comment_user_groups']));
if ($is_admin || ($is_allowed_group && $message_length > 3))
{
$upload_dir = BASE_DIR . '/uploads/comments/';
$new_file_sql = "";
// 1. ЗАМЕНА ФАЙЛА
if (isset($_FILES['comment_image']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK) {
if (!is_dir($upload_dir)) @mkdir($upload_dir, 0777, true);
// Удаляем старый файл, если он был
if (!empty($row['comment_file'])) {
$old_file = $upload_dir . $row['comment_file'];
if (file_exists($old_file)) @unlink($old_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) . "'";
$delete_file = false;
}
}
// 2. УДАЛЕНИЕ ФАЙЛА
elseif ($delete_file && !empty($row['comment_file'])) {
$old_file = $upload_dir . $row['comment_file'];
if (file_exists($old_file)) @unlink($old_file);
$new_file_sql = ", comment_file = ''";
}
// --- ОБНОВЛЕНИЕ БАЗЫ ---
$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_cut) . "'
$new_file_sql
WHERE
Id = '" . $comment_id . "'
");
// Возвращаем текст для обновления на странице
echo htmlspecialchars($comment_text_cut, 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;
if ($comment_id <= 0) exit;
// --- ШАГ 0. ПРОВЕРКА ПРАВ (БЕЗОПАСНОСТЬ) ---
// Сначала узнаем, кто автор комментария, который хотят удалить
$comment_data = $AVE_DB->Query("
SELECT comment_author_id
FROM " . PREFIX . "_module_comment_info
WHERE Id = '" . $comment_id . "'
")->FetchAssocArray();
if (!$comment_data) exit; // Если комментария нет, и удалять нечего
$author_id = (int)$comment_data['comment_author_id'];
$current_user_id = (int)($_SESSION['user_id'] ?? 0);
$user_group = (int)(defined('UGROUP') ? UGROUP : 0);
$can_delete = false;
// ПРАВО АДМИНА: Если группа 1 — разрешаем всё сразу
if ($user_group === 1) {
$can_delete = true;
}
// ПРАВО АВТОРА: Если залогинен и ID совпадает с автором — разрешаем
elseif ($current_user_id > 0 && $current_user_id === $author_id) {
$can_delete = true;
}
// Если ни одно условие не сработало — выкидываем взломщика
if (!$can_delete) {
exit('Доступ запрещен');
}
// --- ШАГ 1. ОЧИСТКА ФАЙЛОВ (ТОЛЬКО ЕСЛИ ПРАВА ЕСТЬ) ---
$upload_dir = BASE_DIR . '/uploads/comments/';
$res = $AVE_DB->Query("
SELECT comment_file
FROM " . PREFIX . "_module_comment_info
WHERE (Id = '" . $comment_id . "' OR parent_id = '" . $comment_id . "')
AND comment_file != ''
");
while ($row = $res->FetchAssocArray()) {
$file_path = $upload_dir . $row['comment_file'];
if (file_exists($file_path)) {
@unlink($file_path);
}
}
// --- ШАГ 2. УДАЛЕНИЕ ИЗ БАЗЫ ---
// Удаляем сам коммент
$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");
echo "OK"; // Даем сигнал фронтенду, что всё прошло успешно
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;
$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_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')
{
$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);
$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 . "',
comment_allow_files = '" . (int)$post_allow_files . "',
comment_show_f1 = '" . (int)$post_show_f1 . "',
comment_req_f1 = '" . (int)$post_req_f1 . "',
comment_name_f1 = '" . $clean_name_f1 . "',
comment_show_f2 = '" . (int)$post_show_f2 . "',
comment_req_f2 = '" . (int)$post_req_f2 . "',
comment_name_f2 = '" . $clean_name_f2 . "'
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));
}
}
?>