Файл "forums.topics.php" в Cotonti
отвечает за вывод списка тем форума, информации о темах, их постах, просмотрах, ответах, для отображения превью, ссылок на последние посты и пользователей
Файл forums.topics.php является частью модуля форума в системе управления контентом Cotonti. Этот файл располагается в директории /modules/forums/inc/, что указывает на его предназначение для обработки запросов и рендеринга контента, связанного с темами форума. Данный файл выполняет ключевую роль в обработке и отображении информации о темах форума, управлении пагинацией, взаимодействии с базой данных, а также выводе данных, которые затем отображаются на веб-странице.
Основное назначение файла
Файл forums.topics.php отвечает за вывод списка тем форума. Он выполняет запросы к базе данных для извлечения информации о темах, их постах, просмотрах, ответах и т. д. Взаимодействует с переменными, которые могут быть переданы через параметры URL или через настройки системы Cotonti. Файл управляет пагинацией, отображает тему, привязывает к ней иконки для отображения статуса (новые, горячие, закрепленные), а также предлагает функционал для отображения превью, ссылок на последние посты и пользователей, которые участвовали в обсуждении.
Место файла в системе Cotonti
Файл расположен в каталоге /modules/forums/inc/, что говорит о его принадлежности к модулю форума. Эта директория предназначена для хранения внутренних файлов модуля, которые не видны пользователю, но активно используются для обработки данных и логики. Модуль forums является частью стандартной установки Cotonti и предоставляет функционал форума, включая создание и управление темами, постами и комментариями.
Взаимодействие с другими частями сайта
- Интеракция с базой данных: Файл выполняет SQL-запросы для получения списка тем форума и их характеристик, таких как количество постов, количество просмотров, последнее сообщение, создание темы и т. д.
- Пагинация: Используется для разделения тем на страницы, чтобы избежать переполнения страницы слишком большим количеством контента.
- Шаблоны и вывод данных: С помощью шаблонизатора Cotonti данные о темах передаются в шаблон для отображения. Вся информация передается через объект шаблона $t.
- Функции и хуки: Файл активно использует хуки для расширяемости и интеграции с плагинами, например, для добавления пользовательских данных в темы форума.
- Авторизация: Проверка прав пользователей, как например, доступ к просмотру или созданию темы в зависимости от их уровня доступа.
- Кэширование: В некоторых случаях используется кэширование для ускорения работы с данными и уменьшения нагрузки на сервер.
Используемые переменные, хуки, методы, функции и классы
Переменные:
- $s - Идентификатор категории форума, передаваемый через URL. Используется для фильтрации тем по категории.
- $o - Параметр сортировки, указывающий, по какому критерию сортировать темы (например, по количеству постов или дате последнего сообщения).
- $w - Направление сортировки (по возрастанию или убыванию).
- $d - Параметр, который указывает на сдвиг для пагинации (с какой страницы начинать вывод).
- $row - Массив данных о конкретной теме, извлеченный из базы данных.
- $t - Объект шаблона, используемый для передачи данных в шаблон и вывода на экран.
Хуки:
описание каждого хука в файле "forums.topics.php":
1. forums.topics.rights
Этот хук используется для интеграции с плагинами, которые должны управлять правами доступа к темам форума. В коде он подключает все плагины, зарегистрированные для этого хука, с помощью функции cot_getextplugins('forums.topics.rights'). Каждый плагин может модифицировать или проверять права доступа пользователей к темам форума.
Пример использования:
- Добавление или изменение прав доступа на создание, редактирование или удаление тем на форуме.
2. forums.topics.delete.done
Этот хук вызывается после того, как тема была удалена. Он позволяет плагинам выполнить дополнительные действия после удаления темы, например, отправку уведомлений, логирование действий или обновление связанных данных.
Пример использования:
- Уведомление администраторов или пользователей о том, что тема была удалена.
- Логирование удаления темы в системе или обновление статистики.
3. forums.topics.first
Этот хук вызывается при первой загрузке темы форума. Обычно используется для обработки данных, которые необходимо подготовить до того, как тема будет полностью загружена на страницу.
Пример использования:
- Инициализация дополнительных данных для темы.
- Запуск логики, которая должна сработать при первом доступе к теме (например, установка меток или добавление дополнительных визуальных элементов).
4. forums.topics.main
Это основной хук, который загружает плагины, связанные с главной частью обработки тем форума. Он используется для подключений плагинов, которые должны выполнять основную логику работы с темами форума, такую как обработка запросов, отображение информации и другие важные операции.
Пример использования:
- Обработка запросов на просмотр, изменение или удаление темы.
- Взаимодействие с базой данных для загрузки или изменения данных о теме.
5. forums.topics.sections.loop (с двумя частями: Set и Include)
Этот хук разделен на два этапа:
- Set: используется для регистрации плагинов, которые будут выполняться на этапе обработки тем в разделе форума.
- Include: выполняет подключение этих плагинов и их работу. Этот хук помогает динамически изменять или расширять функциональность форума, связанного с секциями (разделами) форума.
Пример использования:
- Добавление дополнительных фильтров или настроек на страницы разделов форума.
- Включение дополнительного функционала, например, настроек отображения или пользовательских функций в разделах форума.
6. forums.topics.query
Этот хук используется для изменения или расширения SQL-запроса, который выполняется для получения списка тем форума. Плагины, зарегистрированные на этот хук, могут добавлять дополнительные условия или фильтры к запросу для получения данных о темах.
Пример использования:
- Фильтрация тем по дополнительным критериям (например, по тегам, авторам, или временным рамкам).
- Добавление пользовательских параметров в запрос, чтобы изменить стандартное поведение получения списка тем.
7. forums.topics.loop (с двумя частями: Set и Include)
Как и хук forums.topics.sections.loop, этот хук имеет две части:
- Set: регистрирует плагины, которые будут выполняться в цикле при обработке тем.
- Include: включает эти плагины и выполняет их действия. Этот хук активно используется при отображении тем форума, включая их список, страницы, сортировку и постраничный вывод.
Пример использования:
- Добавление дополнительных элементов или данных в вывод списка тем.
- Изменение внешнего вида или структуры списка тем (например, добавление кнопок для сортировки или фильтрации).
8. forums.topics.tags
Этот хук работает с тегами тем. Он позволяет плагинам подключать дополнительный функционал или обработку, связанную с тегами, прикрепленными к темам форума.
Пример использования:
- Добавление или модификация отображения тегов.
- Обработка тега как фильтра для поиска или сортировки тем форума.
Общие замечания:
-
cot_getextplugins — это функция Cotonti CMF, которая ищет и подключает плагины, зарегистрированные для определенного хука. Это позволяет расширять функциональность системы без изменения основного кода, просто добавляя плагины.
-
Принцип работы хуков: каждый хук связан с определенным этапом обработки данных или вывода контента в рамках работы с темами форума. Плагины, подключаемые к этим хукам, могут изменять стандартное поведение системы в нужный момент.
Каждый из этих хуков позволяет интегрировать внешние расширения и кастомизировать функциональность форума, улучшая гибкость и возможности системы для различных нужд.
Методы и функции:
- cot_url() - Генерирует URL для различных страниц форума или других страниц сайта.
- cot_build_timegap() - Функция, которая вычисляет разницу во времени и возвращает ее в формате, подходящем для отображения (например, "5 минут назад").
- cot_breadcrumbs() - Создает хлебные крошки (навигацию по сайту), чтобы пользователь мог видеть, где он находится в структуре сайта.
- cot_extrafield_title() - Получает название дополнительного поля (если оно есть) для тем форума.
- cot_build_user() - Функция для построения ссылки на профиль пользователя с учетом его ID и имени.
- cot_pagenav() - Генерирует пагинацию для страниц форума, позволяет разделить темы на несколько страниц.
- cot_parse() - Парсит текст с учетом BBCode или других разрешенных форматов.
- cot_build_oddeven() - Определяет четность/нечетность строки для чередования стилей отображения элементов (например, для строк в таблице).
Классы:
- Cot::$db - Содержит объект базы данных, через который выполняются SQL-запросы к базе данных форума.
- Cot::$usr - Хранит информацию о текущем пользователе, его правах доступа и идентификаторе.
- Cot::$cfg - Глобальный объект конфигурации, из которого извлекаются параметры настройки форума, такие как максимальное количество тем на странице, настройки кэширования и т. д.
- Cot::$R - Массив, содержащий различные строки (например, иконки или текст), используемые в интерфейсе форума.
- Cot::$cache - Класс для работы с кэшированием данных на сайте.
Задачи, функции и условия, выполняемые кодом:
- Извлечение данных: Код извлекает данные о темах из базы данных, включая их название, описание, количество постов, количество просмотров, последний пост, время создания и последнего обновления, а также информацию о пользователях, которые создали тему или сделали последний пост.
- Пагинация: Создание навигации по страницам форума для удобства пользователей. Это позволяет разбить темы на несколько страниц, что предотвращает перегрузку одной страницы.
- Сортировка тем: Реализация функционала сортировки тем форума по различным критериям, таким как название, количество просмотров, количество постов, дата создания и обновления.
- Обработка прав доступа: Проверка, может ли текущий пользователь видеть или взаимодействовать с определенными темами на форуме. Это зависит от его прав доступа и уровня авторизации.
- Вывод темы на экран: После того, как данные были извлечены, они передаются в шаблон для отображения пользователю. Здесь задаются переменные, такие как заголовок темы, количество постов, информация о пользователе и другие элементы.
- Расширяемость через хуки: Код использует хуки для возможности расширения функционала и подключения дополнительных плагинов, которые могут изменять запросы к базе данных или внешний вид форума.
- Кэширование: Для улучшения производительности кэшируются данные, связанные с форумом, если кэширование разрешено в конфигурации.
Таким образом, файл forums.topics.php обеспечивает обработку и вывод данных для страницы форума, реализуя основные функции форума, такие как отображение списка тем, сортировка, пагинация, доступ по правам пользователя, а также интеграция с другими частями системы через хуки и плагины.
// Проверяет, определена ли константа 'COT_CODE'. Если нет, скрипт прекращает выполнение с сообщением 'Wrong URL'.
// Это механизм защиты, который предотвращает прямой доступ к файлу.
defined('COT_CODE') or die('Wrong URL');
// Импортирует GET-параметр 's' (секция форума), ожидая строковое значение (TXT).
$s = cot_import('s','G','TXT'); // Код раздела форума
// Импортирует GET-параметр 'q' (идентификатор темы), ожидая целое число (INT).
$q = cot_import('q','G','INT'); // ID темы
// Импортирует информацию для постраничной навигации, используя параметр 'd'.
// 'Cot::$cfg['forums']['maxtopicsperpage']' указывает максимальное количество тем на странице.
list($pg, $d, $durl) = cot_import_pagenav('d', Cot::$cfg['forums']['maxtopicsperpage']); // Пагинация
// Импортирует GET-параметр 'ord', который указывает поле для сортировки. Ожидает строку до 16 символов.
// Значение 'ALP' указывает, что это буквенное поле (алфавитное).
$o = cot_import('ord','G','ALP',16); // Поле сортировки
// Импортирует GET-параметр 'w', который указывает направление сортировки (asc/desc). Ожидает строку до 4 символов.
$w = cot_import('w','G','ALP',4); // Направление сортировки
// Если параметр сортировки отсутствует или указанного поля не существует в таблице тем форума,
// то используется значение 'updated' (обновленные темы).
if (empty($o) || !Cot::$db->fieldExists($db_forum_topics, "ft_$o")) {
$o = 'updated';
}
// Если направление сортировки пустое или не равно 'asc' или 'desc',
// то по умолчанию устанавливается 'desc' (по убыванию).
$w = (empty($w) || !in_array($w, array('asc', 'desc'))) ? 'desc' : $w;
// Проверяет, передан ли параметр 's' и существует ли такая секция в структуре форума.
// Если нет, то выполнение прекращается.
cot_die(empty($s) || !isset(Cot::$structure['forums'][$s]), true);
// Получает права пользователя на чтение, запись и администрирование в данном разделе форума.
list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('forums', $s);
/* === Хук (Hook) === */
// Загружает и выполняет все плагины, привязанные к точке расширения 'forums.topics.rights'.
// Это позволяет другим плагинам вмешиваться в систему прав на просмотр тем.
foreach (cot_getextplugins('forums.topics.rights') as $pl) {
include $pl;
}
/* ===== */
// Проверяет, есть ли у пользователя право на чтение в разделе форума.
// Если прав нет, выполнение прекращается.
cot_block(Cot::$usr['auth_read']);
// Проверяет, является ли текущий пользователь администратором, и переданы ли параметры 'q' (ID темы) и 'a' (действие).
// Если все условия выполнены, продолжается выполнение кода.
if (Cot::$usr['isadmin'] && !empty($q) && !empty($a)) {
// Проверяет, был ли отправлен правильный токен безопасности (XG). Это защита от CSRF атак.
cot_check_xg();
// В зависимости от значения параметра 'a', выполняется соответствующее действие.
switch($a) {
// Если значение параметра 'a' равно 'delete', выполняется удаление темы.
case 'delete':
// Вызывает функцию для удаления темы. 'single' - удаление одной темы, '$s' - секция форума, '$q' - ID темы.
cot_forums_prunetopics('single', $s, $q);
// Логирует удаление темы в журнал. Формируется сообщение вида "Deleted topic #ID_темы".
cot_log("Deleted topic #" . $q, 'forums', 'delete topic', 'done');
/* === Хук (Hook) === */
// Загружает и выполняет все плагины, привязанные к точке расширения 'forums.topics.delete.done'.
// Это позволяет другим плагинам выполнять действия после удаления темы.
foreach (cot_getextplugins('forums.topics.delete.done') as $pl) {
include $pl;
}
/* ===== */
// Отображает сообщение об успешном удалении темы.
cot_message(Cot::$L['Deleted']);
// Перенаправляет пользователя обратно на страницу форума, с параметром 'm' = 'topics' и выбранной секцией.
cot_redirect(cot_url('forums', ['m' => 'topics', 's' => $s,], '', true));
break;
// Если значение параметра 'a' равно 'move', выполняется перенос темы.
case 'move':
// Импортирует параметр 'ns' (новая секция форума), который передается через POST и является строкой (ALP).
$ns = cot_import('ns','P','ALP');
// Импортирует параметр 'ghost', который передается через POST и является булевым значением (BOL).
$ghost = cot_import('ghost','P','BOL');
// Если новая секция не указана или не существует, завершаем выполнение с ошибкой 404.
if (empty($ns) || empty(Cot::$structure['forums'][$ns])) {
cot_die_message(404);
}
// Если текущая секция и новая секция одинаковы, генерируем ошибку и перенаправляем пользователя.
if ($s == $ns) {
cot_error(Cot::$L['forums_moveToSameSection'], 'ns');
cot_redirect(cot_url('forums', ['m' => 'posts', 'q' => $q,], '', true));
}
// Извлекаем данные о теме (заголовок, описание, режим, дата создания и информация о первом авторе)
// из базы данных для указанной темы и секции.
$topic = Cot::$db->query(
"SELECT ft_title, ft_desc, ft_mode, ft_creationdate, ft_firstposterid, ft_firstpostername" .
" FROM " . Cot::$db->forum_topics . " WHERE ft_id = :topicId AND ft_cat = :cat",
['cat' => $s, 'topicId' => $q]
)->fetch();
// Если тема не найдена, завершаем выполнение с ошибкой 404.
if (!$topic) {
cot_die_message(404);
}
// Получаем количество сообщений в теме.
$num = Cot::$db->query(
'SELECT COUNT(*) FROM ' . Cot::$db->forum_posts . ' WHERE fp_topicid = :topicId',
['topicId' => $q]
)->fetchColumn();
// Если сообщений в теме меньше одного или если структура новой секции не является корректной, завершаем выполнение с ошибкой 404.
if ($num < 1 || !strpos(Cot::$structure['forums'][$ns]['path'], '.')) {
cot_die_message(404);
}
// Удаляет все темы, которые были перемещены в указанную тему, чтобы избежать дублирования.
Cot::$db->delete(Cot::$db->forum_topics, 'ft_movedto = ?', $q);
// Если параметр 'ghost' равен true, то выполняется создание новой "призрачной" темы в старой секции форума.
if ($ghost) {
// Вставляем новую запись в таблицу тем форума (forum_topics).
// Создается новая тема с атрибутами из исходной темы, но с некоторыми изменениями:
Cot::$db->insert(
Cot::$db->forum_topics,
[
'ft_state' => 0, // Устанавливаем состояние темы как 0 (обычная тема, не закрыта).
'ft_mode' => (int) $topic['ft_mode'], // Используем режим исходной темы (например, открыта/закрыта).
'ft_sticky' => 0, // Тема не закреплена.
'ft_cat' => $s, // Устанавливаем секцию для новой темы как текущую секцию.
'ft_title' => $topic['ft_title'], // Заголовок темы остается таким же.
'ft_desc' => $topic['ft_desc'], // Описание темы сохраняется.
'ft_preview' => $topic['ft_preview'], // Превью темы сохраняется.
'ft_creationdate' => $topic['ft_creationdate'], // Дата создания темы сохраняется.
'ft_updated' => (int) Cot::$sys['now'], // Устанавливаем дату последнего обновления как текущее время.
'ft_postcount' => 0, // Количество сообщений в теме устанавливаем в 0 (так как это "призрачная" копия).
'ft_viewcount' => 0, // Количество просмотров также устанавливаем в 0.
'ft_firstposterid' => $topic['ft_firstposterid'], // ID первого автора сохраняется.
'ft_firstpostername' => $topic['ft_firstpostername'], // Имя первого автора сохраняется.
'ft_lastposterid' => 0, // ID последнего автора в новой теме равно 0.
'ft_lastpostername' => '-', // Имя последнего автора в новой теме равно '-'.
'ft_movedto' => $q, // Устанавливаем ID исходной темы, чтобы отслеживать, что это перемещенная тема.
]
);
}
// Обновляет запись о теме в таблице forum_topics, изменяя категорию (ft_cat) на новую секцию $ns.
Cot::$db->update(
Cot::$db->forum_topics,
['ft_cat' => $ns], // Обновляем поле ft_cat (категория) на новую секцию.
'ft_id = :topicId AND ft_cat = :cat', // Условие: выбираем тему по ID и исходной категории.
['topicId' => $q, 'cat' => $s] // Параметры: ID темы и исходная категория.
);
// Обновляет записи о сообщениях в таблице forum_posts, изменяя категорию (fp_cat) на новую секцию $ns для всех сообщений этой темы.
Cot::$db->update(
Cot::$db->forum_posts,
['fp_cat' => $ns], // Обновляем поле fp_cat (категория) на новую секцию.
'fp_topicid = :topicId', // Условие: выбираем все сообщения по ID темы.
['topicId' => $q] // Параметр: ID темы.
);
// Обновляет счетчики для старой секции форума.
cot_forums_updateStructureCounters($s);
// Обновляет счетчики для новой секции форума.
cot_forums_updateStructureCounters($ns);
// Логирует действие перемещения темы из одной секции в другую.
cot_log(
"Moved topic #$q from section #$s to section #" . $ns,
'forums', // Категория логирования.
'move topic', // Тип действия (перемещение темы).
'done' // Статус выполнения.
);
// Отображает сообщение о том, что тема была перемещена из текущей секции.
cot_message(Cot::$L['forums_movedoutofthissection']);
break;
// Если значение параметра 'a' равно 'lock', выполняется блокировка темы.
case 'lock':
// Обновляем запись в таблице forum_topics, устанавливая состояние темы как заблокированное (ft_state = 1),
// и убираем закрепление (ft_sticky = 0).
Cot::$db->update($db_forum_topics, array("ft_state" => 1, "ft_sticky"=> 0 ), "ft_id=$q");
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
// Логируем действие о блокировке темы.
cot_log("Locked topic #".$q, 'forums', 'lock topic', 'done');
break;
// Если значение параметра 'a' равно 'sticky', выполняется закрепление темы.
case 'sticky':
// Обновляем запись в таблице forum_topics, устанавливая состояние темы как обычное (ft_state = 0),
// и закрепляем тему (ft_sticky = 1).
Cot::$db->update($db_forum_topics, array("ft_state" => 0, "ft_sticky"=> 1 ), "ft_id=$q");
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
// Логируем действие о закреплении темы.
cot_log("Pinned topic #".$q, 'forums', 'pin topic', 'done');
break;
// Если значение параметра 'a' равно 'announcement', выполняется создание объявления из темы.
case 'announcement':
// Обновляем запись в таблице forum_topics, устанавливая состояние темы как заблокированное (ft_state = 1)
// и закрепляем тему (ft_sticky = 1).
Cot::$db->update($db_forum_topics, array("ft_state" => 1, "ft_sticky"=> 1 ), "ft_id=$q");
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
// Логируем действие о создании объявления.
cot_log("Announcement topic #".$q, 'forums', 'announce topic', 'done');
break;
// Если значение параметра 'a' равно 'bump', выполняется обновление темы, чтобы поднять ее в списке.
case 'bump':
// Обновляем поле 'ft_updated' для темы, устанавливая дату последнего обновления на текущее время.
Cot::$db->update(Cot::$db->forum_topics, ['ft_updated' => Cot::$sys['now'],], 'ft_id = ?', $q);
// Обновляем счетчики для секции форума.
cot_forums_updateStructureCounters($s);
// Логируем действие о поднятии темы.
cot_log("Bumped topic #" . $q, 'forums', 'bump topic', 'done');
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
break;
// Если значение параметра 'a' равно 'private', выполняется перевод темы в закрытый режим.
case 'private':
// Обновляем поле 'ft_mode' для темы, устанавливая его в 1 (закрытая тема).
Cot::$db->update(Cot::$db->forum_topics, ['ft_mode' => 1,], 'ft_id = ?', $q);
// Обновляем счетчики для секции форума.
cot_forums_updateStructureCounters($s);
// Логируем действие о закрытии темы.
cot_log("Made topic #" . $q . " private", 'forums', 'made topic', 'done');
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
break;
// Если значение параметра 'a' равно 'clear', выполняется сброс всех параметров темы.
case 'clear':
// Обновляем тему, сбрасывая все ее параметры:
// 'ft_state' = 0 (обычное состояние), 'ft_sticky' = 0 (не закреплена), 'ft_mode' = 0 (не закрыта).
Cot::$db->update(
Cot::$db->forum_topics,
['ft_state' => 0, 'ft_sticky' => 0, 'ft_mode' => 0,],
'ft_id = ?',
$q
);
// Обновляем счетчики для секции форума.
cot_forums_updateStructureCounters($s);
// Логируем действие о сбросе темы.
cot_log("Resetted topic #".$q, 'forums', 'reset topic', 'done');
// Отображаем сообщение о завершении действия.
cot_message(Cot::$L['Done']);
break;
}
// Перенаправляем пользователя обратно на страницу темы.
cot_redirect(cot_url('forums', ['m' => 'posts', 'q' => $q,], '', true));
/* === Hook === */
// Подключение плагинов, которые могут быть зарегистрированы для работы на этапе 'forums.topics.first'.
foreach (cot_getextplugins('forums.topics.first') as $pl) {
include $pl; // Подключаем каждый плагин.
}
/* ===== */
// Подключаем файл, который необходим для работы с формами.
require_once cot_incfile('forms');
// Парсим описание секции форума, автоматически заменяя URL-ссылки в тексте.
Cot::$structure['forums'][$s]['desc'] = cot_parse_autourls(Cot::$structure['forums'][$s]['desc']);
// Формируем параметры для заголовка страницы.
$title_params = array(
'FORUM' => Cot::$L['Forums'], // Заголовок форума.
'SECTION' => Cot::$structure['forums'][$s]['title'] // Заголовок текущей секции.
);
// Устанавливаем подзаголовок страницы, комбинируя стандартный заголовок форума с названием секции.
Cot::$out['subtitle'] = cot_title(Cot::$cfg['forums']['title_topics'], $title_params);
// Устанавливаем описание страницы, очищая описание секции форума от HTML-тегов и преобразуя их в безопасный формат.
Cot::$out['desc'] = htmlspecialchars(strip_tags(Cot::$structure['forums'][$s]['desc']));
// Устанавливаем подкатегорию для системного уровня подменю.
Cot::$sys['sublocation'] = Cot::$structure['forums'][$s]['title'];
// Если для текущей секции форума указаны ключевые слова, то добавляем их в мета-данные.
if (!empty(Cot::$cfg['forums']['cat_' . $s]['keywords'])) {
Cot::$out['keywords'] = Cot::$cfg['forums']['cat_' . $s]['keywords'];
}
// Если для текущей секции форума указано описание для мета-тегов, то добавляем его.
if (!empty(Cot::$cfg['forums']['cat_' . $s]['metadesc'])) {
Cot::$out['desc'] = Cot::$cfg['forums']['cat_' . $s]['metadesc'];
}
// Если описание для мета-тегов не задано, но имеется описание по умолчанию для секции, добавляем его.
if (empty(Cot::$out['desc']) && !empty(Cot::$cfg['forums']['cat___default']['metadesc'])) {
Cot::$out['desc'] = Cot::$cfg['forums']['cat___default']['metadesc'] . ' - '
. htmlspecialchars(strip_tags(Cot::$structure['forums'][$s]['title']));
}
// Если для текущей секции форума задано специальное название для мета-тегов, устанавливаем его как подзаголовок страницы.
if (!empty(Cot::$cfg['forums']['cat_' . $s]['metatitle'])) {
Cot::$out['subtitle'] = Cot::$cfg['forums']['cat_' . $s]['metatitle'];
}
/* === Hook === */
// Подключение плагинов, которые могут быть зарегистрированы для работы на этапе 'forums.topics.main'.
foreach (cot_getextplugins('forums.topics.main') as $pl)
{
include $pl; // Подключаем каждый плагин.
}
/* ===== */
// Подключаем файл header.php из системной директории, который обычно содержит заголовок страницы.
require_once Cot::$cfg['system_dir'] . '/header.php';
// Определяем путь к шаблону страницы форума, учитывая настройки для конкретной секции форума.
$mskin = cot_tplfile(array('forums' ,'topics', Cot::$structure['forums'][$s]['tpl']));
// Создаем новый объект XTemplate для работы с шаблонами, используя путь к шаблону.
$t = new XTemplate($mskin);
// Получаем дочерние категории форума для текущей секции.
$arraychilds = cot_structure_children('forums', $s, false, false);
// Если в секции есть дочерние категории, продолжаем выполнение.
if (count($arraychilds) > 0) {
/* === Hook - Part1 : Set === */
// Получаем список плагинов, которые могут быть зарегистрированы для работы в цикле секций форума.
$extp = cot_getextplugins('forums.topics.sections.loop');
/* ===== */
$jj = 0; // Инициализация счетчика для отслеживания номера секции.
// Проходим по всем дочерним категориям.
foreach($arraychilds as $cat) {
$jj++; // Увеличиваем счетчик для текущей секции.
// Получаем список всех дочерних категорий текущей категории.
$all = cot_structure_children('forums', $cat);
// Запрашиваем последнюю тему по времени из статистики форума для всех дочерних категорий.
$last = Cot::$db->query("SELECT fs_lt_id, fs_lt_title, fs_lt_date, fs_lt_posterid, fs_lt_postername FROM $db_forum_stats
WHERE fs_cat IN (\"".implode('", "', $all)."\") ORDER BY fs_lt_date DESC LIMIT 1")->fetch();
// Получаем статистику по всем дочерним категориям (количество тем, сообщений, просмотров).
$stat = Cot::$db->query("SELECT SUM(fs_topiccount) AS topiccount, SUM(fs_postcount) AS postcount, SUM(fs_viewcount) AS viewcount
FROM $db_forum_stats
WHERE fs_cat IN (\"".implode('", "', $all)."\") ORDER BY fs_lt_date DESC LIMIT 1")->fetch();
// Если найдены данные для последней темы и статистики, объединяем их в один массив.
$last = (is_array($last) && is_array($stat)) ? $stat + $last : '';
// Присваиваем данные для текущей секции и генерируем теги для шаблона.
$t->assign(cot_generate_sectiontags($cat, 'FORUMS_SECTIONS_ROW_', $last));
// Присваиваем дополнительные данные для четности/нечетности строки и номера секции.
$t->assign(array(
'FORUMS_SECTIONS_ROW_ODDEVEN' => cot_build_oddeven($jj),
'FORUMS_SECTIONS_ROW_NUM' => $jj
));
/* === Hook - Part2 : Include === */
// Подключаем плагины, если они зарегистрированы для данного этапа.
foreach ($extp as $pl)
{
include $pl; // Подключаем каждый плагин.
}
/* ===== */
// Добавляем текущую строку секции в основной шаблон.
$t->parse('MAIN.FORUMS_SECTIONS.FORUMS_SECTIONS_ROW_SECTION');
}
// Добавляем все секции в основной шаблон.
$t->parse('MAIN.FORUMS_SECTIONS');
}
// Проверяем, существует ли переменная $where и является ли она массивом. Если нет, создаем пустой массив.
$where = (isset($where) && is_array($where)) ? $where : array();
// Добавляем условие для выбора по категории (ft_cat) форума.
$where['cat'] = 'ft_cat='.Cot::$db->quote($s);
// Условие для проверки прав пользователя: если он администратор, то условие пустое, иначе проверка на доступность тем.
$where['admin'] = (Cot::$usr['isadmin']) ? '' : "(ft_mode=0 OR (ft_mode=1 AND ft_firstposterid=".(int)Cot::$usr['id']."))";
// Формируем строку сортировки: сначала закрепленные темы (ft_sticky DESC), потом сортировка по выбранному полю и направлению.
$order = "ft_sticky DESC, ft_$o $w";
// Инициализация переменных для присоединений таблиц (если такие будут).
$join_columns = '';
$join_condition = '';
// === Hook ===
// Подключаем плагины, которые могут быть зарегистрированы для работы с запросом тем форума.
foreach (cot_getextplugins('forums.topics.query') as $pl)
{
include $pl; // Подключаем каждый плагин.
}
/* ===== */
// Убираем пустые элементы из массива $where.
$where = array_diff($where, array(''));
// Создаем копию массива $where для проверки только приватных тем (ft_mode = 1).
$where_prv = $where;
$where_prv['ft_mode'] = '1';
// Запрашиваем количество приватных тем для данного форума с учетом условий.
$prvtopics = Cot::$db->query("SELECT COUNT(*) FROM $db_forum_topics AS t $join_condition WHERE ".implode(' AND ', $where_prv))->fetchColumn();
// Запрашиваем общее количество тем для данного форума с учетом условий.
$totaltopics = Cot::$db->query("SELECT COUNT(*) FROM $db_forum_topics AS t $join_condition WHERE ".implode(' AND ', $where))->fetchColumn();
// Запрещаем доступ к несуществующим страницам (если номер страницы больше общего количества тем).
if ($totaltopics > 0 && $d > $totaltopics) {
cot_die_message(404); // Если страница не существует, выводим ошибку 404.
}
// Проверяем, авторизован ли пользователь.
if (Cot::$usr['id'] > 0) {
// Проверяем, опубликовал ли пользователь сообщение в теме.
$join_columns .= ", (SELECT COUNT(*) FROM $db_forum_posts WHERE fp_topicid = t.ft_id AND fp_posterid = ".Cot::$usr['id'].") AS ft_user_posted";
}
// Формируем SQL-запрос для получения списка тем форума с учетом условий и сортировки.
$sql_forums = Cot::$db->query("SELECT t.* $join_columns
FROM $db_forum_topics AS t $join_condition
WHERE ".implode(' AND ', $where)." ORDER BY $order LIMIT $d, ".Cot::$cfg['forums']['maxtopicsperpage']);
/* === Hook - Part1 : Set === */
// Получаем список плагинов, которые могут быть подключены для обработки темы форума.
$extp = cot_getextplugins('forums.topics.loop');
/* ===== */
// Инициализация переменной для подсчета количества тем.
$ft_num = 0;
// Получаем все строки из результата SQL-запроса.
$sql_forums_rowset = $sql_forums->fetchAll();
// Проходим по всем полученным строкам (темам форума).
foreach ($sql_forums_rowset as $row) {
// Инициализация значений для иконки темы и флага, указывающего, является ли пост новым.
$row['ft_icon'] = 'posts'; // Иконка по умолчанию для темы
$row['ft_postisnew'] = FALSE; // Флаг, что пост не новый
$row['ft_pages'] = ''; // Страницы не заданы
$row['ft_maxpages'] = ''; // Максимальное количество страниц (TODO: понять, что это за значение)
$ft_num++; // Увеличиваем счетчик тем.
// Если тема приватная (ft_mode == 1), добавляем символ "# " перед названием.
$row['ft_title'] = ($row['ft_mode'] == 1) ? "# ". $row['ft_title'] : $row['ft_title'];
// Проверяем, была ли тема перемещена (ft_movedto > 0).
if ($row['ft_movedto'] > 0) {
// Если тема перемещена, обновляем URL, иконку и заголовок.
$row['ft_url'] = cot_url('forums', "m=posts&q=".$row['ft_movedto']); // URL перемещенной темы
$row['ft_icon_type'] = 'posts_moved'; // Тип иконки для перемещенной темы
$row['ft_icon'] = Cot::$R['forums_icon_posts_moved']; // Иконка перемещенной темы
$row['ft_title'] = Cot::$L['Moved'] . ": " . $row['ft_title']; // Заголовок с пометкой "Moved"
// Обнуляем статистику темы (количество постов, просмотров и т. д.), так как это перемещенная тема.
$row['ft_postcount'] = Cot::$R['forums_code_post_empty'];
$row['ft_replycount'] = Cot::$R['forums_code_post_empty'];
$row['ft_viewcount'] = Cot::$R['forums_code_post_empty'];
$row['ft_lastpostername'] = Cot::$R['forums_code_post_empty']; // Нет последнего автора
$row['ft_lastposturl'] = cot_url('forums', "m=posts&q=".$row['ft_movedto']."&n=last", "#bottom"); // Ссылка на последний пост перемещенной темы
$row['ft_lastpostlink'] = cot_rc_link($row['ft_lastposturl'], Cot::$R['icon_follow'], 'rel="nofollow"') .Cot::$L['Moved']; // Ссылка на последний пост с пометкой "Moved"
} else {
// Если тема не была перемещена, устанавливаем URL для текущей темы.
$row['ft_url'] = cot_url('forums', "m=posts&q=".$row['ft_id']); // URL для текущей темы
// Определяем URL последнего поста в теме. Если пользователь авторизован и тема была обновлена после его последнего визита, показываем ссылку на непрочитанное сообщение.
$row['ft_lastposturl'] = (Cot::$usr['id'] > 0 && $row['ft_updated'] > Cot::$usr['lastvisit'])
? cot_url('forums', "m=posts&q=".$row['ft_id']."&n=unread", "#unread") // Непрочитанное сообщение
: cot_url('forums', "m=posts&q=".$row['ft_id']."&n=last", "#bottom"); // Последний пост в теме
// Создаем ссылку на последний пост с иконкой, если пост новый, то добавляем иконку для непрочитанного.
$row['ft_lastpostlink'] = cot_rc_link($row['ft_lastposturl'], Cot::$R['icon_unread'], 'rel="nofollow"').cot_date('datetime_short', $row['ft_updated']);
// Вычисляем количество ответов в теме (общее количество постов минус один, так как сам пост темы не считается).
$row['ft_replycount'] = $row['ft_postcount'] - 1;
// Если тема обновлена после последнего визита пользователя, помечаем её как новую.
if ($row['ft_updated'] > Cot::$usr['lastvisit'] && Cot::$usr['id'] > 0) {
$row['ft_icon'] .= '_new'; // Добавляем суффикс для новой темы
$row['ft_postisnew'] = TRUE; // Устанавливаем флаг, что пост новый
}
// Если количество ответов в теме превышает порог "горячей темы", устанавливаем иконку для горячей темы.
if ($row['ft_postcount'] >= Cot::$cfg['forums']['hottopictrigger'] && !$row['ft_state'] && !$row['ft_sticky']) {
$row['ft_icon'] = ($row['ft_postisnew']) ? 'posts_new_hot' : 'posts_hot'; // Иконка для горячей темы
} else {
// Если тема закреплена или заблокирована, добавляем соответствующие суффиксы к иконке.
$row['ft_icon'] .= ($row['ft_sticky']) ? '_sticky' : ''; // Иконка для закрепленной темы
$row['ft_icon'] .= ($row['ft_state']) ? '_locked' : ''; // Иконка для заблокированной темы
}
// Устанавливаем тип иконки, используемый для отображения темы.
$row['ft_icon_type'] = $row['ft_icon'];
// Преобразуем иконку темы в HTML-строку с использованием шаблона иконки.
$row['ft_icon'] = cot_rc('forums_icon_topic', array('icon' => $row['ft_icon']));
// Строим имя последнего автора и его ссылку на профиль.
$row['ft_lastpostername'] = cot_build_user($row['ft_lastposterid'], $row['ft_lastpostername']);
}
// Если количество постов в теме больше, чем максимально допустимое количество на странице и тема не перемещена,
// создаем пагинацию для темы.
if ($row['ft_postcount'] > Cot::$cfg['forums']['maxpostsperpage'] && !$row['ft_movedto']) {
$pn_q = $row['ft_movedto'] > 0 ? $row['ft_movedto'] : $row['ft_id']; // Если тема перемещена, берем ID перемещенной темы
$pn = cot_pagenav('forums', 'm=posts&q='.$pn_q, 0, $row['ft_postcount'], Cot::$cfg['forums']['maxpostsperpage'], 'd'); // Получаем пагинацию
if (!isset($pn['first'])) $pn['first'] = ''; // Если страница первая, устанавливаем пустое значение
// Формируем HTML код пагинации.
$row['ft_pages'] = cot_rc('forums_code_topic_pages', array('main' => $pn['main'], 'first' => $pn['first'], 'last' => $pn['last']));
}
// Тип иконки, дополнительно добавляем '_posted', если пользователь оставил пост в этой теме.
$row['ft_icon_type_ex'] = $row['ft_icon_type'];
if (!empty($row['ft_user_posted'])) {
$row['ft_icon_type_ex'] .= '_posted'; // Устанавливаем суффикс, если пользователь опубликовал пост
}
// Превью темы (если оно задано).
$topicPreview = '';
if (!empty($row['ft_preview'])) {
// Проверяем, разрешены ли BB-коды в категории форума.
$allowBBCodes = isset(Cot::$cfg['forums']['cat_' . $s])
? Cot::$cfg['forums']['cat_' . $s]['allowbbcodes']
: Cot::$cfg['forums']['cat___default']['allowbbcodes'];
// Применяем парсинг для превью темы с учетом разрешенных BB-кодов.
$topicPreview = trim(cot_parse($row['ft_preview'], $allowBBCodes));
if (!empty($topicPreview)) {
$topicPreview .= '...'; // Добавляем многоточие, если превью не пустое
}
}
// Присваивание значений переменным в шаблон с помощью метода assign объекта $t
$t->assign([
// Присваиваем значение ID темы
'FORUMS_TOPICS_ROW_ID' => $row['ft_id'],
// Присваиваем состояние темы (например, открыта или закрыта)
'FORUMS_TOPICS_ROW_STATE' => $row['ft_state'],
// Присваиваем иконку для темы
'FORUMS_TOPICS_ROW_ICON' => $row['ft_icon'],
// Присваиваем тип иконки для темы
'FORUMS_TOPICS_ROW_ICON_TYPE' => $row['ft_icon_type'],
// Присваиваем расширенный тип иконки
'FORUMS_TOPICS_ROW_ICON_TYPE_EX' => $row['ft_icon_type_ex'],
// Присваиваем название темы, предварительно экранируем HTML-символы для безопасности
'FORUMS_TOPICS_ROW_TITLE' => htmlspecialchars($row['ft_title']),
// Присваиваем описание темы, также экранируем HTML-символы
'FORUMS_TOPICS_ROW_DESC' => htmlspecialchars($row['ft_desc']),
// Присваиваем дату создания темы, форматируем её в короткий формат
'FORUMS_TOPICS_ROW_CREATIONDATE' => cot_date('datetime_short', $row['ft_creationdate']),
// Присваиваем временную метку даты создания
'FORUMS_TOPICS_ROW_CREATIONDATE_STAMP' => $row['ft_creationdate'],
// Присваиваем URL для последнего сообщения в теме
'FORUMS_TOPICS_ROW_UPDATEDURL' => $row['ft_lastposturl'],
// Присваиваем ссылку на последнее сообщение в теме
'FORUMS_TOPICS_ROW_UPDATED' => $row['ft_lastpostlink'],
// Присваиваем временную метку обновления темы
'FORUMS_TOPICS_ROW_UPDATED_STAMP' => $row['ft_updated'],
// Проверяем, была ли тема перемещена, если да, присваиваем 1, если нет — 0
'FORUMS_TOPICS_ROW_MOVED' => ($row['ft_movedto'] > 0) ? 1 : 0,
// Присваиваем строку с временным промежутком с момента последнего обновления
'FORUMS_TOPICS_ROW_TIMEAGO' => cot_build_timegap($row['ft_updated']),
// Присваиваем количество сообщений в теме
'FORUMS_TOPICS_ROW_POSTCOUNT' => $row['ft_postcount'],
// Присваиваем количество ответов в теме
'FORUMS_TOPICS_ROW_REPLYCOUNT' => $row['ft_replycount'],
// Присваиваем количество просмотров темы
'FORUMS_TOPICS_ROW_VIEWCOUNT' => $row['ft_viewcount'],
// Присваиваем данные первого автора темы
'FORUMS_TOPICS_ROW_FIRSTPOSTER' => cot_build_user($row['ft_firstposterid'], $row['ft_firstpostername']),
// Присваиваем имя последнего автора темы
'FORUMS_TOPICS_ROW_LASTPOSTER' => $row['ft_lastpostername'],
// Если пользователь оставлял сообщения в теме, присваиваем это значение
'FORUMS_TOPICS_ROW_USER_POSTED' => isset($row['ft_user_posted']) ? (int) $row['ft_user_posted'] : '',
// Присваиваем URL самой темы
'FORUMS_TOPICS_ROW_URL' => $row['ft_url'],
// Присваиваем превью для темы, предварительно очищаем от HTML-тегов и экранируем
'FORUMS_TOPICS_ROW_PREVIEW' => htmlspecialchars(strip_tags($topicPreview)),
// Присваиваем навигацию по страницам (если она есть) для этой темы
'FORUMS_TOPICS_ROW_PAGES' => $row['ft_pages'],
// Присваиваем количество страниц в теме
'FORUMS_TOPICS_ROW_MAXPAGES' => $row['ft_maxpages'],
// Присваиваем четность/нечетность строки для чередования стилей
'FORUMS_TOPICS_ROW_ODDEVEN' => cot_build_oddeven($ft_num),
// Присваиваем номер текущей строки (для отображения порядка)
'FORUMS_TOPICS_ROW_NUM' => $ft_num,
// Присваиваем саму строку данных темы
'FORUMS_TOPICS_ROW' => $row,
]);
// Проверка, есть ли дополнительные поля в таблице тем форума
if (!empty(Cot::$extrafields[Cot::$db->forum_topics])) {
// Если есть, перебираем все дополнительные поля
foreach (Cot::$extrafields[Cot::$db->forum_topics] as $exfld) {
// Преобразуем имя поля в верхний регистр для использования в тегах шаблона
$tag = mb_strtoupper($exfld['field_name']);
// Получаем заголовок для дополнительного поля, используя функцию cot_extrafield_title
$exfld_title = cot_extrafield_title($exfld, 'forums_topic_');
// Присваиваем значения в шаблон для каждого дополнительного поля
$t->assign(array(
// Присваиваем заголовок для дополнительного поля
'FORUMS_TOPICS_ROW_' . $tag . '_TITLE' => $exfld_title,
// Присваиваем данные дополнительного поля, используя функцию cot_build_extrafields_data
'FORUMS_TOPICS_ROW_' . $tag => cot_build_extrafields_data('forums', $exfld, $row['ft_' . $exfld['field_name']],
(Cot::$cfg['forums']['markup'] && Cot::$cfg['forums']['cat_' . $s]['allowbbcodes'])),
// Присваиваем значение дополнительного поля
'FORUMS_TOPICS_ROW_' . $tag . '_VALUE' => $row['ft_' . $exfld['field_name']]
));
}
}
/* === Хук - Часть 2 : Включение === */
// Перебираем плагины, подключенные в секции 'forums.topics.loop'
foreach ($extp as $pl) {
// Подключаем каждый плагин
include $pl;
}
/* ===== */
// Разбираем строку шаблона для вывода информации о теме
$t->parse('MAIN.FORUMS_TOPICS_ROW');
// Создаем постраничную навигацию для форума
$pagenav = cot_pagenav('forums', "m=topics&s=$s&ord=$o&w=$w", $d, $totaltopics, Cot::$cfg['forums']['maxtopicsperpage']);
// Формируем хлебные крошки для текущего форума
$toptitle = cot_breadcrumbs(cot_forums_buildpath($s), Cot::$cfg['homebreadcrumb']);
// Если пользователь является администратором, добавляем метку администратора
$toptitle .= (Cot::$usr['isadmin']) ? Cot::$R['forums_code_admin_mark'] : '';
// Формируем список форумов для отображения в выпадающем списке (jumpbox)
$jumpbox[cot_url('forums')] = Cot::$L['Forums']; // Добавляем ссылку на главную страницу форума
// Перебираем все форумы в структуре форума
foreach(Cot::$structure['forums'] as $key => $val) {
// Если у пользователя есть права на чтение форума, добавляем его в список jumpbox
if (cot_auth('forums', $key, 'R')) {
$jumpbox[cot_url('forums', "m=topics&s=".$key, '', true)] = $val['tpath'];
}
}
// Функция для смены направления сортировки (по возрастанию/по убыванию)
function rev($sway)
{
return ($sway == 'desc') ? 'asc' : 'desc'; // Меняем направление сортировки
}
// Функция для отображения иконки сортировки в зависимости от направления
function cursort($trigger, $way)
{
global $R;
// Если сортировка активна, возвращаем иконку в зависимости от направления
if ($trigger) {
return (($way == 'asc') ? Cot::$R['icon_down'] : Cot::$R['icon_up']);
}
return ''; // Если сортировка не активна, не выводим иконку
}
// Формируем URL для сортировки по различным полям
foreach (array('title', 'viewcount', 'postcount', 'creationdate', 'updated') as $ord) {
// Сохраняем URL для сортировки по каждому полю
$title_urls[$ord] = cot_url('forums', "m=topics&s=$s&ord=$ord&w=".rev($w));
}
// Присваиваем значения переменным для отображения в шаблоне
$t->assign([
// Идентификатор текущего раздела форума
'FORUMS_TOPICS_PARENT_SECTION_ID' => $s,
// URL для RSS ленты текущего раздела форума
'FORUMS_TOPICS_SECTION_RSS' => cot_url('rss', "m=section&c=$s"),
// Заголовок страницы форума
'FORUMS_TOPICS_PAGETITLE' => $toptitle,
// Краткое название раздела форума
'FORUMS_TOPICS_SHORTTITLE' => htmlspecialchars(Cot::$structure['forums'][$s]['title']),
// Описание раздела форума
'FORUMS_TOPICS_SUBTITLE' => Cot::$structure['forums'][$s]['desc'],
// URL для создания новой темы
'FORUMS_TOPICS_NEWTOPICURL' => cot_url('forums', "m=newtopic&s=".$s),
// Основная ссылка для навигации по страницам
'FORUMS_TOPICS_PAGES' => $pagenav['main'],
// Ссылка на предыдущую страницу
'FORUMS_TOPICS_PAGEPREV' => $pagenav['prev'],
// Ссылка на следующую страницу
'FORUMS_TOPICS_PAGENEXT' => $pagenav['next'],
// Ссылка на последнюю страницу
'FORUMS_TOPICS_PAGELAST' => $pagenav['last'],
// Текущая страница
'FORUMS_TOPICS_PAGECURRENT' => $pagenav['current'],
// Общее количество страниц
'FORUMS_TOPICS_PAGETOTAL' => $pagenav['total'],
// Количество тем на одной странице
'FORUMS_TOPICS_PAGEONPAGE' => $pagenav['onpage'],
// Общее количество записей на странице
'FORUMS_TOPICS_PAGEENTRIES' => $pagenav['entries'],
// Количество тем на форуме
'FORUMS_TOPICS_PRVTOPICS' => $prvtopics,
// Выпадающий список для выбора раздела форума
'FORUMS_TOPICS_JUMPBOX' => cot_selectbox($s, 'jumpbox', array_keys($jumpbox), array_values($jumpbox), false, 'onchange="redirect(this)"'),
// Ссылка для сортировки по названию темы
'FORUMS_TOPICS_TITLE_TOPICS' => cot_rc_link($title_urls['title'], Cot::$L['forums_topics'].' '.cursort($o == 'title', $w), 'rel="nofollow"'),
// URL для сортировки по названию темы
'FORUMS_TOPICS_TITLE_TOPICS_URL' => $title_urls['title'],
// Ссылка для сортировки по количеству просмотров
'FORUMS_TOPICS_TITLE_VIEWS' => cot_rc_link($title_urls['viewcount'], Cot::$L['Views']." ".cursort($o == 'viewcount', $w), 'rel="nofollow"'),
// URL для сортировки по количеству просмотров
'FORUMS_TOPICS_TITLE_VIEWS_URL' => $title_urls['viewcount'],
// Ссылка для сортировки по количеству постов
'FORUMS_TOPICS_TITLE_POSTS' => cot_rc_link($title_urls['postcount'], Cot::$L['forums_posts']." ".cursort($o == 'postcount', $w), 'rel="nofollow"'),
// URL для сортировки по количеству постов
'FORUMS_TOPICS_TITLE_POSTS_URL' => $title_urls['postcount'],
// Ссылка для сортировки по количеству ответов
'FORUMS_TOPICS_TITLE_REPLIES' => cot_rc_link($title_urls['postcount'], Cot::$L['Replies']." ".cursort($o == 'postcount', $w), 'rel="nofollow"'),
// URL для сортировки по количеству ответов
'FORUMS_TOPICS_TITLE_REPLIES_URL' => $title_urls['postcount'],
// Ссылка для сортировки по дате начала темы
'FORUMS_TOPICS_TITLE_STARTED' => cot_rc_link($title_urls['creationdate'], Cot::$L['Started']." ".cursort($o == 'creationdate', $w), 'rel="nofollow"'),
// URL для сортировки по дате начала темы
'FORUMS_TOPICS_TITLE_STARTED_URL' => $title_urls['creationdate'],
// Ссылка для сортировки по дате последнего поста
'FORUMS_TOPICS_TITLE_LASTPOST' => cot_rc_link($title_urls['updated'], Cot::$L['Lastpost']." ".cursort($o == 'updated', $w), 'rel="nofollow"'),
// URL для сортировки по дате последнего поста
'FORUMS_TOPICS_TITLE_LASTPOST_URL' => $title_urls['updated'],
]);
/* === Hook === */
// Запуск плагинов, подключённых к хуку 'forums.topics.tags'
foreach (cot_getextplugins('forums.topics.tags') as $pl)
{
// Включение плагина
include $pl;
}
/* ===== */
// Разбор и вывод шаблона MAIN
$t->parse('MAIN');
$t->out('MAIN');
// Подключение файла footer.php (подвал страницы)
require_once Cot::$cfg['system_dir'] . '/footer.php';
// Если включено кэширование, пользователь не авторизован и разрешено кэширование форумов
if (Cot::$cache && Cot::$usr['id'] === 0 && Cot::$cfg['cache_forums']) {
// Запись кэшированного содержимого для форума
Cot::$cache->static->write();
}
Комментарии (0)
Автор контента
Оффлайн
Sodium Carbonate
Последняя авторизация: 19.07.2026 01:13
- Страница размещена: 10.02.2025 19:07
- Последнее обновление: 11.02.2025 19:52