From 4d4cf34b735720346dcb1fa7740682097d9b9b5f Mon Sep 17 00:00:00 2001 From: Repellent Date: Wed, 24 Dec 2025 21:10:13 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F=20-=20?= =?UTF-8?q?=D1=83=D1=8C=D0=B8=D1=80=D0=B0=D0=B5=D0=BC=20=D1=82=D0=B0=D0=B9?= =?UTF-8?q?=D0=BC=D0=B5=D1=80=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D1=83=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D0=B8=D0=BC=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D1=83=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B5=D1=80=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=20=D0=B8=20?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=BD=D0=B8=D0=BC=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- class/comment.php | 112 +++++++++++++++----------------- js/comment.js | 23 +++++-- templates/comments_tree_sub.tpl | 13 +--- 3 files changed, 72 insertions(+), 76 deletions(-) diff --git a/class/comment.php b/class/comment.php index 69e9f88..272ed27 100644 --- a/class/comment.php +++ b/class/comment.php @@ -100,12 +100,23 @@ class Comment public $_postinfo_tpl = 'comment_info.tpl'; /** - * Настройки времени (в секундах) + * Настройки времени (подгружаются из БД) */ - public $conf_edit_time = 600; // 10 минут на редактирование/удаление - public $conf_cookie_life = 30; // 30 дней жизни куки для анонима + public $conf_edit_time; + public $conf_cookie_life; private $_anon_cookie_name = 'ave_anon_comment_key'; + +/** + * Конструктор класса + * Срабатывает автоматически при создании объекта Comment + */ +function __construct() +{ + // Как только класс создан, мы ПЕРВЫМ ДЕЛОМ лезем в базу за настройками + $this->_commentSettingsGet(); +} + /** * Внутренние методы класса */ @@ -213,14 +224,13 @@ function commentListShow($tpl_dir) $document_id = (int)($_REQUEST['id'] ?? 0); $artpage = $_REQUEST['artpage'] ?? null; $apage = $_REQUEST['apage'] ?? null; - $user_group = UGROUP ?? 0; + $user_group = (int)(UGROUP ?? 0); - // --- НОВАЯ ЛОГИКА: ОПРЕДЕЛЯЕМ ТЕКУЩЕГО ПОЛЬЗОВАТЕЛЯ --- + // --- ОПРЕДЕЛЯЕМ ТЕКУЩЕГО ПОЛЬЗОВАТЕЛЯ --- $current_user_id = (int)($_SESSION['user_id'] ?? 0); $anon_key = $this->_getAnonKey(); - // ----------------------------------------------------- - // Получаем ВСЕ настройки модуля разом + // Получаем ВСЕ настройки модуля разом (из БД) $settings = $this->_commentSettingsGet(); // Проверяем, что в настройках модуля разрешено комментирование @@ -287,6 +297,9 @@ function commentListShow($tpl_dir) $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()) { @@ -299,31 +312,30 @@ function commentListShow($tpl_dir) $row['avatar'] = ''; } - // --- ИСПРАВЛЕННАЯ ЛОГИКА ТАЙМЕРА И ПРАВ --- + // --- ИСПРАВЛЕННАЯ ЛОГИКА ТАЙМЕРА И ПРАВ (УЧЕТ АДМИНА) --- $row['can_edit'] = 0; - $is_admin = ($user_group == 1); + $is_admin = ($user_group === 1); - // Рассчитываем остаток времени (в секундах) - $elapsed = $now - $row['comment_published']; - $time_left = $this->conf_edit_time - $elapsed; - - // Обязательно записываем в массив, чтобы избежать ошибки в шаблоне - $row['edit_time_left'] = ($time_left > 0) ? $time_left : 0; - - // Проверяем авторство (зарегистрированный или аноним по ключу) + // Проверяем авторство $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; - } elseif ($is_author) { - // Автор может править, только если время еще есть - if ($row['edit_time_left'] > 0) { + // Для админа таймер не нужен, ставим 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']); @@ -569,10 +581,6 @@ exit; exit; } -/** - * Метод, предназначенный для редактирования комментария в Публичной части - * с поддержкой анонимных пользователей и ограничением по времени. - */ function commentPostEdit($comment_id) { global $AVE_DB; @@ -581,18 +589,19 @@ function commentPostEdit($comment_id) $comment_id = (int)$comment_id; $user_id = (int)($_SESSION['user_id'] ?? 0); $user_group = (int)(defined('UGROUP') ? UGROUP : 0); - $anon_key = $this->_getAnonKey(); // Наш метод получения куки анонима + $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_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 . "' @@ -604,34 +613,30 @@ function commentPostEdit($comment_id) // 3. Проверка прав (БЕЗОПАСНОСТЬ) $is_admin = ($user_group == 1); - // Проверка на авторство: - // Либо совпадает ID зарегистрированного юзера, - // Либо совпадает anon_key в базе с кукой текущего анонима $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); - // Проверка времени: прошло меньше секунд, чем указано в $this->conf_edit_time + // ИСПРАВЛЕНО: Теперь берем лимит времени ПРЯМО из БД ($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 < $this->conf_edit_time); + $is_time_ok = ($time_passed < $time_limit); // Если не админ, проверяем: автор ли это и не вышло ли время if (!$is_admin) { if (!$is_author) exit('NOT_AUTHOR'); if (!$is_time_ok) { - echo "TIME_EXPIRED"; // Этот ответ поймает JS + echo "TIME_EXPIRED"; exit; } } - // 4. Обработка текста (ТВОИ ОРИГИНАЛЬНЫЕ РЕГУЛЯРКИ) + // 4. Обработка текста (без изменений...) $comment_text = $_POST['text'] ?? ''; - // Декодируем HEX и десятичные сущности (твоя логика) $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); - // Заменяем брейки на переносы строк для корректной работы mb_substr и strip_tags $comment_text = str_replace(array("
\n", "
\n", "
\n", "
", "
"), "\n", $comment_text); $comment_text = strip_tags($comment_text); @@ -639,15 +644,13 @@ function commentPostEdit($comment_id) $comment_text_cut = mb_substr($comment_text, 0, $max); if (mb_strlen($comment_text) > $max) $comment_text_cut .= '…'; - // 5. Работа с изображениями + // 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']); } @@ -659,7 +662,6 @@ function commentPostEdit($comment_id) $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']); @@ -667,12 +669,9 @@ function commentPostEdit($comment_id) $new_file_sql = ", comment_file = ''"; } - // --- ВОТ ЭТО ДОБАВИЛ --- $user_rating = isset($_POST['user_rating']) ? (int)$_POST['user_rating'] : (int)$row['user_rating']; - // ----------------------- // 6. Обновление базы данных - // Если в настройках стоит "нужна премодерация", после правки статус меняется на 0 (если не админ) $new_status = $is_admin ? (int)$row['comment_status'] : ($row['comment_need_approve'] == '1' ? 0 : 1); $AVE_DB->Query(" @@ -687,18 +686,10 @@ function commentPostEdit($comment_id) Id = '" . $comment_id . "' "); - // Возвращаем текст для JS, чтобы он обновил блок без перезагрузки страницы echo htmlspecialchars($comment_text_cut, ENT_QUOTES); exit; } -/** - * Метод, предназначенный для удаления комментария. - * Реализует логику мягкого удаления (затирки) при наличии ответов - * и полную очистку при их отсутствии. - * - * @param int $comment_id - идентификатор комментария - */ function commentPostDelete($comment_id) { global $AVE_DB; @@ -709,6 +700,10 @@ function commentPostDelete($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 @@ -728,7 +723,9 @@ function commentPostDelete($comment_id) } 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'] < $this->conf_edit_time); + + // Теперь $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; @@ -740,7 +737,7 @@ function commentPostDelete($comment_id) die('Доступ запрещен'); } - // --- ШАГ 1. ПРОВЕРКА НАЛИЧИЯ ОТВЕТОВ --- + // --- ШАГ 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/'; @@ -761,20 +758,17 @@ function commentPostDelete($comment_id) else { // --- ВАРИАНТ Б: ПОЛНОЕ УДАЛЕНИЕ (Для админа или если нет детей) --- - // Собираем массив ID для удаления. Сразу кладем туда родителя. $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 = []; // Сбрасываем для следующего уровня + $parent_ids = []; while ($row = $res->FetchAssocArray()) { $all_child_ids[] = (int)$row['Id']; $parent_ids[] = (int)$row['Id']; @@ -783,7 +777,6 @@ function commentPostDelete($comment_id) $ids_to_delete = array_merge($ids_to_delete, $all_child_ids); } - // 1. Удаляем файлы всех комментариев из списка удаления $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()) { @@ -793,7 +786,6 @@ function commentPostDelete($comment_id) } } - // 2. Удаляем все записи из БД одним запросом $AVE_DB->Query("DELETE FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_ids_str)"); echo "OK"; diff --git a/js/comment.js b/js/comment.js index 1147a44..2457907 100644 --- a/js/comment.js +++ b/js/comment.js @@ -21,12 +21,23 @@ var countdown = setInterval(function() { timeLeft--; - if (timeLeft <= 0) { - clearInterval(countdown); - $('#controls_' + cid).fadeOut(300); - $('#timer_container_' + cid).html('Время на правку истекло'); - return; - } +if (timeLeft <= 0) { + clearInterval(countdown); + + // Пытаемся найти блок управления по ID + var $controls = $('#controls_' + cid); + + if ($controls.length) { + // Скрываем кнопки + $controls.fadeOut(300, function() { + $(this).remove(); // Полностью удаляем из DOM для надежности + }); + } + + // Обновляем статус таймера + $('#timer_container_' + cid).html(' Время на правку истекло'); + return; +} var minutes = Math.floor(timeLeft / 60); var seconds = timeLeft % 60; $timer.text(minutes + ':' + (seconds < 10 ? '0' : '') + seconds); diff --git a/templates/comments_tree_sub.tpl b/templates/comments_tree_sub.tpl index 2d16208..f556435 100644 --- a/templates/comments_tree_sub.tpl +++ b/templates/comments_tree_sub.tpl @@ -1,5 +1,4 @@ {foreach from=$subcomments item=c} -
{if isset($smarty.request.subaction) && $smarty.request.subaction=='showonly' && isset($smarty.request.comment_id) && $smarty.request.comment_id==$c.Id} @@ -7,7 +6,6 @@ {/if}
-
{* ----- БЛОК АВАТАРА ----- *} @@ -23,9 +21,7 @@
{* Информация об авторе и дате *}
- {#COMMENT_USER_ADD#} {$c.comment_author_name|stripslashes|escape} - {$c.comment_published} {if $comment_show_f1 == 1 && $c.comment_author_website} @@ -86,11 +82,10 @@
{/if} - {* 2. Общий рейтинг комментария (лайки/звезды для голосования) *} + {* 2. Общий рейтинг комментария *} {if $comment_rating_type != 2}
{if $comment_rating_type == 1} - {* Лайки *}
@@ -98,7 +93,6 @@ {$c.rating_count} {/if} {else} - {* Звезды для голосования *}
{assign var="avg_rating" value=0} {if isset($c.rating_count) && $c.rating_count > 0} @@ -115,8 +109,8 @@
{/if} - {* 3. Таймер редактирования *} - {if $c.can_edit && isset($c.edit_time_left) && $c.edit_time_left > 0} + {* 3. ТАЙМЕР РЕДАКТИРОВАНИЯ (Добавлена проверка на UGROUP != 1) *} + {if $smarty.const.UGROUP != 1 && $c.can_edit && isset($c.edit_time_left) && $c.edit_time_left > 0}
@@ -153,7 +147,6 @@ {/if}
-