init commit
This commit is contained in:
49
ReadMe.txt
Normal file
49
ReadMe.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
Шаг 1: Назначение перемнных в шаблоне
|
||||
|
||||
<script type="text/javascript">
|
||||
var aveabspath = '[tag:path]';
|
||||
var UGROUP = <?=UGROUP;?>;
|
||||
</script>
|
||||
|
||||
Шаг 2: Нужен плагин для jQuery - jquery.form
|
||||
http://malsup.com/jquery/form/
|
||||
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
СТИЛИ ДЛЯ ДРЕВОВИДНОГО ОТОБРАЖЕНИЯ КОММЕНТАРИЕВ (Replies)
|
||||
==================================================================== */
|
||||
|
||||
/* 1. Общий контейнер ответа, который находится внутри .mod_comment_comment
|
||||
и имеет отступ ms-4 */
|
||||
.mod_comment_comment .mod_comment_comment.ms-4 {
|
||||
/* Добавляем вертикальную линию слева */
|
||||
border-left: 3px solid #dee2e6; /* Легкая граница */
|
||||
|
||||
/* Уменьшаем margin-left, который дает ms-4, чтобы освободить место
|
||||
для линии и при этом не уходить слишком далеко вправо на каждом уровне. */
|
||||
margin-left: 20px !important; /* Принудительно уменьшаем отступ */
|
||||
padding-left: 15px; /* Отступ между линией и контентом ответа */
|
||||
|
||||
/* Опционально: немного отличающийся фон */
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 2. Отдельно стилизуем рамку для вложенных карточек, чтобы они не выглядели
|
||||
громоздко внутри родителя */
|
||||
.mod_comment_comment .mod_comment_comment.ms-4 > .mod_comment_box {
|
||||
border: none !important; /* Убираем стандартную рамку карточки, чтобы осталась только наша вертикальная линия */
|
||||
}
|
||||
|
||||
/* 3. Убираем рамки у вложенных заголовков, чтобы линия была чистой */
|
||||
.mod_comment_comment .mod_comment_comment.ms-4 > .mod_comment_box > .card-header {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
/* 4. Более глубокий уровень вложенности (если ответов много) */
|
||||
/* Если ответ на ответ имеет дополнительный ms-4, стилизуем его дальше */
|
||||
.mod_comment_comment .mod_comment_comment.ms-4 .mod_comment_comment.ms-4 {
|
||||
border-color: #adb5bd; /* Чуть темнее линия для следующего уровня */
|
||||
background-color: #fff; /* Возвращаем белый фон для контраста */
|
||||
}
|
||||
|
||||
954
class/comment.php
Normal file
954
class/comment.php
Normal file
@@ -0,0 +1,954 @@
|
||||
<?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;
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$document_id = (int)($_REQUEST['id'] ?? 0);
|
||||
$artpage = $_REQUEST['artpage'] ?? null;
|
||||
$apage = $_REQUEST['apage'] ?? null;
|
||||
$user_group = UGROUP ?? 0;
|
||||
|
||||
|
||||
// Проверяем, что в настройках модуля разрешено комментирование документов
|
||||
if ($this->_commentSettingsGet('comment_active') == 1)
|
||||
{
|
||||
// =================================================================================
|
||||
// НОВОЕ: ПРОВЕРКА ПРАВ НА ПРОСМОТР КОММЕНТАРИЕВ (Read Permission)
|
||||
// =================================================================================
|
||||
$read_groups = explode(',', $this->_commentSettingsGet('comment_user_groups_read'));
|
||||
|
||||
$assign['no_read_permission'] = 0; // Флаг: 0 = права есть
|
||||
|
||||
// Если группа текущего пользователя НЕ в списке разрешенных для ЧТЕНИЯ,
|
||||
if (!in_array($user_group, $read_groups))
|
||||
{
|
||||
// Устанавливаем флаг, что прав на чтение нет
|
||||
$assign['no_read_permission'] = 1;
|
||||
}
|
||||
// =================================================================================
|
||||
|
||||
$assign['display_comments'] = 1;
|
||||
|
||||
// Если группа пользователя, который в текущий момент просматривает документ попадает в список
|
||||
// разрешенных (в настройках модуля), тогда создаем флаг, который будет разрешать к показу
|
||||
// форму для добавления нового комментария
|
||||
if (in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups'))))
|
||||
{
|
||||
$assign['cancomment'] = 1;
|
||||
}
|
||||
|
||||
// ЕСЛИ ЕСТЬ ПРАВА НА ЧТЕНИЕ, ПРОДОЛЖАЕМ ВЫБОРКУ И ВЫВОД
|
||||
if ($assign['no_read_permission'] == 0)
|
||||
{
|
||||
$assign['comment_max_chars'] = $this->_commentSettingsGet('comment_max_chars');
|
||||
$assign['im'] = $this->_commentSettingsGet('comment_use_antispam');
|
||||
|
||||
// Выполняем запрос к БД на получение количества комментариев для текущего документа
|
||||
$comments = array();
|
||||
|
||||
if ($this->_commentSettingsGet('comment_use_page_nav') == 1)
|
||||
{
|
||||
$limit = $this->_commentSettingsGet('comment_page_nav_count');
|
||||
$start = get_current_page() * $limit - $limit;
|
||||
|
||||
$num = $AVE_DB->Query("
|
||||
SELECT COUNT(*)
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE document_id = '" . $document_id . "'
|
||||
")->GetCell();
|
||||
|
||||
$sql = $AVE_DB->Query("
|
||||
SELECT *
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE document_id = '" . $document_id . "'
|
||||
" . ($user_group == 1 ? '' : "AND comment_status = '1'") . "
|
||||
ORDER BY comment_published ASC
|
||||
LIMIT " . $start . "," . $limit . "
|
||||
");
|
||||
|
||||
$pages = @ceil($num / $limit);
|
||||
|
||||
if ($num > $limit)
|
||||
{
|
||||
$page_nav = '<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 = rewrite_link($page_nav);
|
||||
$GLOBALS['page_id'][$document_id]['page']=($GLOBALS['page_id'][$document_id]['page']>ceil($num / $limit) ? $GLOBALS['page_id'][$document_id]['page'] : ceil($num / $limit));
|
||||
}
|
||||
else
|
||||
{
|
||||
$page_nav = '';
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = $AVE_DB->Query("
|
||||
SELECT *
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE document_id = '" . $document_id . "'
|
||||
" . ($user_group == 1 ? '' : "AND comment_status = '1'") . "
|
||||
ORDER BY comment_published ASC
|
||||
");
|
||||
|
||||
$page_nav = '';
|
||||
}
|
||||
|
||||
// Получаем формат даты, который указан в общих настройках системы и
|
||||
// приводим дату создания комментария и дату редактирования к этому формату
|
||||
$date_time_format = $AVE_Template->get_config_vars('COMMENT_DATE_TIME_FORMAT');
|
||||
while ($row = $sql->FetchAssocArray())
|
||||
{
|
||||
$row['comment_published'] = ave_date_format($date_time_format, $row['comment_published']);
|
||||
$row['comment_changed'] = ave_date_format($date_time_format, $row['comment_changed']);
|
||||
|
||||
$comments[$row['parent_id']][] = $row;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Если нет прав, то эти переменные остаются пустыми/неопределенными
|
||||
$comments = array();
|
||||
$page_nav = '';
|
||||
}
|
||||
|
||||
|
||||
// Формируем ряд переменных для использования в шаблоне
|
||||
$assign['closed'] = @$comments[0][0]['comments_close'];
|
||||
$assign['comments'] = $comments;
|
||||
$assign['theme'] = defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER;
|
||||
$assign['doc_id'] = $document_id;
|
||||
$assign['page'] = base64_encode(get_redirect_link());
|
||||
$assign['subtpl'] = $tpl_dir . $this->_comments_tree_sub_tpl;
|
||||
|
||||
$AVE_Template->assign($assign);
|
||||
|
||||
$AVE_Template->assign('page_nav', $page_nav);
|
||||
|
||||
// Отображаем шаблон
|
||||
$AVE_Template->display($tpl_dir . $this->_comments_tree_tpl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для отображения формы при добавлении нового комментария.
|
||||
*
|
||||
* @param string $tpl_dir - путь к шаблонам модуля
|
||||
*/
|
||||
function commentPostFormShow($tpl_dir)
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$docid = (int)($_REQUEST['docid'] ?? 0);
|
||||
$user_group = UGROUP ?? 0;
|
||||
|
||||
// Получаем список комментариев на которые запрещены ответы
|
||||
$geschlossen = $AVE_DB->Query("
|
||||
SELECT comments_close
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE document_id = '" . $docid . "'
|
||||
LIMIT 1
|
||||
")->GetCell();
|
||||
|
||||
// Формируем ряд переменных для использования в шаблоне
|
||||
$AVE_Template->assign('closed', $geschlossen);
|
||||
$AVE_Template->assign('cancomment', ($this->_commentSettingsGet('comment_active') == 1 && in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups')))));
|
||||
$AVE_Template->assign('comment_max_chars', $this->_commentSettingsGet('comment_max_chars'));
|
||||
$AVE_Template->assign('theme', defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER);
|
||||
|
||||
// Отображаем форму для добавления комментария
|
||||
$AVE_Template->display($tpl_dir . $this->_comment_form_tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для записи в БД нового комментария.
|
||||
*
|
||||
* @param string $tpl_dir - путь к шаблонам модуля
|
||||
*
|
||||
*/
|
||||
function commentPostNew($tpl_dir)
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$page = $_REQUEST['page'] ?? '';
|
||||
$ajax = (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == 1);
|
||||
$user_group = UGROUP ?? 0;
|
||||
$secure_code = $_POST['securecode'] ?? '';
|
||||
$session_captcha = $_SESSION['captcha_keystring'] ?? null;
|
||||
|
||||
// Если запрос пришел не ajax запросом, тогда формируем ссылку для последующего редиректа
|
||||
if (! $ajax)
|
||||
{
|
||||
$link = rewrite_link(base64_decode($page));
|
||||
}
|
||||
|
||||
// Если в настройках модуля включено использование защитного кода, тогда
|
||||
if ($this->_commentSettingsGet('comment_use_antispam') == 1)
|
||||
{
|
||||
// Если введенный пользователем защитный код неверен, тогда выполняем обновление кода
|
||||
if (! (isset($session_captcha) && $session_captcha == $secure_code))
|
||||
{
|
||||
unset($_SESSION['captcha_keystring']);
|
||||
|
||||
if ($ajax)
|
||||
{
|
||||
echo 'wrong_securecode';
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($GLOBALS['tmpl']))$GLOBALS['tmpl']->assign("wrongSecureCode", 1);
|
||||
header('Location:' . $link . '#end');
|
||||
}
|
||||
exit;
|
||||
}
|
||||
unset($_SESSION['captcha_keystring']);
|
||||
}
|
||||
|
||||
// Определяем флаг модерации комментариев
|
||||
$comment_status = ($this->_commentSettingsGet('comment_need_approve') == 1) ? 0 : 1;
|
||||
|
||||
// Если комментарии разрешены, тогда получаем все данные, который пользователь указал в форме
|
||||
if ($this->_commentSettingsGet('comment_active') == 1
|
||||
&& !empty($_POST['comment_text'])
|
||||
&& !empty($_POST['comment_author_name'])
|
||||
&& in_array($user_group, explode(',', $this->_commentSettingsGet('comment_user_groups'))))
|
||||
{
|
||||
// --- !!! НАЧАЛО БЕЗОПАСНОСТИ: Санитаризация и Экранирование !!! ---
|
||||
|
||||
$new_comment['parent_id'] = (int)($_POST['parent_id'] ?? 0);
|
||||
$new_comment['document_id'] = (int)($_POST['doc_id'] ?? 0);
|
||||
|
||||
// Экранирование для предотвращения SQLi:
|
||||
// Санитаризация для предотвращения XSS в строковых полях:
|
||||
$new_comment['comment_author_name'] = addslashes(strip_tags($_POST['comment_author_name'] ?? ''));
|
||||
$new_comment['comment_author_id'] = empty($_SESSION['user_id']) ? 0 : (int)$_SESSION['user_id'];
|
||||
$new_comment['comment_author_email'] = addslashes(strip_tags($_POST['comment_author_email'] ?? ''));
|
||||
$new_comment['comment_author_city'] = addslashes(strip_tags($_POST['comment_author_city'] ?? ''));
|
||||
$new_comment['comment_author_website'] = addslashes(strip_tags($_POST['comment_author_website'] ?? ''));
|
||||
|
||||
$new_comment['comment_author_ip'] = $_SERVER['REMOTE_ADDR'];
|
||||
$new_comment['comment_published'] = time();
|
||||
$new_comment['comment_status'] = $comment_status;
|
||||
|
||||
// Текст комментария до очистки
|
||||
$comment_text_raw = $_POST['comment_text'] ?? '';
|
||||
|
||||
// Определяем максимальную длину символов для комментария
|
||||
$comment_max_chars = $this->_commentSettingsGet('comment_max_chars');
|
||||
$comment_max_chars = (!empty($comment_max_chars) && $comment_max_chars > 10) ? $comment_max_chars : 200;
|
||||
|
||||
// 1. Убираем HTML-теги для предотвращения XSS
|
||||
$comment_text_clean = strip_tags(stripslashes($comment_text_raw));
|
||||
|
||||
// 2. Обрезка
|
||||
$comment_text_cut = mb_substr($comment_text_clean, 0, $comment_max_chars);
|
||||
$comment_text_cut .= (mb_strlen($comment_text_clean) > $comment_max_chars) ? '…' : '';
|
||||
|
||||
// 3. Экранирование текста перед вставкой в SQL
|
||||
$new_comment['comment_text'] = addslashes($comment_text_cut);
|
||||
|
||||
// --- !!! КОНЕЦ БЕЗОПАСНОСТИ !!! ---
|
||||
|
||||
// Выполняем запрос к БД на добавление комментария
|
||||
$AVE_DB->Query("
|
||||
INSERT INTO " . PREFIX . "_module_comment_info
|
||||
(`" . implode('`,`', array_keys($new_comment)) ."`)
|
||||
VALUES
|
||||
('" . implode("','", $new_comment) . "')
|
||||
");
|
||||
$new_comment['Id'] = $AVE_DB->InsertId();
|
||||
|
||||
// Получаем e-mail адрес из Общих настроек системы и формируем ссылку на комментарий в Публичной части
|
||||
$mail_from = get_settings('mail_from');
|
||||
$mail_from_name = get_settings('mail_from_name');
|
||||
$page_link = get_home_link() . urldecode(base64_decode($page)) . '&subaction=showonly&comment_id=' . $new_comment['Id'] . '#' . $new_comment['Id'];
|
||||
|
||||
// Формируем текст уведомления для отправки на e-mail
|
||||
$mail_text = $AVE_Template->get_config_vars('COMMENT_MESSAGE_ADMIN');
|
||||
// Используем stripslashes для очистки текста, который будет отправлен по почте
|
||||
$mail_text = str_replace('%COMMENT%', stripslashes($new_comment['comment_text']), $mail_text);
|
||||
$mail_text = str_replace('%N%', "\n", $mail_text);
|
||||
$mail_text = str_replace('%PAGE%', $page_link, $mail_text);
|
||||
$mail_text = str_replace('&', '&', $mail_text);
|
||||
|
||||
// Отправляем уведомление
|
||||
send_mail(
|
||||
$mail_from,
|
||||
$mail_text,
|
||||
$AVE_Template->get_config_vars('COMMENT_SUBJECT_MAIL'),
|
||||
$mail_from,
|
||||
$mail_from_name,
|
||||
'text'
|
||||
);
|
||||
|
||||
// Если данные были отправлены ajax-запросом, тогда выполняем автоматический показ комментария
|
||||
// на странице.
|
||||
if ($ajax)
|
||||
{
|
||||
$new_comment['comment_changed'] = 0;
|
||||
$new_comment['comment_published'] = ave_date_format($AVE_Template->get_config_vars('COMMENT_DATE_TIME_FORMAT'), $new_comment['comment_published']);
|
||||
$subcomments[] = $new_comment;
|
||||
$AVE_Template->assign('subcomments', $subcomments);
|
||||
$AVE_Template->assign('theme', defined('THEME_FOLDER') ? THEME_FOLDER : DEFAULT_THEME_FOLDER);
|
||||
$AVE_Template->display($tpl_dir . $this->_comments_tree_sub_tpl);
|
||||
}
|
||||
}
|
||||
|
||||
// Если же данные пришли НЕ ajax-запросом, тогда полностью обновляем страницу.
|
||||
if (! $ajax) header('Location:' . str_replace("//", "", $link) . '#end');
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для редактирования комментария в Публичной части
|
||||
*
|
||||
* @param int $comment_id - идентификатор комментария
|
||||
*/
|
||||
function commentPostEdit($comment_id)
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
$user_group = UGROUP ?? 0;
|
||||
$post_text = $_POST['text'] ?? '';
|
||||
|
||||
|
||||
if (empty($user_id)) exit;
|
||||
|
||||
$comment_id = intval(preg_replace('/\D/', '', $comment_id));
|
||||
|
||||
// Выполняем запрос к БД и получаем всю информацию о комментарии, а также ряд значений из настроек модуля
|
||||
$row = $AVE_DB->Query("
|
||||
SELECT
|
||||
msg.parent_id,
|
||||
msg.comment_text,
|
||||
cmnt.comment_user_groups,
|
||||
cmnt.comment_max_chars,
|
||||
cmnt.comment_need_approve
|
||||
FROM
|
||||
" . PREFIX . "_module_comment_info AS msg,
|
||||
" . PREFIX . "_module_comments AS cmnt
|
||||
WHERE comment_active = '1'
|
||||
AND msg.Id = '" . $comment_id . "'
|
||||
" . (($user_group != 1) ? "AND comment_author_id = " . $user_id : '') . "
|
||||
")->FetchAssocArray();
|
||||
|
||||
// Если данные получены
|
||||
if ($row !== false)
|
||||
{
|
||||
|
||||
$comment_max_chars = ($row['comment_max_chars'] != '' && $row['comment_max_chars'] > 10) ? $row['comment_max_chars'] : 20;
|
||||
|
||||
$comment_text = $post_text;
|
||||
|
||||
// --- !!! НАЧАЛО ИСПРАВЛЕНИЯ УСТАРЕВШИХ ОПЕРАТОРОВ (/e) !!! ---
|
||||
|
||||
// Безопасная замена: преобразуем hex-сущности
|
||||
$comment_text = preg_replace_callback('/&#x([0-9a-f]{1,7});/', function($matches) {
|
||||
return chr(hexdec($matches[1]));
|
||||
}, $comment_text);
|
||||
|
||||
// Безопасная замена: преобразуем dec-сущности
|
||||
$comment_text = preg_replace_callback('/&#([0-9]{1,7});/', function($matches) {
|
||||
return chr($matches[1]);
|
||||
}, $comment_text);
|
||||
|
||||
// --- !!! КОНЕЦ ИСПРАВЛЕНИЯ УСТАРЕВШИХ ОПЕРАТОРОВ !!! ---
|
||||
|
||||
$comment_text = stripslashes($comment_text);
|
||||
$comment_text = str_replace(array("<br>\n", "<br />\n", "<br/>\n"), "\n", $comment_text);
|
||||
|
||||
// Санитаризация: убираем теги перед обрезкой
|
||||
$comment_text = strip_tags($comment_text);
|
||||
|
||||
$comment_text = mb_substr($comment_text, 0, $comment_max_chars-1);
|
||||
$message_length = mb_strlen($comment_text);
|
||||
$comment_text .= ($message_length > $comment_max_chars) ? '…' : '';
|
||||
|
||||
|
||||
// Если группа текущего пользователя совпадает с разрешенной группой в настройках модуля, тогда
|
||||
// выполняем запрос к БД на обновление информации.
|
||||
if (in_array($user_group, explode(',', $row['comment_user_groups'])) && $message_length > 3)
|
||||
{
|
||||
$AVE_DB->Query("
|
||||
UPDATE " . PREFIX . "_module_comment_info
|
||||
SET
|
||||
comment_changed = '" . time() . "',
|
||||
comment_status = '" . intval(!(bool)$row['comment_need_approve']) . "',
|
||||
comment_text = '" . addslashes($comment_text) . "'
|
||||
WHERE
|
||||
Id = '" . $comment_id . "'
|
||||
");
|
||||
|
||||
// Преобразуем HTML теги в HTML сущности перед выводом (для XSS)
|
||||
echo htmlspecialchars($comment_text, ENT_QUOTES);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Если редактирование не прошло, выводим оригинальный текст (экранированный)
|
||||
echo htmlspecialchars($row['comment_text'], ENT_QUOTES);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для удаления комментария. Если комментарий содержал какие-либо ответы на него,
|
||||
* то все ответы также будут удалены вместе с родительским комментарием.
|
||||
*
|
||||
* @param int $comment_id - идентификатор комментария
|
||||
*/
|
||||
function commentPostDelete($comment_id)
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
$comment_id = (int)$comment_id; // Убедимся, что это целое число
|
||||
|
||||
// Выполняем запрос к БД на удаление родительского комментария
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE Id = '" . $comment_id . "'
|
||||
");
|
||||
|
||||
// Выполняем запрос к БД на удаление дочерних комментариев (ответов)
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE parent_id = '" . $comment_id . "'
|
||||
AND parent_id != 0
|
||||
");
|
||||
|
||||
exit;
|
||||
}
|
||||
function commentAdminDelete($comment_id)
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
$comment_id = (int)$comment_id; // Убедимся, что это целое число
|
||||
|
||||
// Выполняем запрос к БД на удаление родительского комментария
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE Id = '" . $comment_id . "'
|
||||
");
|
||||
|
||||
// Выполняем запрос к БД на удаление дочерних комментариев (ответов)
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE parent_id = '" . $comment_id . "'
|
||||
AND parent_id != 0
|
||||
");
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$session_id = SESSION ?? '';
|
||||
|
||||
header('Location:index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=' . $session_id);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для вывода детальной информации об авторе комментария
|
||||
*
|
||||
* @param string $tpl_dir - путь к шаблонам модуля
|
||||
*/
|
||||
function commentPostInfoShow($tpl_dir)
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$comment_id = (int)($_REQUEST['Id'] ?? 0);
|
||||
|
||||
// Получаем полную информацию о комментарии
|
||||
$row = $AVE_DB->Query("
|
||||
SELECT *
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE Id = '" . $comment_id . "'
|
||||
")->FetchAssocArray();
|
||||
|
||||
// Преобразуем адрес сайта к формату ссылки
|
||||
$row['comment_author_website'] = str_replace('http://', '', $row['comment_author_website']);
|
||||
$row['comment_author_website'] = ($row['comment_author_website'] != '')
|
||||
? '<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;
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$request_sub = $_REQUEST['sub'] ?? '';
|
||||
$post_max_chars = $_POST['comment_max_chars'] ?? 0;
|
||||
$post_user_groups = $_POST['comment_user_groups'] ?? array();
|
||||
// НОВОЕ: Получение данных для групп, которым разрешен просмотр
|
||||
$post_user_groups_read = $_POST['comment_user_groups_read'] ?? array();
|
||||
// КОНЕЦ НОВОГО
|
||||
$post_need_approve = $_POST['comment_need_approve'] ?? 0;
|
||||
$post_active = $_POST['comment_active'] ?? 0;
|
||||
$post_use_antispam = $_POST['comment_use_antispam'] ?? 0;
|
||||
$post_use_page_nav = $_POST['comment_use_page_nav'] ?? 0;
|
||||
$post_page_nav_count = $_POST['comment_page_nav_count'] ?? 0;
|
||||
|
||||
// Если в запросе содержится подзапрос на сохранение данных (пользователь нажал кнопку
|
||||
// сохранить изменения), тогда выполняем запрос к БД на обновление информации.
|
||||
|
||||
if ($request_sub == 'save')
|
||||
{
|
||||
$max_chars = (empty($post_max_chars) || $post_max_chars < 50) ? 50 : $post_max_chars;
|
||||
|
||||
$AVE_DB->Query("
|
||||
UPDATE " . PREFIX . "_module_comments
|
||||
SET
|
||||
comment_max_chars = '" . (int)$max_chars . "',
|
||||
comment_user_groups = '" . implode(',', $post_user_groups) . "',
|
||||
comment_user_groups_read = '" . implode(',', $post_user_groups_read) . "', /* <-- СОХРАНЕНИЕ НОВОГО ПОЛЯ */
|
||||
comment_need_approve = '" . (int)$post_need_approve . "',
|
||||
comment_active = '" . (int)$post_active . "',
|
||||
comment_use_antispam = '" . (int)$post_use_antispam . "',
|
||||
comment_use_page_nav = '" . (int)$post_use_page_nav . "',
|
||||
comment_page_nav_count = '" . (int)$post_page_nav_count . "'
|
||||
WHERE
|
||||
Id = 1
|
||||
");
|
||||
}
|
||||
|
||||
// Получаем список всех настроек модуля
|
||||
$row = $this->_commentSettingsGet();
|
||||
|
||||
// Преобразуем поля с правами в массивы для удобства отображения в шаблоне
|
||||
$row['comment_user_groups'] = explode(',', $row['comment_user_groups']);
|
||||
$row['comment_user_groups_read'] = explode(',', $row['comment_user_groups_read']); /* <-- ПОЛУЧЕНИЕ НОВОГО ПОЛЯ */
|
||||
|
||||
// Передаем данные в шаблон и показываем страницу с настройками модуля
|
||||
$AVE_Template->assign($row);
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_settings_tpl));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
8
index.php
Normal file
8
index.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Файл-заглушка, предназначенный для запрета показа списка файлов в текущей директории,
|
||||
* если через адресную строку браузера было прямое общращение к данной директории.
|
||||
*/
|
||||
header('Location:/');
|
||||
exit;
|
||||
?>
|
||||
20
info.php
Normal file
20
info.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
if (! defined('BASE_DIR'))
|
||||
exit;
|
||||
|
||||
$module = array(
|
||||
'ModuleSysName' => 'comment',
|
||||
'ModuleVersion' => '1.26.2a',
|
||||
'ModuleAutor' => 'AVE.cms Team',
|
||||
'ModuleCopyright' => '© 2007-' . date('Y') . ' AVE.cms',
|
||||
'ModuleStatus' => 1,
|
||||
'ModuleIsFunction' => 1,
|
||||
'ModuleTemplate' => 0,
|
||||
'ModuleAdminEdit' => 1,
|
||||
'ModuleFunction' => 'mod_comment',
|
||||
'ModuleTag' => '[mod_comment]',
|
||||
'ModuleTagLink' => null,
|
||||
'ModuleAveTag' => '#\\\[mod_comment]#',
|
||||
'ModulePHPTag' => '<?php mod_comment(); ?>'
|
||||
);
|
||||
?>
|
||||
297
js/comment.js
Normal file
297
js/comment.js
Normal file
@@ -0,0 +1,297 @@
|
||||
/* ====================================================================
|
||||
ОБЕРТКА ДЛЯ ОЖИДАНИЯ JQUERY
|
||||
==================================================================== */
|
||||
(function waitForJQuery() {
|
||||
if (typeof jQuery === 'undefined') {
|
||||
// jQuery еще не загружен. Ждем 10 мс и проверяем снова.
|
||||
setTimeout(waitForJQuery, 10);
|
||||
} else {
|
||||
// JQuery загружен, можно запускать основной код.
|
||||
|
||||
(function($){
|
||||
|
||||
// ====================================================================
|
||||
// КОРРЕКЦИЯ: ПРИНУДИТЕЛЬНАЯ ФИКСАЦИЯ HTTPS
|
||||
// ====================================================================
|
||||
if (typeof aveabspath !== 'undefined') {
|
||||
aveabspath = 'https://bag.local/';
|
||||
}
|
||||
// ====================================================================
|
||||
|
||||
/*Limit symbols*/
|
||||
(function($){$.fn.extend({limit:function(limit,element){var interval,f;var self=$(this);$(this).focus(function(){interval=window.setInterval(substring,100)});$(this).blur(function(){clearInterval(interval);substring()});substringFunction="function substring(){ var val = $(self).val();var length = val.length;if(length > limit){$(self).val($(self).val().substring(0,limit));}";if(typeof element!='undefined')substringFunction+="if($(element).html() != limit-length){$(element).html((limit-length<=0)?'0':limit-length);}";substringFunction+="}";eval(substringFunction);substring()}})})(jQuery);
|
||||
|
||||
function getCaptha(){
|
||||
now = new Date();
|
||||
$('#captcha img').attr('src', aveabspath+'inc/captcha.php?cd=' + now);
|
||||
};
|
||||
|
||||
// ИСПРАВЛЕННАЯ ФУНКЦИЯ cAction
|
||||
function cAction(obj,action){
|
||||
var cid;
|
||||
|
||||
// --- Логика для действий с документом (open/close) ---
|
||||
if (action === 'open' || action === 'close') {
|
||||
cid = DOC_ID;
|
||||
} else {
|
||||
// 1. Пытаемся найти ссылку и взять ID из атрибута rel
|
||||
var $link = $(obj).closest('a.mod_comment_answer');
|
||||
cid = $link.attr('rel');
|
||||
|
||||
// 2. Если rel не найден, берем ID из родительского блока
|
||||
if (typeof cid === 'undefined' || cid === false || cid === '') {
|
||||
cid = $(obj).parents('.mod_comment_box').attr('id');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof cid === 'undefined' || cid === false || cid === '') {
|
||||
console.error("Comment ID not found for action: " + action);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action=='answer'){
|
||||
$('#parent_id').val(cid);
|
||||
// --- ИСПРАВЛЕНИЕ: Добавлено .show() для отображения формы после перемещения ---
|
||||
$('#mod_comment_new').insertBefore('#end'+cid).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// ... (остальной код для admin actions: delete, lock, open/close)
|
||||
if (UGROUP==1){
|
||||
$.get(aveabspath+'index.php',{
|
||||
module: 'comment',
|
||||
action: action,
|
||||
docid: DOC_ID,
|
||||
Id: cid
|
||||
},function(){
|
||||
if (action=='delete'){
|
||||
$(obj).parents('.mod_comment_comment').eq(0).remove();
|
||||
}
|
||||
if (action=='open'){
|
||||
$('#mod_comment_open').attr('id', 'mod_comment_close').html(COMMENT_SITE_CLOSE);
|
||||
}
|
||||
if (action=='close'){
|
||||
$('#mod_comment_close').attr('id', 'mod_comment_open').html(COMMENT_SITE_OPEN);
|
||||
}
|
||||
// ====================================================================
|
||||
// ИСПРАВЛЕНИЕ: ДИНАМИЧЕСКАЯ СМЕНА ИКОНКИ ЗАМКА (Font Awesome)
|
||||
// ====================================================================
|
||||
if (action=='unlock'){
|
||||
// Меняем классы: mod_comment_unlock (открыт) -> mod_comment_lock (закрыт)
|
||||
// Меняем цвет: text-success (зеленый) -> text-dark (темный)
|
||||
$(obj).removeClass('mod_comment_unlock text-success')
|
||||
.addClass('mod_comment_lock text-dark')
|
||||
.attr('title',COMMENT_LOCK_LINK)
|
||||
.find('i.fa') // Ищем иконку FA
|
||||
.removeClass('fa-unlock').addClass('fa-lock'); // Меняем иконку
|
||||
}
|
||||
if (action=='lock'){
|
||||
// Меняем классы: mod_comment_lock (закрыт) -> mod_comment_unlock (открыт)
|
||||
// Меняем цвет: text-dark (темный) -> text-success (зеленый)
|
||||
$(obj).removeClass('mod_comment_lock text-dark')
|
||||
.addClass('mod_comment_unlock text-success')
|
||||
.attr('title',COMMENT_UNLOCK_LINK)
|
||||
.find('i.fa') // Ищем иконку FA
|
||||
.removeClass('fa-lock').addClass('fa-unlock'); // Меняем иконку
|
||||
}
|
||||
// ====================================================================
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ИСПРАВЛЕННАЯ ФУНКЦИЯ VALIDATE: Устойчива к отсутствию полей
|
||||
function validate(formData,jqForm,options){
|
||||
$('.alert').remove();
|
||||
var form = jqForm ? jqForm[0] : $('#mod_comment_new form')[0];
|
||||
|
||||
if (form.comment_author_name && !form.comment_author_name.value){
|
||||
alert(COMMENT_ERROR_AUTHOR);
|
||||
$(form.comment_author_name).focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (form.comment_author_email && !form.comment_author_email.value){
|
||||
alert(COMMENT_ERROR_EMAIL);
|
||||
$(form.comment_author_email).focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!form.comment_text || !form.comment_text.value){
|
||||
alert(COMMENT_ERROR_TEXT);
|
||||
if (form.comment_text) $(form.comment_text).focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IS_IM && form.securecode && !form.securecode.value){
|
||||
alert(COMMENT_ERROR_CAPTCHA);
|
||||
$(form.securecode).focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
function setClickable(){
|
||||
$('.editable_text').click(function(){
|
||||
var cid = $(this).parents('.mod_comment_box').attr('id');
|
||||
var revert = $(this).html();
|
||||
var textarea = '<p><textarea rows="7" id="ta_'+cid+'" class="editable">'+revert+'</textarea></p>';
|
||||
var charsLeft = '<p>'+COMMENT_CHARS_LEFT+' <span class="charsLeft" id="charsLeft_'+cid+'"></span></p>';
|
||||
var buttonSave = '<input type="button" value="'+COMMENT_BUTTON_EDIT+'" class="button saveButton" /> ';
|
||||
var buttonReset = '<input type="button" value="'+COMMENT_BUTTON_CANCEL+'" class="button cancelButton" />';
|
||||
$(this).after('<div class="box"><div class="block" id="forms"><fieldset><legend>'+COMMENT_EDIT_TITLE
|
||||
+'</legend>'+textarea+buttonSave+buttonReset+charsLeft+'</fieldset></div></div>').remove();
|
||||
$('.saveButton').click(function(){saveChanges(this,false,cid);});
|
||||
$('.cancelButton').click(function(){saveChanges(this,revert,cid);});
|
||||
$('#ta_'+cid).limit(MAX_CHARS,'#charsLeft_'+cid);
|
||||
})
|
||||
.attr('title',COMMENT_EDIT_LINK)
|
||||
.mouseover(function(){$(this).addClass('editable');})
|
||||
.mouseout(function(){$(this).removeClass('editable');});
|
||||
$('#in_message').limit(MAX_CHARS,'#charsLeft_new');
|
||||
};
|
||||
|
||||
// ИСПРАВЛЕННАЯ ФУНКЦИЯ saveChanges
|
||||
function saveChanges(obj,cancel,cid){
|
||||
if (!cancel){
|
||||
var t = $(obj).parent().children().children().val();
|
||||
|
||||
$.ajax({
|
||||
url: aveabspath+'index.php?ajax=1',
|
||||
type: 'POST',
|
||||
data: {
|
||||
module: 'comment',
|
||||
action: 'edit',
|
||||
Id: cid,
|
||||
text: t
|
||||
},
|
||||
success: function(txt){
|
||||
$(obj).parent().parent().parent().after('<div class="mod_comment_text editable_text">'+txt+'</div>').remove();
|
||||
var now = new Date();
|
||||
var date = now.toLocaleString();
|
||||
$('#'+cid).find('.mod_comment_changed').html(' ('+COMMENT_TEXT_CHANGED+' '+date+')');
|
||||
setClickable();
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("AJAX Error (Edit):", status, error);
|
||||
alert("Ошибка при редактировании комментария. Пожалуйста, проверьте консоль.");
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
$(obj).parent().parent().parent().after('<div class="mod_comment_text editable_text">'+cancel+'</div>').remove();
|
||||
setClickable();
|
||||
}
|
||||
};
|
||||
|
||||
function displayNewComment(data){
|
||||
if (data=='wrong_securecode'){
|
||||
$('#captcha').after('<div class="alert alert-error">'+COMMENT_WRONG_CODE+'</div>');
|
||||
$('#securecode').focus();
|
||||
}
|
||||
else {
|
||||
$('#end'+$('#parent_id').val()).before(data);
|
||||
$('#parent_id').val('');
|
||||
$('#mod_comment_new form')[0].reset();
|
||||
// --- Перемещаем форму обратно в конец. УБРАНО .hide() для сохранения видимости.
|
||||
$('#mod_comment_new').insertAfter('#end');
|
||||
setClickable();
|
||||
}
|
||||
getCaptha();
|
||||
};
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
setClickable();
|
||||
|
||||
// Делегирование событий
|
||||
$(document).on('click', '#captcha img', function(){getCaptha();});
|
||||
|
||||
$(document).on('click', '.mod_comment_answer', function(){cAction(this,'answer');});
|
||||
|
||||
$(document).on('click', '.mod_comment_edit', function(){
|
||||
var cid = $(this).parents('.mod_comment_box').attr('id');
|
||||
var commentTextBlock = $('#'+cid).find('.mod_comment_text');
|
||||
var revert = commentTextBlock.html();
|
||||
|
||||
var textarea = '<p><textarea rows="7" id="ta_'+cid+'" class="editable">'+revert+'</textarea></p>';
|
||||
var charsLeft = '<p>'+COMMENT_CHARS_LEFT+' <span class="charsLeft" id="charsLeft_'+cid+'"></span></p>';
|
||||
var buttonSave = '<input type="button" value="'+COMMENT_BUTTON_EDIT+'" class="button saveButton" /> ';
|
||||
var buttonReset = '<input type="button" value="'+COMMENT_BUTTON_CANCEL+'" class="button cancelButton" />';
|
||||
|
||||
commentTextBlock.after(
|
||||
'<div class="box"><div class="block" id="forms"><fieldset><legend>'+COMMENT_EDIT_TITLE
|
||||
+'</legend>'+textarea+buttonSave+buttonReset+charsLeft+'</fieldset></div></div>'
|
||||
).remove();
|
||||
|
||||
$('.saveButton').click(function(){saveChanges(this,false,cid);});
|
||||
$('.cancelButton').click(function(){saveChanges(this,revert,cid);});
|
||||
$('#ta_'+cid).limit(MAX_CHARS,'#charsLeft_'+cid);
|
||||
});
|
||||
|
||||
if (UGROUP == 1) {
|
||||
$(document).on('click', '.mod_comment_delete', function(){
|
||||
if (confirm('Вы уверены, что хотите удалить комментарий?')) {
|
||||
cAction(this, 'delete');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.mod_comment_lock', function(){cAction(this, 'lock');});
|
||||
$(document).on('click', '.mod_comment_unlock', function(){cAction(this, 'unlock');});
|
||||
|
||||
$(document).on('click', '#mod_comment_open', function(){cAction(this,'open');});
|
||||
$(document).on('click', '#mod_comment_close', function(){cAction(this,'close');});
|
||||
}
|
||||
|
||||
// Отправка формы (AJAX) - ИСПРАВЛЕНИЕ ДВОЙНОЙ ОТПРАВКИ
|
||||
$('#mod_comment_new form').on('submit', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var form = $(this);
|
||||
if (!validate(null, form, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var submitButton = form.find('input[type="submit"], button[type="submit"]').first();
|
||||
var originalButtonText = submitButton.val();
|
||||
|
||||
var formData = form.serialize();
|
||||
|
||||
$.ajax({
|
||||
url: aveabspath+'index.php?ajax=1',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
dataType: 'html',
|
||||
|
||||
// Отключаем кнопку перед отправкой
|
||||
beforeSend: function() {
|
||||
submitButton.prop('disabled', true).val('Отправка...');
|
||||
},
|
||||
|
||||
// Включаем кнопку обратно и обрабатываем ответ
|
||||
success: function(data) {
|
||||
displayNewComment(data);
|
||||
submitButton.prop('disabled', false).val(originalButtonText);
|
||||
},
|
||||
timeout: 3000,
|
||||
error: function(xhr, status, error) {
|
||||
console.error("AJAX Error (Creation):", status, error);
|
||||
alert("Ошибка при отправке комментария. Пожалуйста, проверьте консоль.");
|
||||
// Включаем кнопку обратно в случае ошибки
|
||||
submitButton.prop('disabled', false).val(originalButtonText);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// Сброс формы
|
||||
$('#buttonReset').click(function(){
|
||||
$('#parent_id').val('');
|
||||
$('#mod_comment_new form')[0].reset();
|
||||
$('#mod_comment_new').insertAfter('#end');
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
}
|
||||
})();
|
||||
8
lang/index.php
Normal file
8
lang/index.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Файл-заглушка, предназначенный для запрета показа списка файлов в текущей директории,
|
||||
* если через адресную строку браузера было прямое общращение к данной директории.
|
||||
*/
|
||||
header('Location:/');
|
||||
exit;
|
||||
?>
|
||||
92
lang/ru.txt
Normal file
92
lang/ru.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
[name]
|
||||
MODULE_NAME = "Комментарии"
|
||||
MODULE_DESCRIPTION = "Данный модуль предназначен для организации системы комментариев для документов на сайте. Для того, чтобы использовать данный модуль, разместите системный тег <strong>[mod_comment]</strong> в нужном месте шаблона рубрики."
|
||||
|
||||
[module]
|
||||
COMMENT_EDIT_TITLE = "Редактирование комментария"
|
||||
COMMENT_IS_CLOSED = "Редактирование не возможно, поскольку обсуждение закрыто."
|
||||
COMMENT_CLOSE_BUTTON = "Закрыть окно"
|
||||
COMMENT_EDIT_FALSE = "Извините, но вы не имеете прав для редактирования."
|
||||
COMMENT_YOUR_NAME = "* Имя:"
|
||||
COMMENT_YOUR_EMAIL = "* E-mail:"
|
||||
COMMENT_YOUR_SITE = "Веб-сайт:"
|
||||
COMMENT_YOUR_FROM = "Город:"
|
||||
COMMENT_YOUR_TEXT = "* Комментарий:"
|
||||
COMMENT_BUTTON_EDIT = "Сохранить изменения"
|
||||
COMMENT_BUTTON_CANCEL = "Отменить"
|
||||
COMMENT_BUTTON_RESET = "Очистить"
|
||||
COMMENT_NEW_TITLE = "Написать комментарий"
|
||||
COMMENT_NEW_CLOSED = "Извините, но Вы не можете добавить комментарий, поскольку обсуждение закрыто."
|
||||
COMMENT_NEW_FALSE = "Извините, но у Вас не достаточно прав для добавления комментария."
|
||||
COMMENT_READ_FALSE = "Извините, но у Вас не достаточно прав для просмотра комментариев."
|
||||
COMMENT_CHARS_LEFT = "Количество оставшихся символов"
|
||||
COMMENT_BUTTON_ADD = "Добавить комментарий"
|
||||
COMMENT_INFO = "Информация о пользователе"
|
||||
COMMENT_USER_NAME = "Имя пользователя:"
|
||||
COMMENT_DATE_CREATE = "Опубликовано:"
|
||||
COMMENT_USER_EMAIL = "E-mail пользователя:"
|
||||
COMMENT_USER_SITE = "Личный сайт:"
|
||||
COMMENT_USER_FROM = "Откуда:"
|
||||
COMMENT_USER_COMMENTS = "Оставил комментариев:"
|
||||
COMMENT_THANKYOU_TITLE = "Спасибо за комментарий"
|
||||
COMMENT_THANKYOU_TEXT = "Ваш комментарий успешно добавлен."
|
||||
COMMENT_SITE_TITLE = "Комментарии пользователей"
|
||||
COMMENT_SITE_CLOSED = "(комментирование временно отключено)"
|
||||
COMMENT_SITE_ADD = "Добавить комментарий"
|
||||
COMMENT_LAST_COMMENT = "Последний комментарий"
|
||||
COMMENT_SITE_CLOSE = "Запретить комментирование"
|
||||
COMMENT_SITE_OPEN = "Разрешить комментирование"
|
||||
COMMENT_USER_ADD = "Опубликовано:"
|
||||
COMMENT_USER_TIME = "в"
|
||||
COMMENT_ANSWER_LINK = "Ответить на этот комментарий"
|
||||
COMMENT_EDIT_LINK = "Редактировать комментарий"
|
||||
COMMENT_LOCK_LINK = "Заблокировать ответы"
|
||||
COMMENT_DELETE_LINK = "Удалить комментарий"
|
||||
COMMENT_UNLOCK_LINK = "Разрешить ответы"
|
||||
COMMENT_TEXT_CHANGED = "Изменено:"
|
||||
COMMENT_TEXT_ANSWER = "» Ответил(а):"
|
||||
COMMENT_AFTER_MODER = "Ваш комментарий добавлен.<br />Прежде чем, он будет опубликован, он должен пройти проверку Администрацией сайта."
|
||||
COMMENT_MESSAGE_ADMIN = "На Вашем сайте добавлен новый комментарий:%N%%N%%COMMENT% %N%%N%Для просмотра комментария, перейдите по ссылке:%N%%PAGE%"
|
||||
COMMENT_SUBJECT_MAIL = "Добавлен новый комментарий"
|
||||
COMMENT_CHARSET_LEFT = "осталось символов"
|
||||
COMMENT_FORM_CODE = "Защитный код:"
|
||||
COMMENT_FORM_CODE_ENTER = "Введите код:"
|
||||
COMMENT_WRONG_CODE = "Указанный защитный код неверен."
|
||||
COMMENT_DATE_TIME_FORMAT = "%d-%m-%Y %H:%M"
|
||||
COMMENT_ERROR_AUTHOR = "Укажите Имя!"
|
||||
COMMENT_ERROR_EMAIL = "Укажите eMail!"
|
||||
COMMENT_ERROR_TEXT = "Напишите комментарий!"
|
||||
COMMENT_ERROR_CAPTCHA = "Укажите защитный код!"
|
||||
|
||||
[admin]
|
||||
COMMENT_MODULE_NAME = "Комментарии"
|
||||
COMMENT_MODULE_COMENTS = "Список комментариев"
|
||||
COMMENT_MODULE_SETTINGS = "Настройки модуля"
|
||||
COMMENT_TEXT_COMMENT = "Комментарий"
|
||||
COMMENT_DATE_CREATE = "Дата создания"
|
||||
COMMENT_DOC_TITLE = "Документ"
|
||||
COMMENT_DATE_FORMAT = "%d/%m/%Y %H:%M"
|
||||
COMMENT_ENABLE_COMMENT = "Разрешить комментарии?"
|
||||
COMMENT_CHECK_ADMIN = "Опубликовывать только после проверки?"
|
||||
COMMENT_FOR_GROUPS = "Группы пользователей, которым разрешено оставлять комментарии:"
|
||||
COMMENT_MAX_CHARS = "Максимальное количество символов:"
|
||||
COMMENT_BUTTON_SAVE = "Сохранить настройки"
|
||||
COMMENT_EDIT = "Редактировать комментарий"
|
||||
COMMENT_SPAMPROTECT = "Защита от спама"
|
||||
COMMENT_USE_PAGE_NAV = "Использовать постраничную навигацию"
|
||||
COMMENT_PAGE_NAV_COUNT = "Кол-во комментариев на странице"
|
||||
COMMENT_EDIT_TITLE = "Редактирование комментария"
|
||||
COMMENT_IS_CLOSED = "Редактирование не возможно, поскольку обсуждение закрыто."
|
||||
COMMENT_CLOSE_BUTTON = "Закрыть окно"
|
||||
COMMENT_EDIT_FALSE = "Извините, но вы не имеете прав для редактирования."
|
||||
COMMENT_YOUR_NAME = "* Имя:"
|
||||
COMMENT_YOUR_EMAIL = "* E-mail:"
|
||||
COMMENT_YOUR_SITE = "Веб-сайт:"
|
||||
COMMENT_YOUR_FROM = "Город:"
|
||||
COMMENT_YOUR_TEXT = "* Комментарий:"
|
||||
COMMENT_BUTTON_EDIT = "Сохранить изменения"
|
||||
COMMENT_BUTTON_CANCEL = "Отменить"
|
||||
COMMENT_CHARS_LEFT = "Количество оставшихся символов"
|
||||
COMMENT_BUTTON_CANCEL = "Отменить"
|
||||
COMMENT_BUTTON_RESET = "Очистить"
|
||||
COMMENT_FOR_GROUPS_READ = "Группы пользователей, которым разрешен просмотр комментариев:"
|
||||
151
module.php
Normal file
151
module.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AVE.cms - Модуль Комментарии
|
||||
*
|
||||
* @package AVE.cms
|
||||
* @subpackage module_Comment
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
if(!defined('BASE_DIR')) exit;
|
||||
|
||||
/**
|
||||
* Функция, предназначенная для вывода списка комментариев к данному документу.
|
||||
* Она будет выполнена при парсинге шаблона вместо системного тега [mod_comment].
|
||||
*/
|
||||
function mod_comment()
|
||||
{
|
||||
global $AVE_Template;
|
||||
|
||||
// Подключаем класс и создаем объект дял работы
|
||||
require_once(BASE_DIR . '/modules/comment/class/comment.php');
|
||||
$comment = new Comment;
|
||||
|
||||
// Подключаем языковые файлы
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . $_SESSION['user_language'] . '.txt';
|
||||
$AVE_Template->config_load($lang_file, 'module');
|
||||
|
||||
// Обращаемся к методу commentListShow() и отображаем список комментариев
|
||||
$comment->commentListShow($tpl_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Следующий раздел описывает правила поведения модуля и его функциональные возможности
|
||||
* только при работе в Публичной части сайта.
|
||||
*/
|
||||
|
||||
|
||||
// Определяем, что мы не находимся в Панели управления и в строке запроса происходит обращение именно к данному модулю
|
||||
if (!defined('ACP') && isset($_REQUEST['module']) && $_REQUEST['module'] == 'comment' && isset($_REQUEST['action']))
|
||||
{
|
||||
// Подключаем основной класс и создаем объект
|
||||
require_once(BASE_DIR . '/modules/comment/class/comment.php');
|
||||
$comment = new Comment;
|
||||
|
||||
// Определяем директори, где хранятся файлы с шаблонами модуля и подключаем языковые переменные
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . $_SESSION['user_language'] . '.txt';
|
||||
$AVE_Template->config_load($lang_file, 'module');
|
||||
|
||||
// Определяем, какой параметр пришел из строки запроса браузера
|
||||
switch($_REQUEST['action'])
|
||||
{
|
||||
// Если form, тогда отображаем форму для добавления нового комментария
|
||||
case 'form':
|
||||
$comment->commentPostFormShow($tpl_dir);
|
||||
break;
|
||||
|
||||
// Если comment, тогда производим запись нового комментария в БД
|
||||
case 'comment':
|
||||
$comment->commentPostNew($tpl_dir);
|
||||
break;
|
||||
|
||||
// Если edit, тогда открываем форму для редактирования текста комментария
|
||||
case 'edit':
|
||||
$comment->commentPostEdit((int)$_REQUEST['Id']);
|
||||
break;
|
||||
|
||||
|
||||
// Если delete, тогда удаляем комментарий
|
||||
case 'delete':
|
||||
if (UGROUP==1)
|
||||
{
|
||||
$comment->commentPostDelete((int)$_REQUEST['Id']);
|
||||
}
|
||||
break;
|
||||
|
||||
// Если postinfo, тогда отображаем окно с информацией об авторе комментария
|
||||
case 'postinfo':
|
||||
$comment->commentPostInfoShow($tpl_dir);
|
||||
break;
|
||||
|
||||
// Если lock или unlock, тогда запрещаем или разрешаем оставлять ответы для имеющихся комментариев
|
||||
case 'lock':
|
||||
case 'unlock':
|
||||
if (UGROUP==1)
|
||||
{
|
||||
$comment->commentReplyStatusSet((int)$_REQUEST['Id'], $_REQUEST['action']);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// Если open или close, тогда разрешаем или запрещаем полное комментирование документа
|
||||
case 'open':
|
||||
case 'close':
|
||||
if (UGROUP==1)
|
||||
{
|
||||
$comment->commentStatusSet((int)$_REQUEST['docid'], $_REQUEST['action']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Следующий раздел описывает правила поведения модуля и его функциональные возможности
|
||||
* только при работе в Административной части сайта.
|
||||
*/
|
||||
if (defined('ACP') && !empty($_REQUEST['moduleaction']))
|
||||
{
|
||||
// Подключаем основной класс и создаем объект
|
||||
require_once(BASE_DIR . '/modules/comment/class/comment.php');
|
||||
$comment = new Comment;
|
||||
|
||||
// Определяем директори, где хранятся файлы с шаблонами модуля и подключаем языковые переменные
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . $_SESSION['admin_language'] . '.txt';
|
||||
$AVE_Template->config_load($lang_file, 'admin');
|
||||
|
||||
|
||||
// Определяем, какой параметр пришел из строки запроса браузера
|
||||
switch ($_REQUEST['moduleaction'])
|
||||
{
|
||||
|
||||
// Если 1, тогда отображаем список всех комментариев с постраничной навигацией
|
||||
case '1':
|
||||
$comment->commentAdminListShow($tpl_dir);
|
||||
break;
|
||||
|
||||
// Если admin_edit, тогда открываем форму для редактирования выбранного комментария
|
||||
case 'admin_edit':
|
||||
$comment->commentAdminPostEdit($tpl_dir);
|
||||
break;
|
||||
|
||||
// Если settings, тогда открываем страницу с настройками данного модуля
|
||||
case 'settings':
|
||||
// Подключаем файл класса для работы с пользователями, создаем объект и получаем список
|
||||
// всех групп пользователей, имеющихся в системе.
|
||||
require_once(BASE_DIR . '/class/class.user.php');
|
||||
$AVE_User = new AVE_User;
|
||||
$AVE_Template->assign('groups', $AVE_User->userGroupListGet());
|
||||
|
||||
$comment->commentAdminSettingsEdit($tpl_dir);
|
||||
break;
|
||||
case 'admin_del':
|
||||
$comment->commentAdminDelete((int)$_REQUEST['Id']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
117
sql.php
Normal file
117
sql.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AVE.cms - Модуль Комментарии
|
||||
*
|
||||
* Данный файл является частью модуля "Комментарии" и содержит mySQL-запросы
|
||||
* к базе данных при операцих установки, обновления и удаления модуля через Панель управления.
|
||||
*
|
||||
* @package AVE.cms
|
||||
* @subpackage module_Comment
|
||||
* @since 1.4
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
$module_sql_install = array();
|
||||
$module_sql_deinstall = array();
|
||||
$module_sql_update = array();
|
||||
|
||||
$module_sql_deinstall[] = "DROP TABLE IF EXISTS `%%PRFX%%_module_comments`;";
|
||||
$module_sql_deinstall[] = "DROP TABLE IF EXISTS `%%PRFX%%_module_comment_info`;";
|
||||
|
||||
// =================================================================================
|
||||
// 1. ИЗМЕНЕНИЯ ДЛЯ УСТАНОВКИ МОДУЛЯ
|
||||
// =================================================================================
|
||||
$module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comments` (
|
||||
`Id` tinyint(1) unsigned NOT NULL auto_increment,
|
||||
`comment_max_chars` smallint(3) unsigned NOT NULL default '1000',
|
||||
`comment_user_groups` text NOT NULL,
|
||||
`comment_user_groups_read` text NOT NULL, /* <-- НОВОЕ ПОЛЕ ДЛЯ ПРАВ НА ПРОСМОТР */
|
||||
`comment_need_approve` enum('0','1') NOT NULL default '0',
|
||||
`comment_active` enum('1','0') NOT NULL default '1',
|
||||
`comment_use_antispam` enum('1','0') NOT NULL default '1',
|
||||
`comment_use_page_nav` enum('1','0') NOT NULL default '1',
|
||||
`comment_page_nav_count` varchar(5) NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
||||
|
||||
$module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_info` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`parent_id` int(10) unsigned NOT NULL default '0',
|
||||
`document_id` int(10) unsigned NOT NULL default '0',
|
||||
`comment_author_name` varchar(255) NOT NULL,
|
||||
`comment_author_id` int(10) unsigned NOT NULL default '0',
|
||||
`comment_author_email` varchar(255) NOT NULL,
|
||||
`comment_author_city` varchar(255) NOT NULL,
|
||||
`comment_author_website` varchar(255) NOT NULL,
|
||||
`comment_author_ip` varchar(15) NOT NULL,
|
||||
`comment_published` int(10) unsigned NOT NULL default '0',
|
||||
`comment_changed` int(10) unsigned NOT NULL default '0',
|
||||
`comment_text` text NOT NULL,
|
||||
`comment_status` tinyint(1) unsigned NOT NULL default '1',
|
||||
`comments_close` tinyint(1) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `document_id` (`document_id`),
|
||||
KEY `parent_id` (`parent_id`),
|
||||
KEY `comment_status` (`comment_status`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0;";
|
||||
|
||||
// ИЗМЕНЕННАЯ СТРОКА: Устанавливаем права на просмотр по умолчанию для всех групп: 1, 2, 3, 4
|
||||
$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_comments` VALUES (1, 1000, '1,3', '1,2,3,4', '0', '1', '1' , '0', '');";
|
||||
// ^ max chars, ^ write groups, ^ read groups (ИСПРАВЛЕНО), ^ need_approve ...
|
||||
|
||||
// =================================================================================
|
||||
// 2. ИЗМЕНЕНИЯ ДЛЯ ОБНОВЛЕНИЯ МОДУЛЯ (Добавление нового поля)
|
||||
// =================================================================================
|
||||
|
||||
// Обновление версии модуля (оставлено без изменений)
|
||||
$module_sql_update[] = "
|
||||
UPDATE
|
||||
`%%PRFX%%_module`
|
||||
SET
|
||||
ModuleAveTag = '" . $modul['ModuleAveTag'] . "',
|
||||
ModulePHPTag = '" . $modul['ModulePHPTag'] . "',
|
||||
ModuleVersion = '" . $modul['ModuleVersion'] . "'
|
||||
WHERE
|
||||
ModuleSysName = '" . $modul['ModuleSysName'] . "'
|
||||
LIMIT 1;
|
||||
";
|
||||
|
||||
// Добавление нового столбца comment_user_groups_read в существующую таблицу
|
||||
$module_sql_update[] = "
|
||||
ALTER TABLE
|
||||
`%%PRFX%%_module_comments`
|
||||
ADD
|
||||
`comment_user_groups_read` TEXT NOT NULL
|
||||
AFTER
|
||||
`comment_user_groups`;
|
||||
";
|
||||
|
||||
// ИЗМЕНЕННАЯ СТРОКА: Заполнение нового столбца значением по умолчанию для всех групп: 1, 2, 3, 4
|
||||
$module_sql_update[] = "
|
||||
UPDATE
|
||||
`%%PRFX%%_module_comments`
|
||||
SET
|
||||
`comment_user_groups_read` = '1,2,3,4'
|
||||
WHERE
|
||||
`Id` = 1;
|
||||
";
|
||||
|
||||
$module_sql_update[] = "
|
||||
ALTER TABLE
|
||||
`%%PRFX%%_module_comments`
|
||||
ADD
|
||||
`comment_use_page_nav` ENUM('0','1') NOT NULL DEFAULT '1'
|
||||
AFTER
|
||||
`comment_use_antispam`;
|
||||
";
|
||||
|
||||
$module_sql_update[] = "
|
||||
ALTER TABLE
|
||||
`%%PRFX%%_module_comments`
|
||||
ADD
|
||||
`comment_page_nav_count` VARCHAR(5) NOT NULL
|
||||
AFTER
|
||||
`comment_use_page_nav`;
|
||||
";
|
||||
?>
|
||||
89
templates/admin_comments.tpl
Normal file
89
templates/admin_comments.tpl
Normal file
@@ -0,0 +1,89 @@
|
||||
<script type="text/javascript" language="JavaScript">
|
||||
$(document).ready(function(){ldelim}
|
||||
|
||||
|
||||
|
||||
{rdelim});
|
||||
</script>
|
||||
|
||||
<div class="title"><h5>{#COMMENT_MODULE_NAME#}</h5></div>
|
||||
|
||||
<div class="widget" style="margin-top: 0px;">
|
||||
<div class="body">
|
||||
{#COMMENT_MODULE_COMENTS#}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="breadCrumbHolder module">
|
||||
<div class="breadCrumb module">
|
||||
<ul>
|
||||
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
|
||||
<li><a href="index.php?do=modules&cp={$sess}">{#MODULES_SUB_TITLE#}</a></li>
|
||||
<li>{#COMMENT_MODULE_NAME#}</li>
|
||||
<li><strong class="code">{#COMMENT_MODULE_COMENTS#}</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="widget first">
|
||||
<div class="head">
|
||||
<h5 class="iFrames">{#COMMENT_MODULE_COMENTS#}</h5>
|
||||
<div class="num"><a class="basicNum" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=settings&cp={$sess}">{#COMMENT_MODULE_SETTINGS#}</a></div>
|
||||
</div>
|
||||
|
||||
{if isset($smarty.request.page)}
|
||||
{assign var="current_page" value=$smarty.request.page|escape}
|
||||
{else}
|
||||
{assign var="current_page" value=1}
|
||||
{/if}
|
||||
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
|
||||
<col width="20">
|
||||
<col>
|
||||
<col width="120">
|
||||
<col width="120">
|
||||
<col width="20">
|
||||
<col width="20">
|
||||
<thead>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><a href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp={$sess}&page={$current_page}&sort=comment{if $smarty.request.sort|default:'' == 'comment'}_desc{/if}">{#COMMENT_TEXT_COMMENT#}</a> </td>
|
||||
<td><a href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp={$sess}&page={$current_page}&sort=created{if $smarty.request.sort|default:'' == 'created'}_desc{/if}">{#COMMENT_DATE_CREATE#}</a> </td>
|
||||
<td><a href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp={$sess}&page={$current_page}&sort=document{if $smarty.request.sort|default:'' == 'document'}_desc{/if}">{#COMMENT_DOC_TITLE#}</a> </td>
|
||||
<td colspan="2">Действия</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{if $docs}
|
||||
{foreach from=$docs item=doc}
|
||||
<tr>
|
||||
<td>{if $doc.comment_status != "0"}<span class="icon_sprite ico_ok"></span>{else}<span class="icon_sprite ico_blanc"></span>{/if}</td>
|
||||
<td><a class="topDir" title="{$doc.comment_text|escape|truncate:'1000'}" target="_blank" href="../index.php?id={$doc.document_id}&doc=impressum&subaction=showonly&comment_id={$doc.CId}#{$doc.CId}">{$doc.comment_text|escape|truncate:'100'}</a></td>
|
||||
<td class="date_text dgrey">{$doc.comment_published|date_format:$TIME_FORMAT|pretty_date}</td>
|
||||
<td><a target="_blank" href="../index.php?id={$doc.document_id}">{$doc.document_title|escape}</a> <span class="date_text dgrey">({$doc.Comments})</span></td>
|
||||
<td width="20"><a class="topleftDir icon_sprite ico_edit" title="{#COMMENT_EDIT#}" href="javascript:void(0);" onClick="windowOpen('index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_edit&pop=1&docid={$doc.document_id}&Id={$doc.CId}','700','700','1');"></a></td>
|
||||
<td width="20"><a class="topleftDir icon_sprite ico_delete ConfirmDelete" title="{#COMMENT_DELETE_LINK#}" dir="{#COMMENT_DELETE_LINK#}" name="{#COMMENT_DELETE_LINK#}" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&Id={$doc.CId}"></a></td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<ul class="messages">
|
||||
<li class="highlight yellow"><strong>Сообщение:</strong><br />Нет комментариев.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{if $page_nav}
|
||||
<div class="pagination">
|
||||
<ul class="pages">
|
||||
{$page_nav}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
112
templates/admin_edit.tpl
Normal file
112
templates/admin_edit.tpl
Normal file
@@ -0,0 +1,112 @@
|
||||
<script type="text/javascript" language="JavaScript">
|
||||
{literal}
|
||||
$(document).ready(function(){
|
||||
|
||||
var left = {/literal}{$comment_max_chars}{literal}
|
||||
$('#text_counter').text(left);
|
||||
|
||||
$('#in_message').keyup(function () {
|
||||
|
||||
left = {/literal}{$comment_max_chars}{literal} - $(this).val().length;
|
||||
|
||||
if(left < 0){
|
||||
$('#text_counter').addClass("overlimit");
|
||||
}
|
||||
if(left >= 0){
|
||||
$('#text_counter').removeClass("overlimit");
|
||||
}
|
||||
|
||||
$('#text_counter').text(left);
|
||||
});
|
||||
|
||||
});
|
||||
{/literal}
|
||||
</script>
|
||||
|
||||
<div class="widget first"></div>
|
||||
|
||||
<div class="title"><h5>{#COMMENT_MODULE_NAME#}</h5></div>
|
||||
|
||||
<div class="widget" style="margin-top: 0px;">
|
||||
<div class="body">
|
||||
{#COMMENT_EDIT_TITLE#}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="breadCrumbHolder module">
|
||||
<div class="breadCrumb module">
|
||||
<ul>
|
||||
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
|
||||
<li>{#COMMENT_MODULE_NAME#}</li>
|
||||
<li>{#COMMENT_EDIT_TITLE#}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget first">
|
||||
{if $closed == 1 && $smarty.const.UGROUP != 1}
|
||||
|
||||
{#COMMENT_IS_CLOSED#}
|
||||
|
||||
<p><input onclick="window.close();" type="button" class="basicBtn" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
{else}
|
||||
{if $editfalse==1}
|
||||
{#COMMENT_EDIT_FALSE#}
|
||||
{else}
|
||||
<form method="post" action="index.php" class="mainForm">
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
|
||||
<col width="150">
|
||||
{if $smarty.const.UGROUP == 1}
|
||||
<tr>
|
||||
<td>{#COMMENT_YOUR_NAME#}</td>
|
||||
<td><input name="comment_author_name" type="text" id="in_author_name" style="width:250px" value="{$row.comment_author_name|stripslashes|escape}" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>{#COMMENT_YOUR_EMAIL#}</td>
|
||||
<td><input name="comment_author_email" type="text" id="in_author_email" style="width:250px" value="{$row.comment_author_email|stripslashes|escape}" /></td>
|
||||
</tr>
|
||||
{else}
|
||||
<input type="hidden" name="comment_author_name" value="{$row.comment_author_name|stripslashes|escape}" />
|
||||
<input type="hidden" name="comment_author_email" value="{$row.comment_author_email|stripslashes|escape}" />
|
||||
{/if}
|
||||
<tr>
|
||||
<td>{#COMMENT_YOUR_SITE#}</td>
|
||||
<td><input name="comment_author_website" type="text" id="in_author_website" style="width:250px" value="{$row.comment_author_website|stripslashes|escape}" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>{#COMMENT_YOUR_FROM#}</td>
|
||||
<td><input name="comment_author_city" type="text" id="in_author_city" style="width:250px" value="{$row.comment_author_city|stripslashes|escape}" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>{#COMMENT_YOUR_TEXT#}</td>
|
||||
<td>
|
||||
<div class="pr12"><textarea style="width:100%; height:170px" name="comment_text" id="in_message">{$row.comment_text}</textarea></div>
|
||||
<span id="text_counter"></span> {#COMMENT_CHARS_LEFT#}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<input type="hidden" name="do" value="modules" />
|
||||
<input type="hidden" name="action" value="modedit" />
|
||||
<input type="hidden" name="mod" value="comment" />
|
||||
<input type="hidden" name="moduleaction" value="admin_edit" />
|
||||
<input type="hidden" name="sub" value="send" />
|
||||
<input type="hidden" name="Id" value="{$smarty.request.Id|escape}" />
|
||||
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<input type="submit" class="basicBtn" value="{#COMMENT_BUTTON_EDIT#}" />
|
||||
<input type="reset" class="basicBtn" value="{#COMMENT_BUTTON_CANCEL#}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</form>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
105
templates/admin_settings.tpl
Normal file
105
templates/admin_settings.tpl
Normal file
@@ -0,0 +1,105 @@
|
||||
<div class="title"><h5>{#COMMENT_MODULE_NAME#}</h5></div>
|
||||
|
||||
<div class="widget" style="margin-top: 0px;">
|
||||
<div class="body">
|
||||
{#COMMENT_MODULE_SETTINGS#}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="breadCrumbHolder module">
|
||||
<div class="breadCrumb module">
|
||||
<ul>
|
||||
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
|
||||
<li><a href="index.php?do=modules&cp={$sess}">{#MODULES_SUB_TITLE#}</a></li>
|
||||
<li><a href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp={$sess}">{#COMMENT_MODULE_NAME#}</a></li>
|
||||
<li><strong class="code">{#COMMENT_MODULE_SETTINGS#}</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget first">
|
||||
<div class="head">
|
||||
<h5 class="iFrames">{#COMMENT_MODULE_SETTINGS#}</h5>
|
||||
<div class="num"><a class="basicNum" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp={$sess}">{#COMMENT_MODULE_COMENTS#}</a></div>
|
||||
</div>
|
||||
|
||||
<form action="index.php?do=modules&action=modedit&mod=comment&moduleaction=settings&cp={$sess}&sub=save" method="post" class="mainForm">
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
|
||||
<tr class="noborder">
|
||||
<td width="240">{#COMMENT_ENABLE_COMMENT#}</td>
|
||||
<td><input name="comment_active" type="checkbox" value="1" {if $comment_active=='1'}checked{/if} /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_CHECK_ADMIN#}</td>
|
||||
<td>
|
||||
<input name="comment_need_approve" type="checkbox" value="1" {if $comment_need_approve=='1'}checked{/if} />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_SPAMPROTECT#}</td>
|
||||
<td>
|
||||
<input name="comment_use_antispam" type="checkbox" value="1" {if $comment_use_antispam=='1'}checked{/if} />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_USE_PAGE_NAV#}</td>
|
||||
<td>
|
||||
<input name="comment_use_page_nav" type="checkbox" value="1" {if $comment_use_page_nav=='1'}checked{/if} />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_PAGE_NAV_COUNT#}</td>
|
||||
<td>
|
||||
<input name="comment_page_nav_count" type="text" value="{$comment_page_nav_count}" size="4" style="width: 50px;" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_FOR_GROUPS#}</td>
|
||||
<td>
|
||||
<select name="comment_user_groups[]" multiple="multiple" size="5" style="width:300px">
|
||||
{foreach from=$groups item=g}
|
||||
{assign var='sel' value=''}
|
||||
{if $g->user_group}
|
||||
{if (in_array($g->user_group,$comment_user_groups)) }
|
||||
{assign var='sel' value='selected'}
|
||||
{/if}
|
||||
{/if}
|
||||
<option value="{$g->user_group}" {$sel}>{$g->user_group_name|escape}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_FOR_GROUPS_READ#}</td>
|
||||
<td>
|
||||
<select name="comment_user_groups_read[]" multiple="multiple" size="5" style="width:300px">
|
||||
{foreach from=$groups item=g}
|
||||
{assign var='sel_read' value=''}
|
||||
{if $g->user_group}
|
||||
{if (in_array($g->user_group,$comment_user_groups_read)) }
|
||||
{assign var='sel_read' value='selected'}
|
||||
{/if}
|
||||
{/if}
|
||||
<option value="{$g->user_group}" {$sel_read}>{$g->user_group_name|escape}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="240">{#COMMENT_MAX_CHARS#}</td>
|
||||
<td><input name="comment_max_chars" type="text" id="comment_max_chars" value="{$comment_max_chars}" size="5" maxlength="5" style="width: 50px;" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><input type="submit" value="{#COMMENT_BUTTON_SAVE#}" class="basicBtn" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
71
templates/comment_edit.tpl
Normal file
71
templates/comment_edit.tpl
Normal file
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>{#COMMENT_EDIT_TITLE#}</title>
|
||||
<link href="templates/{$theme}/css/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
<script src="templates/{$theme}/js/common.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="body_popup">
|
||||
<div id="module_header"><h2>{#COMMENT_EDIT_TITLE#}</h2></div>
|
||||
|
||||
<div id="module_content">
|
||||
{if $closed == 1 && $smarty.const.UGROUP != 1}
|
||||
{#COMMENT_IS_CLOSED#}
|
||||
<p> </p>
|
||||
<p><input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
{else}
|
||||
{if $editfalse==1}
|
||||
{#COMMENT_EDIT_FALSE#}
|
||||
{else}
|
||||
<form method="post">
|
||||
{if $smarty.const.UGROUP==1}
|
||||
<fieldset>
|
||||
<legend><label for="in_author_name">{#COMMENT_YOUR_NAME#}</label></legend>
|
||||
<input name="comment_author_name" type="text" id="in_author_name" style="width:250px" value="{$row.comment_author_name|stripslashes|escape}" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_author_email">{#COMMENT_YOUR_EMAIL#}</label></legend>
|
||||
<input name="comment_author_email" type="text" id="in_author_email" style="width:250px" value="{$row.comment_author_email|stripslashes|escape}" />
|
||||
</fieldset>
|
||||
{else}
|
||||
<input name="comment_author_name" type="hidden" id="in_author_name" value="{$row.comment_author_name|stripslashes|escape}" />
|
||||
<input name="comment_author_email" type="hidden" id="in_author_email" value="{$row.comment_author_email|stripslashes|escape}" />
|
||||
{/if}
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_author_website">{#COMMENT_YOUR_SITE#}</label></legend>
|
||||
<input name="comment_author_website" type="text" id="in_author_website" style="width:250px" value="{$row.comment_author_website|stripslashes|escape}" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_author_city">{#COMMENT_YOUR_FROM#}</label></legend>
|
||||
<input name="comment_author_city" type="text" id="in_author_city" style="width:250px" value="{$row.comment_author_city|stripslashes|escape}" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_message">{#COMMENT_YOUR_TEXT#}</label></legend>
|
||||
<textarea onkeyup="javascript:textCounter(this.form.comment_text,this.form.charleft,{$row.comment_max_chars});" onkeydown="javascript:textCounter(this.form.comment_text,this.form.charleft,{$row.comment_max_chars});" style="width:98%; height:170px" name="comment_text" id="in_message">{$row.comment_text}</textarea>
|
||||
<input type="text" size="6" name="charleft" value="{$row.comment_max_chars}" /> {#COMMENT_CHARS_LEFT#}
|
||||
</fieldset>
|
||||
|
||||
<input name="theme" type="hidden" id="theme" value="{$smarty.request.theme|escape}" />
|
||||
<input name="module" type="hidden" value="comment" />
|
||||
<input name="action" type="hidden" value="edit" />
|
||||
<input name="pop" type="hidden" value="1" />
|
||||
<input name="sub" type="hidden" value="send" />
|
||||
<input name="Id" type="hidden" value="{$smarty.request.Id|escape}" />
|
||||
|
||||
<p>
|
||||
<input type="submit" class="button" value="{#COMMENT_BUTTON_EDIT#}" />
|
||||
<input type="reset" class="button" />
|
||||
</p>
|
||||
</form>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
84
templates/comment_form.tpl
Normal file
84
templates/comment_form.tpl
Normal file
@@ -0,0 +1,84 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
|
||||
<title>{#COMMENT_NEW_TITLE#}</title>
|
||||
<link href="templates/{$theme}/css/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
<script src="templates/{$theme}/js/common.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body id="body_popup">
|
||||
|
||||
<div id="module_header"><h2>{#COMMENT_NEW_TITLE#}</h2></div>
|
||||
|
||||
<div id="module_content">
|
||||
{if $closed==1}
|
||||
{#COMMENT_NEW_CLOSED#}
|
||||
<p> </p>
|
||||
<p><input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
{else}
|
||||
{if !$cancomment}
|
||||
<p id="module_intro">{#COMMENT_NEW_FALSE#}</p>
|
||||
<p> </p>
|
||||
<p><input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
{else}
|
||||
<form method="post">
|
||||
{if $smarty.session.user_name != ''}
|
||||
<input name="comment_author_name" type="hidden" value="{$smarty.session.user_name|escape}" />
|
||||
{else}
|
||||
<fieldset>
|
||||
<legend><label for="in_author_name">{#COMMENT_YOUR_NAME#}</label></legend>
|
||||
<input name="comment_author_name" type="text" id="in_author_name" style="width:250px" value="{$smarty.session.user_name|escape}" />
|
||||
</fieldset>
|
||||
<br />
|
||||
{/if}
|
||||
|
||||
{if $smarty.session.user_email != ''}
|
||||
<input name="comment_author_email" type="hidden" value="{$smarty.session.user_email|escape}" />
|
||||
{else}
|
||||
<fieldset>
|
||||
<legend><label for="in_author_email">{#COMMENT_YOUR_EMAIL#}</label></legend>
|
||||
<input name="comment_author_email" type="text" id="in_author_email" style="width:250px" value="" />
|
||||
</fieldset>
|
||||
<br />
|
||||
{/if}
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_author_website">{#COMMENT_YOUR_SITE#}</label></legend>
|
||||
<input name="comment_author_website" type="text" id="in_author_website" style="width:250px" />
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_author_city">{#COMMENT_YOUR_FROM#}</label></legend>
|
||||
<input name="comment_author_city" type="text" id="in_author_city" style="width:250px" />
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<fieldset>
|
||||
<legend><label for="in_message">{#COMMENT_YOUR_TEXT#}</label></legend>
|
||||
<textarea onkeyup="javascript:textCounter(this.form.comment_text,this.form.charleft,{$comment_max_chars});" onkeydown="javascript:textCounter(this.form.comment_text,this.form.charleft,{$comment_max_chars});" style="width:98%; height:165px" name="comment_text" id="in_message"></textarea>
|
||||
<input type="text" size="6" name="charleft" value="{$comment_max_chars}" /> {#COMMENT_CHARSET_LEFT#}
|
||||
</fieldset>
|
||||
|
||||
<input name="theme" type="hidden" id="theme" value="{$smarty.request.theme|escape}" />
|
||||
<input name="module" type="hidden" value="comment" />
|
||||
<input name="action" type="hidden" value="comment" />
|
||||
<input name="pop" type="hidden" id="pop" value="1" />
|
||||
<input name="sub" type="hidden" id="sub" value="send" />
|
||||
<input name="page" type="hidden" value="{$smarty.request.page|escape}" />
|
||||
<input name="document_id" type="hidden" value="{$smarty.request.docid|escape}" />
|
||||
<input name="parent_id" type="hidden" value="{$smarty.request.parent|escape|default:0}" />
|
||||
|
||||
<p>
|
||||
<input type="submit" class="button" value="{#COMMENT_BUTTON_ADD#}" />
|
||||
<input type="reset" class="button" />
|
||||
</p>
|
||||
</form>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
54
templates/comment_info.tpl
Normal file
54
templates/comment_info.tpl
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
|
||||
<title>{#COMMENT_INFO#}</title>
|
||||
<link href="templates/{$smarty.request.theme|escape}/css/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
</head>
|
||||
|
||||
<body id="body_popup">
|
||||
|
||||
<div id="module_header"><h2>{#COMMENT_INFO#}</h2></div>
|
||||
|
||||
<div id="module_content">
|
||||
<table width="100%" border="0" cellspacing="1" cellpadding="4">
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_NAME#}</td>
|
||||
<td>{$c.comment_author_name|stripslashes|escape}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_DATE_CREATE#}</td>
|
||||
<td>{$c.comment_published|date_format:$TIME_FORMAT|pretty_date}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_EMAIL#}</td>
|
||||
<td>
|
||||
{assign var=comment_author_email value=$c.comment_author_email}
|
||||
{mailto address="$comment_author_email" encode="javascript_charcode"}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_SITE#}</td>
|
||||
<td>{$c.comment_author_website|default:'-'}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_FROM#}</td>
|
||||
<td>{$c.comment_author_city|stripslashes|escape|default:'-'}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_COMMENTS#}</td>
|
||||
<td>{$c.num|default:'-'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
24
templates/comment_new.tpl
Normal file
24
templates/comment_new.tpl
Normal file
@@ -0,0 +1,24 @@
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="mod_comment_box">
|
||||
<tr>
|
||||
<td class="mod_comment_header">
|
||||
<div class="mod_comment_author">
|
||||
<a name="{$comment_id}"></a>{#COMMENT_USER_ADD#} <a title="{#COMMENT_INFO#}" href="javascript:void(0);" onclick="popup('index.php?module=comment&action=postinfo&pop=1&Id={$comment_id}&theme={$theme}','comment','500','300','1');">{$comment_author_name}</a> • {$smarty.now|date_format:$TIME_FORMAT|pretty_date}{if $smarty.const.UGROUP==1} • IP:{$comment_author_ip}{/if}
|
||||
</div>
|
||||
|
||||
{if $smarty.const.UGROUP==1}
|
||||
<div class="mod_comment_icons">
|
||||
<a class="" title="{#COMMENT_DELETE_LINK#}" href="javascript:void(0);" onclick="cAction(this, 'delete', '{$comment_id}');"><img src="modules/comment/templates/images/trash.gif" alt="" border="0" /></a>
|
||||
{if $comment_status!=1}
|
||||
<a class="" title="{#COMMENT_UNLOCK_LINK#}" href="javascript:void(0);" onclick="cAction(this, 'unlock', '{$comment_id}');"><img src="modules/comment/templates/images/unlock.gif" alt="" border="0" /></a>
|
||||
{else}
|
||||
<a class="" title="{#COMMENT_LOCK_LINK#}" href="javascript:void(0);" onclick="cAction(this, 'unlock', '{$comment_id}');"><img src="modules/comment/templates/images/lock.gif" alt="" border="0" /></a>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td id="id_{$comment_id}" class="mod_comment_text{if $smarty.session.user_id} editable_text{/if}">{$comment_text}</td>
|
||||
</tr>
|
||||
</table>
|
||||
15
templates/comment_thankyou.tpl
Normal file
15
templates/comment_thankyou.tpl
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
|
||||
<title>{#COMMENT_THANKYOU_TITLE#}</title>
|
||||
<link href="templates/{$smarty.request.theme}/css/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body id="body_popup">
|
||||
<div id="module_header"><h2>{#COMMENT_THANKYOU_TITLE#}</h2></div>
|
||||
<div id="module_content">
|
||||
<p id="module_intro">{$JsAfter}</p>
|
||||
<input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
122
templates/comments_show.tpl
Normal file
122
templates/comments_show.tpl
Normal file
@@ -0,0 +1,122 @@
|
||||
{if $display_comments==1}<br />
|
||||
|
||||
<h6>{#COMMENT_SITE_TITLE#}{if $closed==1} {#COMMENT_SITE_CLOSED#}{/if}</h6>
|
||||
|
||||
{if $cancomment==1 && $closed!=1}
|
||||
<a href="javascript:void(0);" onclick="popup('index.php?docid={$smarty.request.id|escape}&module=comment&action=form&pop=1&theme={$theme}&page={$page}','comment','500','600','1')">{#COMMENT_SITE_ADD#}</a> |
|
||||
{/if}
|
||||
|
||||
<a href="#end">{#COMMENT_LAST_COMMENT#}</a>
|
||||
|
||||
{if $smarty.const.UGROUP == 1}
|
||||
|
|
||||
{if $closed==1}
|
||||
<a href="javascript:void(0);" onclick="popup('index.php?document_id={$smarty.request.id|escape}&module=comment&action=open&pop=1','comment','50','50','1');">{#COMMENT_SITE_OPEN#}</a>
|
||||
{else}
|
||||
<a href="javascript:void(0);" onclick="popup('index.php?document_id={$smarty.request.id|escape}&module=comment&action=close&pop=1','comment','50','50','1');">{#COMMENT_SITE_CLOSE#}</a>
|
||||
{/if}
|
||||
{/if}<br />
|
||||
<br />
|
||||
|
||||
{foreach from=$comments.0 item=c name=co}
|
||||
{if $smarty.request.subaction=='showonly' && $smarty.request.comment_id==$c.Id}
|
||||
<div class="mod_comment_highlight">
|
||||
{/if}
|
||||
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="mod_comment_box">
|
||||
<tr>
|
||||
<td class="mod_comment_header">
|
||||
<div class="mod_comment_author">
|
||||
<a name="{$c.Id}"></a>{#COMMENT_USER_ADD#} <a title="{#COMMENT_INFO#}" href="javascript:void(0);" onclick="popup('index.php?module=comment&action=postinfo&pop=1&Id={$c.Id}&theme={$theme}','comment','500','300','1');">{$c.comment_author_name}{*|stripslashes|escape:html*}</a> • {$c.comment_published}{if $smarty.const.UGROUP==1} • IP:{$c.comment_author_ip}{/if}
|
||||
</div>
|
||||
|
||||
<div class="mod_comment_icons">
|
||||
<a class="popup" href="javascript:void(0);" onclick="popup('index.php?parent={$c.Id}&docid={$smarty.request.id|escape}&module=comment&action=form&pop=1&theme={$theme}&page={$page}','comment','500','520','1');">
|
||||
<img src="modules/comment/templates/images/reply.gif" alt="" border="0" /><span>{#COMMENT_ANSWER_LINK#}</span>
|
||||
</a>
|
||||
|
||||
{if $smarty.const.UGROUP==1 || $c.comment_author_id==$smarty.session.user_id}
|
||||
<a class="popup" href="javascript:void(0);" onclick="popup('index.php?parent={$c.Id}&docid={$smarty.request.id|escape}&module=comment&action=edit&pop=1&Id={$c.Id}&theme={$theme}','comment','500','620','1');">
|
||||
<img src="modules/comment/templates/images/edit.gif" alt="" border="0" /><span>{#COMMENT_EDIT_LINK#}</span></a>
|
||||
{/if}
|
||||
|
||||
{if $smarty.const.UGROUP==1}
|
||||
<a class="popup" href="javascript:void(0);" onclick="popup('index.php?parent={$c.Id}&docid={$smarty.request.id|escape}&module=comment&action=delete&pop=1&Id={$c.Id}','comment','100','100','1');">
|
||||
<img src="modules/comment/templates/images/trash.gif" alt="" border="0" /><span>{#COMMENT_DELETE_LINK#}</span>
|
||||
</a>
|
||||
{if $c.comment_status!=1}
|
||||
<a class="popup" href="javascript:void(0);" onclick="popup('index.php?parent={$c.Id}&docid={$smarty.request.id|escape}&module=comment&action=unlock&pop=1&Id={$c.Id}','comment','100','100','1');">
|
||||
<img src="modules/comment/templates/images/unlock.gif" alt="" border="0" /><span>{#COMMENT_UNLOCK_LINK#}</span>
|
||||
</a>
|
||||
{else}
|
||||
<a class="popup" href="javascript:void(0);" onclick="popup('index.php?parent={$c.Id}&docid={$smarty.request.id|escape}&module=comment&action=lock&pop=1&Id={$c.Id}','comment','100','100','1');">
|
||||
<img src="modules/comment/templates/images/lock.gif" alt="" border="0" /><span>{#COMMENT_LOCK_LINK#}</span>
|
||||
</a>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="mod_comment_text">
|
||||
{$c.comment_text}
|
||||
{if $c.comment_changed > 1}<br /><span class="mod_comment_changed">{#COMMENT_TEXT_CHANGED#} {$c.comment_changed}</span>{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{if $smarty.request.subaction=='showonly' && $smarty.request.comment_id==$c.Id}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{foreach from=$comments[$c.Id] item=sc}
|
||||
<div class="mod_comment_ans_box">
|
||||
{if $smarty.request.subaction=='showonly' && $smarty.request.comment_id==$sc.Id}
|
||||
<div class="mod_comment_highlight">
|
||||
{/if}
|
||||
|
||||
<table width="100%" border="0" cellpadding="0" cellspacing="0" class="mod_comment_box">
|
||||
<tr>
|
||||
<td class="mod_comment_header">
|
||||
<div class="mod_comment_author">
|
||||
<a name="{$sc.Id}"></a>{#COMMENT_TEXT_ANSWER#} <a title="{#COMMENT_INFO#}" href="javascript:void(0);" onclick="popup('index.php?module=comment&action=postinfo&pop=1&Id={$sc.Id}&theme={$theme}','comment','500','300','1');">{$sc.comment_author_name}{*|stripslashes|escape:html*}</a> ({$sc.comment_published}){if $smarty.const.UGROUP==1} IP:{$sc.comment_author_ip}{/if}
|
||||
</div>
|
||||
|
||||
<div class="mod_comment_icons">
|
||||
{if $smarty.const.UGROUP==1 || $sc.comment_author_id==$smarty.session.user_id}
|
||||
<a title="{#COMMENT_EDIT_LINK#}" href="javascript:void(0);" onclick="popup('index.php?parent={$sc.Id}&docid={$smarty.request.id|escape}&module=comment&action=edit&pop=1&Id={$sc.Id}&theme={$theme}','comment','500','620','1');"><img src="modules/comment/templates/images/edit.gif" alt="" border="0" /></a>
|
||||
{/if}
|
||||
|
||||
{if $smarty.const.UGROUP==1}
|
||||
<a title="{#COMMENT_DELETE_LINK#}" href="javascript:void(0);" onclick="popup('index.php?parent={$sc.Id}&docid={$smarty.request.id|escape}&module=comment&action=delete&pop=1&Id={$sc.Id}','comment','100','100','1');"><img src="modules/comment/templates/images/trash.gif" alt="" border="0" /></a>
|
||||
{if $sc.comment_status!=1}
|
||||
<a title="{#COMMENT_UNLOCK_LINK#}" href="javascript:void(0);" onclick="popup('index.php?parent={$sc.Id}&docid={$smarty.request.id|escape}&module=comment&action=unlock&pop=1&Id={$sc.Id}','comment','100','100','1');"><img src="modules/comment/templates/images/unlock.gif" alt="" border="0" /></a>
|
||||
{else}
|
||||
<a title="{#COMMENT_LOCK_LINK#}" href="javascript:void(0);" onclick="popup('index.php?parent={$sc.Id}&docid={$smarty.request.id|escape}&module=comment&action=lock&pop=1&Id={$sc.Id}','comment','100','100','1');"><img src="modules/comment/templates/images/lock.gif" alt="" border="0" /></a>
|
||||
{/if}
|
||||
{else}
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="mod_comment_text">
|
||||
{$sc.comment_text}
|
||||
{if $sc.comment_changed > 1}<br /><span class="mod_comment_changed">{#COMMENT_TEXT_CHANGED#} {$sc.comment_changed}</span>{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{if $smarty.request.subaction=='showonly' && $smarty.request.comment_id==$sc.Id}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/foreach}
|
||||
{/foreach}
|
||||
|
||||
{if $smarty.foreach.co.last}<a name="end"></a>{/if}
|
||||
|
||||
{/if}
|
||||
193
templates/comments_tree.tpl
Normal file
193
templates/comments_tree.tpl
Normal file
@@ -0,0 +1,193 @@
|
||||
{if $display_comments==1}
|
||||
|
||||
{* ===================================================================== *}
|
||||
{* НОВОЕ: ПРОВЕРКА ПРАВ НА ЧТЕНИЕ (самый высокий приоритет) *}
|
||||
{* ===================================================================== *}
|
||||
{if $no_read_permission == 1}
|
||||
<div class="alert alert-warning" role="alert">{#COMMENT_READ_FALSE#}</div>
|
||||
|
||||
{else}
|
||||
{* ===================================================================== *}
|
||||
{* ВСЁ СУЩЕСТВУЮЩЕЕ СОДЕРЖИМОЕ БЛОКА КОММЕНТАРИЕВ (если права есть) *}
|
||||
{* ===================================================================== *}
|
||||
|
||||
<h3 class="mb-3">
|
||||
{#COMMENT_SITE_TITLE#}
|
||||
{if $closed==1 && $smarty.const.UGROUP!=1}
|
||||
<span class="badge bg-secondary ms-2">{#COMMENT_SITE_CLOSED#}</span>
|
||||
{/if}
|
||||
</h3>
|
||||
|
||||
<div class="d-flex mb-4 align-items-center">
|
||||
{* Кнопка "Добавить комментарий" - ведет к якорю формы *}
|
||||
<a href="#end" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-plus-circle me-1"></i> {#COMMENT_SITE_ADD#}
|
||||
</a>
|
||||
|
||||
{if $smarty.const.UGROUP==1}
|
||||
{* Кнопки управления комментированием для Администратора *}
|
||||
{if $closed==1}
|
||||
<a id="mod_comment_open" href="javascript:void(0);" class="btn btn-sm btn-outline-success ms-3">
|
||||
<i class="bi bi-lock-fill me-1"></i> {#COMMENT_SITE_OPEN#}
|
||||
</a>
|
||||
{else}
|
||||
<a id="mod_comment_close" href="javascript:void(0);" class="btn btn-sm btn-outline-danger ms-3">
|
||||
<i class="bi bi-unlock-fill me-1"></i> {#COMMENT_SITE_CLOSE#}
|
||||
</a>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{* ИСПРАВЛЕНИЕ 1: Добавлена проверка isset() для безопасного доступа к $comments[0] *}
|
||||
{if isset($comments[0])}
|
||||
<div class="comments-list">
|
||||
{include file="$subtpl" subcomments=$comments[0]}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<a id="end"></a>
|
||||
|
||||
{* ===================================================================== *}
|
||||
{* ФОРМА ДОБАВЛЕНИЯ КОММЕНТАРИЯ (MODAL/BLOCK) *}
|
||||
{* ===================================================================== *}
|
||||
<div class="mt-5">
|
||||
{if $closed==1 && $smarty.const.UGROUP!=1}
|
||||
<div class="alert alert-info">{#COMMENT_NEW_CLOSED#}</div>
|
||||
{elseif $cancomment!=1 && $smarty.const.UGROUP!=1}
|
||||
<div class="alert alert-info">{#COMMENT_NEW_FALSE#}</div>
|
||||
{else}
|
||||
<div id="mod_comment_new" class="card shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
<h4 class="mb-0">{#COMMENT_NEW_TITLE#}</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4" id="forms">
|
||||
<form method="post" action="{$ABS_PATH}">
|
||||
|
||||
<fieldset>
|
||||
<legend class="d-none">Форма добавления комментария</legend>
|
||||
|
||||
{* Блок для имени и email (скрытые поля для авторизованных) *}
|
||||
{if $smarty.session.user_group != '2'}
|
||||
{* АВТОРИЗОВАННЫЙ ПОЛЬЗОВАТЕЛЬ *}
|
||||
<input name="comment_author_name" type="hidden" id="in_author_name" value="{if isset($smarty.session.user_name)}{$smarty.session.user_name|escape|stripslashes}{/if}" />
|
||||
{* ИСПРАВЛЕНИЕ: Добавлена проверка isset для user_email *}
|
||||
{if isset($smarty.session.user_email) && $smarty.session.user_email != ''}
|
||||
<input name="comment_author_email" type="hidden" id="in_author_email" value="{$smarty.session.user_email|escape|stripslashes}" />
|
||||
{/if}
|
||||
{else}
|
||||
{* ГОСТЬ (требуется ввод имени) *}
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<label for="in_author_name" class="form-label">{#COMMENT_YOUR_NAME#}</label>
|
||||
<input name="comment_author_name" type="text" id="in_author_name" class="form-control" placeholder="{#COMMENT_YOUR_NAME#}" value="{if isset($smarty.request.comment_author_name)}{$smarty.request.comment_author_name|escape|stripslashes}{/if}" />
|
||||
</div>
|
||||
|
||||
{* ГОСТЬ (email) *}
|
||||
<div class="col-md-6">
|
||||
<label for="in_author_email" class="form-label">{#COMMENT_YOUR_EMAIL#}</label>
|
||||
<input name="comment_author_email" type="email" id="in_author_email" class="form-control" placeholder="{#COMMENT_YOUR_EMAIL#}" value="{if isset($smarty.request.comment_author_email)}{$smarty.request.comment_author_email|escape|stripslashes}{/if}" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{* Сайт и Город *}
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<label for="in_author_website" class="form-label">{#COMMENT_YOUR_SITE#} (необязательно)</label>
|
||||
{* ИСПРАВЛЕНИЕ 2: Безопасное чтение comment_author_website через if/else *}
|
||||
<input name="comment_author_website" type="text" id="in_author_website" class="form-control" placeholder="{#COMMENT_YOUR_SITE#}" value="{if isset($smarty.request.comment_author_website)}{$smarty.request.comment_author_website|escape|stripslashes}{else}{/if}" />
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="in_author_city" class="form-label">{#COMMENT_YOUR_FROM#} (необязательно)</label>
|
||||
{* ИСПРАВЛЕНИЕ 3: Безопасное чтение comment_author_city через if/else *}
|
||||
<input name="comment_author_city" type="text" id="in_author_city" class="form-control" placeholder="{#COMMENT_YOUR_FROM#}" value="{if isset($smarty.request.comment_author_city)}{$smarty.request.comment_author_city|escape|stripslashes}{else}{/if}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* Текст комментария *}
|
||||
<div class="mb-3">
|
||||
<label for="in_message" class="form-label">{#COMMENT_YOUR_TEXT#}*</label>
|
||||
<textarea rows="8" name="comment_text" id="in_message" class="form-control" placeholder="{#COMMENT_YOUR_TEXT#}"></textarea>
|
||||
</div>
|
||||
|
||||
{* Оставшиеся символы *}
|
||||
<p class="text-end text-muted small">
|
||||
{#COMMENT_CHARS_LEFT#} <span class="charsLeft fw-bold" id="charsLeft_new"></span>
|
||||
</p>
|
||||
|
||||
{* CAPTCHA *}
|
||||
{if $im}
|
||||
<div class="row mb-3 align-items-center">
|
||||
<div class="col-md-4">
|
||||
<label for="securecode" class="form-label">{#COMMENT_FORM_CODE#}</label>
|
||||
<span id="captcha" class="d-block mb-2">
|
||||
<img src="{$ABS_PATH}inc/captcha.php" alt="{#COMMENT_FORM_CODE#}" class="img-fluid border rounded" style="cursor: pointer;" width="120" height="60" border="0" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label for="securecode" class="form-label">{#COMMENT_FORM_CODE_ENTER#}*</label>
|
||||
<input name="securecode" type="text" id="securecode" maxlength="10" class="form-control" placeholder="{#COMMENT_FORM_CODE_ENTER#}" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{* Кнопки отправки *}
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-success me-2">
|
||||
<i class="bi bi-send-fill me-1"></i> {#COMMENT_BUTTON_ADD#}
|
||||
</button>
|
||||
<button type="reset" id="buttonReset" class="btn btn-secondary">
|
||||
<i class="bi bi-x-circle me-1"></i> Сбросить
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{* Скрытые поля *}
|
||||
<input name="module" type="hidden" value="comment" />
|
||||
<input name="action" type="hidden" value="comment" />
|
||||
<input name="sub" type="hidden" value="send" />
|
||||
<input name="doc_id" type="hidden" value="{$smarty.request.id|escape}" />
|
||||
<input name="parent_id" id="parent_id" type="hidden" value="" />
|
||||
<input name="page" type="hidden" value="{$page}" />
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div> {* <-- Закрывает mt-5 для формы *}
|
||||
|
||||
{if $page_nav}
|
||||
<div class="page_navigation_box mt-4">
|
||||
<nav aria-label="Comment Page Navigation">{$page_nav}</nav>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<script type="text/javascript">
|
||||
var COMMENT_SITE_CLOSE = '{#COMMENT_SITE_CLOSE#}';
|
||||
var COMMENT_SITE_OPEN = '{#COMMENT_SITE_OPEN#}';
|
||||
var COMMENT_LOCK_LINK = '{#COMMENT_LOCK_LINK#}';
|
||||
var COMMENT_EDIT_LINK = '{#COMMENT_EDIT_LINK#}';
|
||||
var COMMENT_EDIT_TITLE = '{#COMMENT_EDIT_TITLE#}';
|
||||
var COMMENT_UNLOCK_LINK = '{#COMMENT_UNLOCK_LINK#}';
|
||||
var COMMENT_ERROR_AUTHOR = '{#COMMENT_ERROR_AUTHOR#}';
|
||||
var COMMENT_ERROR_EMAIL = '{#COMMENT_ERROR_EMAIL#}';
|
||||
var COMMENT_ERROR_TEXT = '{#COMMENT_ERROR_TEXT#}';
|
||||
var COMMENT_ERROR_CAPTCHA = '{#COMMENT_ERROR_CAPTCHA#}';
|
||||
var COMMENT_BUTTON_EDIT = '{#COMMENT_BUTTON_EDIT#}';
|
||||
var COMMENT_BUTTON_CANCEL = '{#COMMENT_BUTTON_CANCEL#}';
|
||||
var COMMENT_CHARS_LEFT = '{#COMMENT_CHARS_LEFT#}';
|
||||
var COMMENT_DATE_TIME_FORMAT = '{#COMMENT_DATE_TIME_FORMAT#}';
|
||||
var COMMENT_TEXT_CHANGED = '{#COMMENT_TEXT_CHANGED#}';
|
||||
var COMMENT_WRONG_CODE = '{#COMMENT_WRONG_CODE#}';
|
||||
var UGROUP = '{$smarty.const.UGROUP}';
|
||||
var IS_IM = '{$im}';
|
||||
var DOC_ID = '{$doc_id}';
|
||||
var MAX_CHARS = '{$comment_max_chars}';
|
||||
var aveabspath = '{$ABS_PATH}';
|
||||
</script>
|
||||
<script src="{$ABS_PATH}modules/comment/js/comment.js" type="text/javascript"></script>
|
||||
|
||||
{/if} {* <-- Закрывает if $no_read_permission *}
|
||||
|
||||
{/if}
|
||||
90
templates/comments_tree_sub.tpl
Normal file
90
templates/comments_tree_sub.tpl
Normal file
@@ -0,0 +1,90 @@
|
||||
{foreach from=$subcomments item=c}
|
||||
|
||||
{* Контейнер комментария: Используем .card для блока, и ms-4 для вложенности *}
|
||||
<div class="card mb-3 mod_comment_comment{if $c.parent_id} ms-4{/if}">
|
||||
|
||||
{* Подсветка (Highlight) *}
|
||||
{if isset($smarty.request.subaction) && $smarty.request.subaction=='showonly' && isset($smarty.request.comment_id) && $smarty.request.comment_id==$c.Id}
|
||||
<div class="border border-warning border-3 rounded p-0">
|
||||
{/if}
|
||||
|
||||
<div id="{$c.Id}" class="mod_comment_box">
|
||||
|
||||
{* Заголовок комментария: Используем card-header и d-flex для выравнивания метаданных и иконок *}
|
||||
<div class="card-header mod_comment_header d-flex justify-content-between align-items-center bg-light clearfix">
|
||||
|
||||
{* Информация об авторе и дате *}
|
||||
<div class="mod_comment_author text-muted small me-2">
|
||||
{* Автор (Иконка fa-user) *}
|
||||
<i class="fa fa-user me-1"></i> {#COMMENT_USER_ADD#} <a title="{#COMMENT_INFO#}" href="javascript:void(0);" onclick="popup('{$ABS_PATH}index.php?module=comment&action=postinfo&pop=1&Id={$c.Id}&theme={$theme}','comment','500','300','1');" class="fw-bold link-dark">{$c.comment_author_name|stripslashes|escape}</a>
|
||||
|
||||
{* Дата публикации (Иконка fa-clock) *}
|
||||
<span class="ms-2"><i class="fa fa-clock-o me-1"></i> {$c.comment_published}</span>
|
||||
|
||||
{* IP-адрес (для Админа) *}
|
||||
{if $smarty.const.UGROUP==1}
|
||||
<span class="ms-2 text-secondary">• IP:{$c.comment_author_ip}</span>
|
||||
{/if}
|
||||
|
||||
{* Метка "Изменено" *}
|
||||
<span class="mod_comment_changed">{if isset($c.comment_changed) && $c.comment_changed > 1} (<span class="text-secondary">{#COMMENT_TEXT_CHANGED#} {$c.comment_changed}</span>){/if}</span>
|
||||
</div>
|
||||
|
||||
{* Иконки действий - Используем p-2 me-3 для интервала и кликабельности *}
|
||||
<div class="mod_comment_icons d-flex align-items-center flex-shrink-0">
|
||||
|
||||
{* Ссылка "Ответить" (fa-reply) *}
|
||||
{if $c.comment_author_id!=$smarty.session.user_id|default:'*' && (($cancomment==1 && $closed!=1) || $smarty.const.UGROUP==1)}
|
||||
<a class="mod_comment_answer p-2 me-3 text-primary" href="javascript:void(0);" rel="{$c.Id}" title="{#COMMENT_ANSWER_LINK#}">
|
||||
<i class="fa fa-reply"></i>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{* ИКОНКА РЕДАКТИРОВАНИЯ (fa-pencil) *}
|
||||
{if $smarty.const.UGROUP==1 || $c.comment_author_id==$smarty.session.user_id|default:'*'}
|
||||
<a class="mod_comment_edit p-2 me-3 text-secondary" href="javascript:void(0);" title="{#COMMENT_EDIT_LINK#}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{if $smarty.const.UGROUP==1}
|
||||
{* Замок (Разблокировать/Заблокировать) *}
|
||||
{if $c.comment_status!=1}
|
||||
<a class="mod_comment_unlock p-2 me-3 text-success" href="javascript:void(0);" title="{#COMMENT_UNLOCK_LINK#}">
|
||||
<i class="fa fa-unlock"></i>
|
||||
</a>
|
||||
{else}
|
||||
<a class="mod_comment_lock p-2 me-3 text-dark" href="javascript:void(0);" title="{#COMMENT_LOCK_LINK#}">
|
||||
<i class="fa fa-lock"></i>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{* Корзина (Удалить) *}
|
||||
<a class="mod_comment_delete p-2 text-danger" href="javascript:void(0);" title="{#COMMENT_DELETE_LINK#}">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* Тело комментария: Используем card-body *}
|
||||
<div class="card-body mod_comment_text{if $smarty.const.UGROUP==1 || $c.comment_author_id==$smarty.session.user_id|default:'*'} editable_text{/if}">{$c.comment_text|escape}</div>
|
||||
</div>
|
||||
|
||||
{* Закрываем подсветку *}
|
||||
{if isset($smarty.request.subaction) && $smarty.request.subaction=='showonly' && isset($smarty.request.comment_id) && $smarty.request.comment_id==$c.Id}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{* Точка вставки формы ответа *}
|
||||
<span id="end{$c.Id}"></span>
|
||||
|
||||
{* Рекурсивный вызов дочерних комментариев *}
|
||||
{if isset($comments) && isset($comments[$c.Id])}
|
||||
<div class="mt-3">
|
||||
{include file="$subtpl" subcomments=$comments[$c.Id] sub=1}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div> {* Закрывает mod_comment_comment *}
|
||||
{/foreach}
|
||||
BIN
templates/images/edit.gif
Normal file
BIN
templates/images/edit.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 67 B |
BIN
templates/images/lock.gif
Normal file
BIN
templates/images/lock.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 B |
BIN
templates/images/reply.gif
Normal file
BIN
templates/images/reply.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 B |
BIN
templates/images/trash.gif
Normal file
BIN
templates/images/trash.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 B |
BIN
templates/images/unlock.gif
Normal file
BIN
templates/images/unlock.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 67 B |
4
templates/index.php
Normal file
4
templates/index.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
header('Location:/');
|
||||
exit;
|
||||
?>
|
||||
Reference in New Issue
Block a user