Файл forums.posts.php в Cotonti. Часть 2
Начинаем изучать код файла "forums.posts.php" в Cotonti CMF, который находится в дириктории: /modules/forums/inc/ php-фреймворка.
Filed under: Модуль Forums в Cotonti CMF
if ($a == 'newpost' && !empty($s) && !empty($q)) // Проверяем, что действие $a равно 'newpost' (новый пост), а также что заданы переменные $s (раздел форума) и $q (ID темы).
{
cot_shield_protect(); // Защита от спама и флудеров с помощью встроенного механизма Cotonti.
Cot::$db->query("SELECT ft_state FROM $db_forum_topics WHERE ft_id = $q")->fetchColumn() && cot_die();
// Выполняем SQL-запрос к базе данных, чтобы получить состояние (ft_state) темы с ID $q.
// Если запрос вернул ненулевое значение (тема закрыта или удалена), вызываем `cot_die()`, завершив выполнение скрипта.
$sql_forums = Cot::$db->query("SELECT fp_id, fp_text, fp_posterid, fp_creation, fp_updated, fp_updater FROM $db_forum_posts
WHERE fp_topicid = $q ORDER BY fp_creation DESC LIMIT 1");
// Запрашиваем последний пост в теме $q, сортируя их по дате создания (fp_creation) в порядке убывания (DESC),
// чтобы получить самый новый пост (LIMIT 1).
if ($row = $sql_forums->fetch()) { // Если удалось получить данные последнего поста:
if (
Cot::$cfg['forums']['antibumpforums'] // Проверяем, включена ли функция защиты от "бампинга" (искусственного поднятия темы).
&& (
(Cot::$usr['id'] == 0 && $row['fp_posterid'] == 0 && $row['fp_posterip'] == Cot::$usr['ip'])
// Если текущий пользователь не авторизован (гость), а IP последнего поста совпадает с его IP, запрещаем отправку нового поста.
|| ($row['fp_posterid'] > 0 && $row['fp_posterid'] == Cot::$usr['id'])
// Если последний пост принадлежит текущему пользователю (авторизованному), запрещаем отправку нового поста.
)
) {
cot_die(); // Завершаем выполнение, если обнаружена попытка "бампинга".
}
$merge = (!Cot::$cfg['forums']['antibumpforums'] && Cot::$cfg['forums']['mergeforumposts'] && $row['fp_posterid'] == Cot::$usr['id']) ? true : false;
// Проверяем, можно ли объединить новый пост с последним постом.
// Это возможно, если:
// - Отключена защита от бампинга (`antibumpforums = false`).
// - Включена настройка объединения сообщений (`mergeforumposts = true`).
// - Последний пост написан текущим пользователем.
$merge = ($merge && Cot::$cfg['forums']['mergetimeout'] > 0 && (($sys['now'] - $row['fp_updated']) > (Cot::$cfg['forums']['mergetimeout'] * 3600))) ? false : $merge;
// Если объединение сообщений разрешено (`$merge = true`), проверяем, не истек ли лимит времени для объединения (`mergetimeout`).
// Если время между обновлением последнего поста (`fp_updated`) и текущим моментом (`sys['now']`) больше лимита (`mergetimeout` в часах),
// то объединение отменяется (`$merge = false`).
} else {
cot_die(); // Если в теме еще нет постов (запрос `$sql_forums` не вернул строк), выполнение скрипта завершается.
}
Объяснение логики:
- Проверка входных данных
- Убедимся, что действие
$a— этоnewpost(новый пост). - Проверяем, что заданы идентификаторы
$s(раздел форума) и$q(ID темы).
- Убедимся, что действие
- Защита от спама
- Функция
cot_shield_protect()предотвращает флуд и возможные атаки.
- Функция
- Проверка состояния темы
- Выполняется SQL-запрос, чтобы проверить состояние темы (
ft_state). - Если тема закрыта (
ft_stateне пустое), то выполнение прекращается.
- Выполняется SQL-запрос, чтобы проверить состояние темы (
- Получение последнего поста в теме
- Запрос выбирает последний пост в теме (сортировка
ORDER BY fp_creation DESC).
- Запрос выбирает последний пост в теме (сортировка
- Проверка на "бампинг"
- Если активирована настройка
antibumpforums, проверяется, чтобы пользователь не "поднимал" тему. - Если последний пост сделан этим же пользователем, то новый пост запрещается.
- Если активирована настройка
- Объединение постов
- Если активирована настройка
mergeforumposts, новый пост объединяется с последним, если его автор тот же. - Однако, если прошло больше времени, чем указано в
mergetimeout, объединение отменяется.
- Если активирована настройка
- Если тема пуста — выход
- Если в теме еще нет сообщений, выполнение скрипта завершается (
cot_die()).
- Если в теме еще нет сообщений, выполнение скрипта завершается (
$rmsg = array();
// Инициализация массива $rmsg для хранения данных нового поста.
$rmsg['fp_text'] = cot_import('rmsgtext', 'P', 'HTM');
// Импорт текста нового сообщения (из POST-параметра 'rmsgtext'), который будет сохранен как HTML.
$rmsg['fp_updated'] = (int)$sys['now'];
// Устанавливаем время обновления поста (текущее время из системы).
$rmsg['fp_posterip'] = Cot::$usr['ip'];
// Сохраняем IP-адрес пользователя, который создает новый пост.
if (mb_strlen($rmsg['fp_text']) < Cot::$cfg['forums']['minpostlength']) {
// Проверяем, что длина текста сообщения больше минимальной длины, заданной в конфигурации форума.
cot_error('forums_messagetooshort', 'rmsgtext');
// Если длина текста слишком короткая, вызываем ошибку с сообщением 'forums_messagetooshort' для поля 'rmsgtext'.
cot_redirect(cot_url('forums', "m=posts&q=$q&n=last", '#bottom', true));
// Перенаправляем пользователя обратно на страницу форума, на последний пост (с добавлением якоря '#bottom' для прокрутки).
}
if (!empty(Cot::$extrafields[Cot::$db->forum_posts])) {
// Если существуют дополнительные поля для постов форума (поля, определенные в конфигурации форума).
foreach (Cot::$extrafields[Cot::$db->forum_posts] as $exfld) {
// Перебираем все дополнительные поля.
$rmsg['fp_' . $exfld['field_name']] = cot_import_extrafields('rmsg' . $exfld['field_name'], $exfld, 'P', '', 'forums_post_');
// Импортируем значения этих дополнительных полей через функцию cot_import_extrafields и сохраняем их в массив $rmsg.
}
}
foreach (cot_getextplugins('forums.posts.newpost.first') as $pl) {
// Выполняем хуки, если они есть, для действия 'forums.posts.newpost.first' (перед созданием нового поста).
include $pl;
// Подключаем каждый плагин, который расширяет функционал на этом этапе.
}
Объяснение логики:
- Инициализация массива
- Создается массив
$rmsg, который будет хранить данные нового поста.
- Создается массив
- Импорт текста поста
- Текст сообщения (
rmsgtext) импортируется с помощью функцииcot_import(). В данном случае, текст обрабатывается как HTML.
- Текст сообщения (
- Проверка минимальной длины сообщения
- Если длина текста сообщения меньше минимально установленной длины (
minpostlength), пользователю выводится ошибка, и он перенаправляется обратно на форум.
- Если длина текста сообщения меньше минимально установленной длины (
- Обработка дополнительных полей
- Если в таблице постов форума определены дополнительные поля (например, кастомные поля), они импортируются и добавляются в массив
$rmsg.
- Если в таблице постов форума определены дополнительные поля (например, кастомные поля), они импортируются и добавляются в массив
- Выполнение хуков
- Если существуют плагины, подключенные к хуку
forums.posts.newpost.first, они выполняются. Это позволяет расширить функциональность при создании нового поста, например, добавлением дополнительной обработки перед сохранением поста.
- Если существуют плагины, подключенные к хуку
if (!cot_error_found()) {
// Проверяем, если нет ошибок, которые были добавлены ранее с помощью cot_error().
if (!$merge) {
// Если пост не нужно сливать с предыдущим (нет режима слияния сообщений).
$rmsg['fp_topicid'] = (int) $q;
// Устанавливаем ID темы (используем значение переменной $q, которое хранит ID темы).
$rmsg['fp_cat'] = $s;
// Устанавливаем категорию форума (с помощью переменной $s).
$rmsg['fp_posterid'] = (int) Cot::$usr['id'];
// Устанавливаем ID пользователя, который создает пост (из информации о пользователе Cot::$usr).
$rmsg['fp_postername'] = Cot::$usr['name'];
// Устанавливаем имя пользователя, который создает пост.
$rmsg['fp_creation'] = (int) $sys['now'];
// Устанавливаем дату создания поста (текущее время системы).
$rmsg['fp_updater'] = 0;
// Устанавливаем поле обновления в 0, так как это новый пост.
Cot::$db->insert($db_forum_posts, $rmsg);
// Вставляем новый пост в таблицу форумов ($db_forum_posts).
$p = Cot::$db->lastInsertId();
// Получаем ID последнего вставленного поста.
cot_forums_resyncTopic($q, Cot::$usr['id']);
// Пересчитываем статистику темы (например, обновляем время последнего поста, количество сообщений и т. д.).
cot_forums_updateStructureCounters($s);
// Обновляем счетчики категорий форума для текущей категории.
} else {
// Если пост нужно слить с предыдущим (режим слияния сообщений).
$p = (int) $row['fp_id'];
// Получаем ID поста, который будет слит (из строки $row).
$gap_base = empty($row['fp_updated']) ? $row['fp_creation'] : $row['fp_updated'];
// Если у предыдущего поста нет времени обновления, используем время его создания. Иначе, используем время последнего обновления.
$updated = sprintf(Cot::$L['forums_mergetime'], cot_build_timegap($gap_base, Cot::$sys['now']));
// Создаем строку, которая показывает разницу во времени между предыдущим и текущим сообщением.
$rmsg['fp_text'] = $row['fp_text'] . cot_rc('forums_code_update', array('updated' => $updated)) . $rmsg['fp_text'];
// Добавляем в текст нового сообщения информацию о времени обновления, а затем добавляем сам текст нового поста.
$rmsg['fp_updater'] = ($row['fp_posterid'] == Cot::$usr['id'] && ($sys['now'] < $row['fp_updated'] + 300) && empty($row['fp_updater']) ) ? '' : Cot::$usr['name'];
// Устанавливаем поле обновления в имя пользователя, если пост обновляется (если прошло меньше 5 минут с последнего обновления).
Cot::$db->update($db_forum_posts, $rmsg, 'fp_id=' . $row['fp_id']);
// Обновляем пост в таблице форумов ($db_forum_posts) с новыми данными из массива $rmsg.
Cot::$db->update($db_forum_topics, array('ft_updated' => $sys['now']), "ft_id = $q");
// Обновляем время последнего поста в теме (таблица $db_forum_topics).
cot_forums_resyncTopic($q, false);
// Пересчитываем статистику темы без изменения ID пользователя.
cot_forums_updateStructureCounters($s);
// Обновляем счетчики категории форума.
}
}
Объяснение логики:
- Проверка наличия ошибок
- Код выполняется, если нет ошибок, с помощью проверки
!cot_error_found(). Это позволяет убедиться, что до выполнения не произошло ошибок, связанных с данными, переданными в форму.
- Код выполняется, если нет ошибок, с помощью проверки
- Создание нового поста (если не используется слияние)
- Если не нужно сливать пост с предыдущим (переменная
$mergeравнаfalse), то:- Вставляется новый пост с данными о теме, категории, авторе, времени создания.
- Также выполняется пересинхронизация статистики темы и обновление счетчиков категории.
- Если не нужно сливать пост с предыдущим (переменная
- Слияние постов (если используется слияние)
- Если активирован режим слияния сообщений (переменная
$mergeравнаtrue), то:- Получаем ID поста, с которым нужно выполнить слияние.
- Вычисляется разница во времени между текущим и предыдущим сообщением.
- В текст нового сообщения добавляется информация о времени обновления.
- Обновляется информация о посте в базе данных, и тема обновляется с новым временем последнего поста.
- Если активирован режим слияния сообщений (переменная
- Пересинхронизация и обновление статистики
- После добавления или обновления поста, выполняются два важных действия:
- Пересинхронизация статистики темы (
cot_forums_resyncTopic). - Обновление счетчиков категории форума (
cot_forums_updateStructureCounters).
- Пересинхронизация статистики темы (
- После добавления или обновления поста, выполняются два важных действия:
cot_extrafield_movefiles();
// Перемещает файлы, связанные с дополнительными полями (например, изображения или прикрепленные файлы), если они были загружены при создании нового поста.
/* === Hook === */
foreach (cot_getextplugins('forums.posts.newpost.done') as $pl) {
include $pl;
}
// Запускаются все внешние плагины, связанные с окончанием создания нового поста в форуме. Эти плагины могут добавлять дополнительный функционал.
/* ===== */
if (Cot::$cache) {
// Проверяем, включено ли кэширование в системе.
if (Cot::$cfg['cache_forums']) {
// Если кэширование для форума включено.
// Cot::$cache->page->clearByUri(cot_url('forums', ['m' => 'posts', 'q' => $q]));
// Удаление страницы кэша по URL форума и текущей теме (эта строка закомментирована).
Cot::$cache->static->clearByUri(cot_url('forums'));
// Очистка кэша для всего форума, если обновился какой-либо контент.
}
if (Cot::$cfg['cache_index']) {
// Если включено кэширование главной страницы.
Cot::$cache->static->clear('index');
// Очистка кэша для главной страницы сайта.
}
}
cot_shield_update(30, "New post");
// Обновление защиты от повторных отправок формы (например, защиты от спама). Параметры определяют период (30 секунд) и сообщение.
cot_redirect(
cot_url('forums', ['m' => 'posts', 'q' => $q, 'n' => 'last'], '#bottom', true)
);
// Перенаправление на страницу форума, где отображается последний пост в теме. URL включает параметры: ID темы ($q) и переход к последнему сообщению ('n' => 'last').
// #bottom указывает браузеру прокрутить страницу вниз к последнему сообщению.
Объяснение:
- Перемещение файлов с дополнительными полями
cot_extrafield_movefiles()выполняет перемещение файлов, которые могут быть прикреплены к сообщениям через дополнительные поля. Это необходимо, чтобы управлять прикрепленными файлами, например, изображениями, которые были загружены в пост.
- Запуск плагинов после создания нового поста
- Цикл
foreach (cot_getextplugins('forums.posts.newpost.done')активирует все внешние плагины, подключенные к событию завершения создания поста. Эти плагины могут выполнять дополнительные действия, такие как уведомления, аналитика, интеграции с внешними сервисами и т.д.
- Цикл
- Очистка кэша
- Если включено кэширование:
- Очистка кэша форума: если обновилась тема или пост, выполняется удаление старого кэша для форума с помощью
Cot::$cache->static->clearByUri(cot_url('forums')). - Очистка кэша главной страницы сайта, если она также кэшируется, с помощью
Cot::$cache->static->clear('index').
- Очистка кэша форума: если обновилась тема или пост, выполняется удаление старого кэша для форума с помощью
- Если включено кэширование:
- Обновление защиты от повторных отправок
- Вызов
cot_shield_update(30, "New post")обновляет защиту от повторных отправок, устанавливая 30-секундный период защиты, чтобы предотвратить повторную отправку формы при создании поста.
- Вызов
- Перенаправление после успешного создания поста
- После завершения всех операций, связанных с созданием поста, выполняется редирект на страницу с последним постом в теме. Это позволяет пользователю сразу же увидеть добавленный пост в конце обсуждения.
} elseif (
$a == 'delete' // Проверяется, что действие равно "delete" (удалить).
&& Cot::$usr['id'] > 0 // Пользователь должен быть авторизован (его ID больше 0).
&& !empty($s) // Проверяется, что передан код категории форума (раздел).
&& !empty($q) // Проверяется, что передан ID темы форума.
&& !empty($p) // Проверяется, что передан ID поста.
&& (
Cot::$usr['isadmin'] // Если пользователь является администратором, то ему разрешено удалить любой пост.
|| (
$fp_posterid == Cot::$usr['id'] // Если пользователь является автором поста, то ему разрешено удалять свои посты.
&& (
Cot::$cfg['forums']['edittimeout'] == '0' // Если настройка времени редактирования отключена (0 часов), то пользователь может удалить пост в любое время.
|| Cot::$sys['now'] - $row['fp_creation'] < Cot::$cfg['forums']['edittimeout'] * 3600 // Если прошло меньше времени, чем указано в настройке форума для редактирования поста (например, 1 час).
)
)
)
) {
cot_check_xg(); // Функция для проверки на наличие действующего токена безопасности, предотвращающая атаки типа CSRF.
/* === Hook === */
foreach (cot_getextplugins('forums.posts.delete.first') as $pl) { // Хук, который позволяет подключить плагины для выполнения действий перед удалением поста (например, логирование, уведомления).
include $pl; // Подключаем и выполняем каждый плагин, найденный для этого хука.
}
/* ===== */
// Этот блок используется для выполнения любых пользовательских действий до самого удаления поста, если такие плагины подключены.
Пояснение:
- Проверка условий:
Условие внутриelseifвыполняется только если действие ($a) равно "delete", и если все параметры (s,q,p) присутствуют и валидны. Также проверяется, что пользователь либо администратор, либо автор поста, который пытается удалить свой пост, и что время для редактирования не вышло, если оно ограничено в настройках форума. - cot_check_xg():
Это стандартная защита от CSRF (Cross-Site Request Forgery) атак. Функция проверяет, что запрос был отправлен с правильным токеном, который подтверждает, что запрос действительно был инициирован пользователем, а не злоумышленником. - Хук для плагинов:
С помощью функцииcot_getextpluginsи хука'forums.posts.delete.first'можно подключить и выполнить дополнительные действия, которые разработчики или администраторы хотят выполнить перед удалением поста. Например, это может быть создание записи в логе, отправка уведомлений пользователю или другим пользователям, проверка на выполнение дополнительных условий и так далее.
$row = Cot::$db->query("SELECT * FROM $db_forum_posts WHERE fp_id = ? AND fp_topicid = ? AND fp_cat = ? LIMIT 1", // Выполняется SQL-запрос для получения поста из базы данных, проверяя ID поста ($p), ID темы ($q) и код категории ($s).
array($p, $q, $s))->fetch(); // Подставляем параметры запроса: ID поста, ID темы и код категории.
is_array($row) || cot_die(); // Проверяется, что результат запроса представляет собой массив (т.е. пост найден). Если нет, вызывает ошибку и завершает выполнение.
$first_id = Cot::$db->query("SELECT fp_id FROM $db_forum_posts WHERE fp_topicid = ? LIMIT 1", array($q))->fetchColumn(); // Выполняется SQL-запрос для получения ID первого поста в теме ($q).
if ($p == $first_id) // Проверка, если текущий пост является первым постом в теме.
{
if (Cot::$usr['isadmin']) // Если пользователь является администратором.
{
// Если пост является первым в теме, перенаправляем на страницу подтверждения удаления темы.
cot_redirect(str_replace('&', '&', cot_confirm_url(cot_url('forums', 'm=topics&a=delete&s='.$s.'&q='.$q.'&x='.$sys['xk'], '', true), 'forums', 'forums_confirm_delete_topic')));
}
else
{
// Если пользователь не администратор, выводим ошибку (пользователи не могут удалять темы).
cot_die();
}
}
Пояснение:
- Запрос поста:
SQL-запрос извлекает данные поста из базы данных по его ID ($p), ID темы ($q) и категории ($s). После выполнения запроса, с помощью методаfetch(), извлекается одна строка данных из таблицы. Если результат не является массивом, программа завершится с ошибкой. - Проверка первого поста:
Еще один SQL-запрос извлекает ID первого поста в теме. После этого происходит проверка: если текущий пост является первым в теме (т.е. его ID совпадает с ID первого поста), то выполняется дальнейшая логика. - Удаление темы:
Если пользователь является администратором, его перенаправляют на страницу подтверждения удаления всей темы (с использованиемcot_redirect). Для этого формируется URL, который включает параметры для удаления темы (с помощью функцииcot_urlиcot_confirm_url). - Проверка прав пользователя:
Если пользователь не является администратором, программа вызывает ошибку с помощьюcot_die(), и дальнейшая обработка запроса не происходит, т.к. обычные пользователи не имеют прав на удаление темы.
foreach($cot_extrafields[$db_forum_posts] as $exfld) { // Цикл по всем дополнительным полям для таблицы постов форума.
cot_extrafield_unlinkfiles($row['fp_'.$exfld['field_name']], $exfld); // Для каждого дополнительного поля выполняется удаление связанных файлов, если они существуют. Используется функция `cot_extrafield_unlinkfiles`.
}
Cot::$db->delete($db_forum_posts, 'fp_id = ? AND fp_topicid = ? AND fp_cat = ?', array($p, $q, $s)); // Выполняется удаление поста из таблицы `db_forum_posts`, где ID поста ($p), ID темы ($q) и код категории ($s) совпадают.
cot_forums_resyncTopic($q, $fp_posterid); // Пересинхронизация темы. Эта функция обновляет информацию о теме (например, количество постов) после удаления поста.
cot_log("Deleted post #" . $p, 'forums', 'delete post', 'done'); // Логирование действия удаления поста с ID $p. В журнал записывается сообщение о выполнении операции удаления.
foreach (cot_getextplugins('forums.posts.delete.done') as $pl) { // Запуск внешних плагинов после завершения удаления поста.
include $pl; // Подключение плагинов, если они существуют.
}
Пояснение:
- Удаление файлов, связанных с дополнительными полями:
Для каждого дополнительного поля, связанного с постами в форуме, вызывается функцияcot_extrafield_unlinkfiles, которая удаляет связанные файлы (например, прикрепленные файлы или изображения). Это позволяет избежать "мертвых" ссылок или файлов, оставшихся после удаления поста. - Удаление поста:
В SQL-запросе происходит удаление записи из таблицы постов в базе данных, где значения полей ID поста, ID темы и код категории совпадают с переданными параметрами. - Пересинхронизация темы:
После удаления поста вызывается функцияcot_forums_resyncTopic, которая обновляет статистику темы (например, количество постов и другие параметры), чтобы отражать изменения. - Логирование:
Операция удаления поста логируется с помощью функцииcot_log. Это позволяет отслеживать удаление постов в административной панели и хранить запись об этом в журнале. - Запуск плагинов:
Если существуют сторонние плагины, которые должны быть выполнены после удаления поста, они будут подключены с помощью циклаforeachи функцииcot_getextplugins. Эти плагины могут выполнять дополнительные действия, такие как уведомления или обработка данных после удаления поста.
if (
Cot::$db->query('SELECT COUNT(*) FROM ' . Cot::$db->forum_posts . ' WHERE fp_topicid = ?', $q) // Выполняется запрос для подсчета количества постов в теме с ID $q.
->fetchColumn() == 0 // Если количество постов в теме равно 0 (то есть тема пуста).
) {
// Если в теме нет постов, то удаляем саму тему.
$sqlTopic = Cot::$db->query('SELECT * FROM ' . Cot::$db->forum_topics . ' WHERE ft_id = ?', $q); // Выполняется запрос, чтобы получить информацию о теме с ID $q.
if ($row = $sqlTopic->fetch()) { // Если тема существует (нашлась в базе данных).
cot_forums_prunetopics('single', $s, $q); // Вызов функции для удаления темы. Тип удаления — "single" (одиночная тема), категория — $s, ID темы — $q.
/* === Hook === */
foreach (cot_getextplugins('forums.posts.emptytopicdel') as $pl) { // Запуск плагинов, если таковые есть, для обработки удаления пустой темы.
include $pl; // Подключение плагинов.
}
/* ===== */
cot_log('Delete topic #' . $q . " (no post left)", 'forums', 'delete topic', 'done'); // Логирование события удаления темы без постов в журнал.
}
cot_forums_updateStructureCounters($s); // Обновление счетчиков структуры форума (например, количество тем в категории $s).
cot_redirect(cot_url('forums', ['m' => 'topics', 's' => $s], '', true)); // Перенаправление на список тем в категории после удаления темы.
} else {
// Если в теме остались хотя бы 1 пост.
cot_forums_updateStructureCounters($s); // Обновление счетчиков структуры форума для категории $s.
cot_redirect(
cot_url(
'forums',
['m' => 'posts', 'q' => $q, 'd' => $durl,], // Перенаправление на страницу темы с постами.
'#' . $row['fp_id'], // Переход к первому посту в теме.
true
)
);
}
Пояснение:
- Проверка наличия постов в теме:
Выполняется запрос к базе данных для подсчета количества постов в теме с помощью SQL-запроса. Если количество постов равно нулю, это означает, что тема пуста. - Удаление пустой темы:
Если тема не содержит постов, то выполняется удаление темы с использованием функцииcot_forums_prunetopics. Параметр'single'указывает, что нужно удалить только одну тему. После этого выполняется запуск плагинов черезcot_getextplugins, которые могут обрабатывать это событие (например, выполнить дополнительные действия или уведомления). - Логирование события:
Когда тема удалена, в журнал добавляется запись об этом событии с помощьюcot_log, где указано, что тема была удалена из-за отсутствия постов. - Обновление счетчиков:
После удаления темы или при нахождении постов в теме, обновляются счетчики структуры форума через функциюcot_forums_updateStructureCounters. Это необходимо для актуализации статистики, например, количество постов и тем. - Перенаправление пользователя:
Если тема была удалена, пользователя перенаправляют на страницу списка тем категории черезcot_redirect. В случае, если хотя бы один пост остался, пользователя перенаправляют на страницу с постами темы.
15 minutes read Administrator
Comments (0)
No comments yet
Only registered users can post new comments
Content author
Offline
Administrator
Last logged: 2026-07-05 18:32
- Page published: 2025-02-20 15:30
- Last update: 2026-06-27 10:57
Similar pages
Файл forums.posts.php в Cotonti. Часть 1
1 Начинаем изучать код файла "forums.posts.php" в Cotonti CMF, который находится в дириктории:
Модуль Forums в Cotonti CMF • 2025-02-20 15:27 Administrator
Файл forums.posts.php в Cotonti. Часть 3
2
$sql_forums = Cot::$db->query("SELECT * FROM $db_forum_topics WHERE ft_id= $q"); //
Модуль Forums в Cotonti CMF • 2025-02-20 15:55 Administrator
Файл forums.posts.php в Cotonti. Часть 4
3 // Устанавливаем переменную $lastpage для проверки, является ли текущая страница последней
// Вычисляем это, сравнив,
Модуль Forums в Cotonti CMF • 2025-02-20 16:14 Administrator
Файл forums.posts.php в Cotonti. Часть 5
4
// Проверяем, разрешено ли пользователю отвечать на сообщение
// Это условие проверяет несколько параметров, в
Модуль Forums в Cotonti CMF • 2025-02-20 16:24 Administrator
Файл forums.posts.php в Cotonti. завершающая часть
5
// Назначаем теги пагинации для шаблона
$t->assign(cot_generatePaginationTags($pagenav));
// Иконка
Модуль Forums в Cotonti CMF • 2025-02-20 16:32 Administrator