Файл forums.sections.php в Cotonti

Файл "forums.sections.php" является частью модуля форума в системе Cotonti CMF. Он хранится в директории /modules/forums/inc/ и играет ключевую роль в обработке и отображении структуры форума на сайте. Рассмотрим его назначение и взаимодействие с системой, а также подробное описание всех ключевых переменных, хуков, методов и других компонентов, используемых в коде.

1. Основное назначение файла

Этот файл отвечает за вывод и обработку структуры форума, которая включает в себя разделы, категории и их дочерние категории (если они существуют). Он взаимодействует с базой данных для получения информации о разделах форума, вычисляет статистику активности (например, количество постов, просмотров и тем), а затем отображает эту информацию на страницах форума.

Он обеспечивает динамическое построение структуры форума, включая отображение активных разделов и категорий, а также поддерживает функционал, такой как обновление информации о прочитанных темах (метка "Прочитано"), кеширование, обработку мета-данных и интеграцию с плагинами.

2. Место файла в системе Cotonti

Файл расположен в директории /modules/forums/inc/ в структуре модуля форума.

Файл обрабатывает логику представления разделов форума, в том числе создание и отображение различных уровней вложенности категорий и разделов форума.

3. Взаимодействие файла с другими частями сайта

Этот файл активно взаимодействует с базой данных, получая информацию о структуре форума (категории, разделы, темы и посты). Он также взаимодействует с кэшированием, мета-данными (для оптимизации SEO) и с плагинами для расширенной настройки и взаимодействия с форумом.

Основные шаги взаимодействия файла:

  • Получение и обработка данных из базы данных (через запросы SQL).
  • Генерация шаблонных тегов для вывода информации на страницу.
  • Кеширование для повышения производительности.
  • Интеграция с плагинами для расширения функционала форума.
  • Обновление состояния разделов и категорий форума, например, подсчет количества постов или обновление информации о прочитанных темах.

4. Переменные, хуки, методы и функции, используемые в файле

Переменные:

  • $cot_sections_act: Массив, хранящий активность разделов форума. Он используется для отображения уровня активности каждого раздела.
  • $cat_top: Массив, содержащий информацию о каждой категории форума, такую как количество тем, постов и просмотров.
  • $fstlvl, $nxtlvl: Массивы, которые разделяют разделы форума на различные уровни вложенности (например, первичные разделы, подкатегории и их дочерние категории).
  • $secact_max: Максимальный уровень активности разделов, используется для вычисления процентной активности каждого раздела.
  • $t: Объект шаблона XTemplate, который используется для генерации HTML-кода страницы.

Хуки:

  • forums.sections.rights: Хук, используемый для обработки прав доступа к разделам форума.
  • forums.sections.first: Хук, который срабатывает на первой стадии загрузки страницы разделов форума.
  • forums.sections.loop: Хук для обработки циклов вывода разделов форума.
  • forums.sections.loop.sections: Хук для обработки секций форума (категорий).
  • forums.sections.loop.subsections: Хук для обработки подкатегорий.
  • forums.sections.tags: Хук для обработки тегов, связанных с разделами форума.
  • forums.sections.main: Основной хук для вывода информации о разделе форума.

Методы и функции:

  • cot_auth(): Функция для проверки прав доступа пользователя к форуму, разделу или категории.
  • cot_import(): Функция для получения параметров из запроса (например, s и c для выбора раздела и категории).
  • cot_getextplugins(): Функция для получения списка плагинов, подключенных к хукам.
  • cot_generate_sectiontags(): Функция для генерации шаблонных тегов для отображения информации о разделе.
  • cot_breadcrumbs(): Функция для формирования хлебных крошек (breadcrumbs) для навигации по разделам форума.
  • cot_rc(): Функция для генерации ссылок с параметрами, например, для пометки всех сообщений как прочитанных.
  • cot_build_oddeven(): Функция для определения четности/нечетности строки, используемая для чередования классов в шаблоне.
  • cot_die_message(): Функция для вывода страницы ошибки 404, если раздел или категория не найдены.
  • cot_forums_updateStructureCounters(): Функция для обновления счетчиков категорий форума (тем, постов и просмотров).
  • cot_url(): Функция для генерации URL с параметрами.

Классы:

  • XTemplate: Класс для работы с шаблонами в Cotonti, используется для генерации HTML-кода.
  • Cot::$db: Класс для работы с базой данных.
  • Cot::$usr: Класс для работы с данными пользователя (например, его правами доступа).
  • Cot::$cfg: Класс для работы с конфигурацией сайта.

5. Суть содержания кода

Файл выполняет несколько ключевых задач:

  1. Обработка прав доступа:

    • В начале кода проверяются права пользователя на чтение и запись на форуме с помощью функции cot_auth(). Если права недостаточны, доступ к разделам ограничивается.
  2. Обработка структуры форума:

    • Далее файл обрабатывает структуру форума, разделяя его на уровни (основные разделы, подкатегории). Для каждого раздела вычисляются статистики активности, такие как количество тем, постов и просмотров. Эти данные выводятся на странице форума.
  3. Генерация HTML-кода:

    • С использованием класса XTemplate и функций шаблонов, таких как cot_generate_sectiontags(), генерируются HTML-данные, которые включают информацию о разделах, подкатегориях и статистике активности.
  4. Работа с кешированием:

    • Кеширование используется для повышения производительности, особенно для неавторизованных пользователей. Данные кешируются, и при необходимости они обновляются.
  5. Интеграция с плагинами:

    • Файл активно использует хуки для интеграции с плагинами. Это позволяет расширять функциональность форума, добавлять дополнительные действия и изменять поведение форума без изменения основного кода.
  6. Обработка мета-данных:

    • Файл управляет мета-данными страницы (например, мета-заголовки, описания и ключевые слова) для улучшения SEO. Это особенно важно для оптимизации форума в поисковых системах.
  7. Обновление информации о прочитанных темах:

    • В конце кода есть логика для обновления меток о прочитанных темах, что позволяет пользователю видеть новые сообщения и темы.

Таким образом, этот файл обеспечивает динамическую работу разделов форума, управление правами доступа, обновление информации о состоянии форума и отображение актуальной информации на страницах форума, а также взаимодействует с плагинами для расширения функционала.

 

<?php

// Определяет метаинформацию о файле, в том числе имя пакета и лицензию.
// Это стандартный блок, предоставляющий информацию о пакете и лицензии.
// Данный блок обычно используется для документации, чтобы указать автора и условия лицензирования.
 /**
 * @package Forums
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL'); 
// Проверка на то, что файл подключен через правильный механизм.
// Если 'COT_CODE' не определен (это указывает на отсутствие правильного контекста), выполнение скрипта будет остановлено с сообщением 'Wrong URL'.

// Определение переменных для прав доступа пользователя в форуме.
// cot_auth используется для получения прав доступа пользователя для модуля 'forums' на любом уровне.
// Функция возвращает массив прав доступа для чтения, записи и флага администратора.
list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('forums', 'any');

// Получаем параметры запроса 's' и 'c' из глобального массива $_GET.
// Значения этих параметров могут быть использованы для фильтрации или идентификации данных на форуме.
$s = cot_import('s', 'G', 'TXT'); 
$c = cot_import('c', 'G', 'TXT');

// Устанавливаем подзаголовок для текущей страницы форума.
// В данном случае, подзаголовок задается как 'Home' из массива переводов Cot::$L.
Cot::$sys['sublocation'] = Cot::$L['Home'];

 

// Проверяем, не пуста ли переменная $c, которая содержит параметр из глобального массива $_GET.
// Если переменная $c пуста, то это условие не выполняется.
if (!empty($c)) {
    
    // Если структура форума не содержит ключа с значением $c, то выполняется ошибка 404 (страница не найдена).
    // Проверяется наличие форума в структуре Cot::$structure['forums'].
    // Если нужной секции нет, вызывается ошибка.
    if (!isset(Cot::$structure['forums'][$c])) {
        cot_die_message(404, TRUE);
    }

    // Получаем права доступа для текущей секции форума с ключом $c.
    // Функция cot_auth получает права на чтение, запись и проверку администраторских прав.
    list($canRead, $canWrite, $isAdmin) = cot_auth('forums', $c);

    // Обновляем права пользователя.
    // Права чтения, записи и админские права пользователя проверяются и изменяются в зависимости от прав для конкретной секции форума.
    Cot::$usr['auth_read'] = Cot::$usr['auth_read'] && $canRead;
    Cot::$usr['auth_write'] = Cot::$usr['auth_write'] && $canWrite;
    Cot::$usr['isadmin'] = Cot::$usr['isadmin'] && $isAdmin;

    // Устанавливаем подзаголовок страницы как название текущей секции форума.
    Cot::$sys['sublocation'] = Cot::$structure['forums'][$c]['title'];
}

/* === Hook === */
// Здесь вызываются плагины, если они зарегистрированы для этого действия.
// Для хуков 'forums.sections.rights' выполняются подключаемые плагины.
foreach (cot_getextplugins('forums.sections.rights') as $pl) {
    include $pl;
}
/* ===== */

// Функция cot_block проверяет, есть ли у пользователя права на чтение.
// Если у пользователя нет прав на чтение, он не сможет продолжить работу с разделом форума, и будет выведено сообщение об ошибке.
cot_block(Cot::$usr['auth_read']);

 

 

/* === Hook === */
// Выполняются плагины, если они зарегистрированы для действия 'forums.sections.first'.
// Хуки подключаются, если они настроены для выполнения на этой стадии, позволяя расширять функционал форума.
foreach (cot_getextplugins('forums.sections.first') as $pl) {
    include $pl;
}
/* ===== */

// Проверяем, если переменная $n равна 'markall' и у пользователя есть ID (он авторизован).
// Если условие выполняется, обновляется время последнего визита пользователя в базе данных.
if ($n == 'markall' && Cot::$usr['id'] > 0) {
    Cot::$db->update($db_users, array('user_lastvisit' => Cot::$sys['now']), "user_id=".Cot::$usr['id']);
    Cot::$usr['lastvisit'] = Cot::$sys['now'];  // Обновляем переменную lastvisit в объекте пользователя.
}

// Если переменная $cot_sections_act пуста, инициализируем её как пустой массив.
if (empty($cot_sections_act)) {
    $cot_sections_act = [];
    
    // Вычисляем время, которое прошло за последние 7 дней.
    $timeback = Cot::$sys['now'] - 604800; // 604800 секунд = 7 дней.
    
    // Выполняем SQL-запрос, чтобы получить количество сообщений для каждой категории форума, созданных за последние 7 дней.
    $sqltmp = Cot::$db->query(
        'SELECT fp_cat, COUNT(*) FROM ' . Cot::$db->forum_posts . " WHERE fp_creation > $timeback GROUP BY fp_cat"
    );
    
    // Проходим по результатам запроса и сохраняем количество сообщений для каждой категории в массив $cot_sections_act.
    while ($tmprow = $sqltmp->fetch()) {
        $cot_sections_act[$tmprow['fp_cat']] = $tmprow['COUNT(*)'];
    }
    
    // Закрываем курсор запроса, чтобы освободить ресурсы.
    $sqltmp->closeCursor();
    
    // Если кэширование включено, сохраняем данные о количестве активных сообщений для каждой категории в кэш на 2 часа.
    if (!empty(Cot::$cache)) {
        Cot::$cache->db->store('cot_sections_act', $cot_sections_act, 'system', 7200); // Кэшируем на 2 часа.
    }
}

 

// Инициализируем пустой массив $cat_top, в котором будем хранить информацию о категориях форума.
$cat_top = [];

// Выполняем SQL-запрос для получения всех данных из таблицы форума "forum_stats", отсортированных по убыванию значения fs_cat.
$sqlForums = Cot::$db->query('SELECT * FROM ' . Cot::$db->forum_stats . ' ORDER by fs_cat DESC');

// Проходим по каждому результату запроса (по каждой строке из таблицы forum_stats).
while ($row = $sqlForums->fetch()) {
    
    // Проверяем несколько условий:
    // 1. Категория форума (fs_cat) не пуста.
    // 2. Не существует связанного объекта (fs_lt_id пуст).
    // 3. Структура форума для этой категории существует в Cot::$structure.
    // 4. Категория форума является не корневой (rpath содержит более одного элемента).
    // 5. Для категории есть хотя бы один пост (count > 0).
    if (
        !empty($row['fs_cat'])
        && !$row['fs_lt_id']
        && !empty(Cot::$structure['forums'][$row['fs_cat']])
        && count(explode('.', Cot::$structure['forums'][$row['fs_cat']]['rpath'])) > 1
        && Cot::$structure['forums'][$row['fs_cat']]['count'] > 0
    ) {
        // Если все условия выполняются, обновляем счетчики для структуры форума этой категории.
        cot_forums_updateStructureCounters($row['fs_cat']);
    }
    
    // Добавляем информацию о текущей категории форума в массив $cat_top, используя fs_cat как ключ.
    $cat_top[$row['fs_cat']] = $row;
    
    // Присваиваем дополнительные значения для текущей категории:
    // 1. Количество тем (topiccount) равно значению fs_topiccount.
    // 2. Количество постов (postcount) равно значению fs_postcount.
    // 3. Количество просмотров (viewcount) равно значению fs_viewcount.
    $cat_top[$row['fs_cat']]['topiccount'] = $cat_top[$row['fs_cat']]['fs_topiccount'];
    $cat_top[$row['fs_cat']]['postcount'] = $cat_top[$row['fs_cat']]['fs_postcount'];
    $cat_top[$row['fs_cat']]['viewcount'] = $cat_top[$row['fs_cat']]['fs_viewcount'];
}

// Закрываем курсор запроса для освобождения ресурсов.
$sqlForums->closeCursor();

 

// Инициализируем массивы:
// $fstlvl - массив для хранения категорий первого уровня (разделы верхнего уровня в форуме).
// $nxtlvl - массив для хранения подкатегорий (разделы второго и третьего уровней).
// $cot_act - массив для хранения активности категорий, то есть количества новых сообщений за последние 7 дней.
$fstlvl = $nxtlvl = $cot_act = [];

// Проходим по всем элементам массива Cot::$structure['forums'], где хранятся данные о форумах и их структурах.
foreach (Cot::$structure['forums'] as $i => $x) {
    // Разбиваем путь категории форума на части (например, "main.subcat" превратится в ['main', 'subcat']).
    $parents = explode('.', $x['path']);
    
    // Определяем глубину текущей категории, считая количество элементов в массиве $parents.
    $depth = count($parents);
    
    // Если еще не установлена активность для родительской категории (первого элемента пути), инициализируем её нулем.
    if (!isset($cot_act[$parents[0]])) {
        $cot_act[$parents[0]] = 0;
    }

    // Проверяем, имеет ли текущий пользователь права на чтение форума ($i).
    if (cot_auth('forums', $i, 'R')) {
        
        // Если глубина категории меньше 2 (верхний уровень форума), добавляем её в массив $fstlvl.
        if ($depth < 2) {
            $fstlvl[$i] = $i;
        } 
        // Если глубина категории меньше 4, добавляем её в подкатегории родительской категории.
        elseif($depth < 4) {
            $nxtlvl[$parents[$depth-2]][$i] = $i;
        }
        
        // Определяем максимальную глубину для текущего форума.
        // Если глубина меньше 4, то ограничиваем глубину на один уровень ниже, иначе оставляем 3.
        $depmax = ($depth < 4) ? ($depth - 1) : 3;
        
        // Проходим по родительским категориям на максимальной глубине.
        for ($ii = 0; $ii < $depmax; $ii++) {
            
            // Проверяем, есть ли в текущей категории информация о последнем сообщении (fs_lt_date).
            if (isset($cat_top[$i]['fs_lt_date'])) {
                
                // Если у родительской категории нет данных о последнем сообщении или последнее сообщение в текущей категории новее, обновляем родительскую категорию.
                if (
                    !isset($cat_top[$parents[$ii]]['fs_lt_date'])
                    || ($cat_top[$i]['fs_lt_date'] > $cat_top[$parents[$ii]]['fs_lt_date'])
                ) {
                    // Обновляем информацию о последнем сообщении в родительской категории:
                    // fs_lt_id - ID последнего сообщения.
                    // fs_lt_title - Заголовок темы последнего сообщения.
                    // fs_lt_date - Дата последнего сообщения.
                    // fs_lt_posterid - ID автора последнего сообщения.
                    // fs_lt_postername - Имя автора последнего сообщения.
                    $cat_top[$parents[$ii]]['fs_lt_id'] = $cat_top[$i]['fs_lt_id'];
                    $cat_top[$parents[$ii]]['fs_lt_title'] = $cat_top[$i]['fs_lt_title'];
                    $cat_top[$parents[$ii]]['fs_lt_date'] = $cat_top[$i]['fs_lt_date'];
                    $cat_top[$parents[$ii]]['fs_lt_posterid'] = $cat_top[$i]['fs_lt_posterid'];
                    $cat_top[$parents[$ii]]['fs_lt_postername'] = $cat_top[$i]['fs_lt_postername'];
                }

                // Если в родительской категории не установлено количество тем, инициализируем его нулем.
                if (!isset($cat_top[$parents[$ii]]['topiccount'])) {
                    $cat_top[$parents[$ii]]['topiccount'] = 0;
                }
                // Добавляем количество тем текущей категории к родительской.
                $cat_top[$parents[$ii]]['topiccount'] += $cat_top[$i]['fs_topiccount'];

                // Если в родительской категории не установлено количество сообщений, инициализируем его нулем.
                if (!isset($cat_top[$parents[$ii]]['postcount'])) {
                    $cat_top[$parents[$ii]]['postcount'] = 0;
                }
                // Добавляем количество сообщений текущей категории к родительской.
                $cat_top[$parents[$ii]]['postcount'] += $cat_top[$i]['fs_postcount'];

                // Если в родительской категории не установлено количество просмотров, инициализируем его нулем.
                if (!isset($cat_top[$parents[$ii]]['viewcount'])) {
                    $cat_top[$parents[$ii]]['viewcount'] = 0;
                }
                // Добавляем количество просмотров текущей категории к родительской.
                $cat_top[$parents[$ii]]['viewcount'] += $cat_top[$i]['fs_viewcount'];
            }
        }

        // Если для текущей категории есть данные об активности (количество новых сообщений за неделю),
        // добавляем их в общую активность родительской категории.
        if (isset($cot_sections_act[$i])) {
            $cot_act[$parents[0]] += $cot_sections_act[$i];
        }
    }
}

 

// Определяем максимальную активность среди всех категорий форума.
// Если массив $cot_act содержит данные, выбираем максимальное значение, иначе устанавливаем 0.
$secact_max = count($cot_act) > 0 ? (max($cot_act)) : 0;

// Устанавливаем подзаголовок страницы по умолчанию — "Форумы".
Cot::$out['subtitle'] = Cot::$L['Forums'];

// Проверяем, выбрана ли конкретная категория форума.
if (!empty($c)) {
    // Получаем заголовок категории, очищая его от HTML-тегов и специальных символов.
    $catTitle = htmlspecialchars(strip_tags(Cot::$structure['forums'][$c]['title']));

    // Определяем мета-описание (meta description) для страницы:
    if (!empty(Cot::$cfg['forums']['cat_' . $c]['metadesc'])) {
        // Если в настройках есть мета-описание для данной категории, используем его.
        Cot::$out['desc'] = Cot::$cfg['forums']['cat_' . $c]['metadesc'];
    } elseif (!empty(Cot::$structure['forums'][$c]['desc'])) {
        // Если у категории есть описание в структуре форума, очищаем его и используем.
        Cot::$out['desc'] = htmlspecialchars(strip_tags(Cot::$structure['forums'][$c]['desc']));
    } elseif (!empty(Cot::$cfg['forums']['cat___default']['metadesc'])) {
        // Если у категории нет своего описания, используем мета-описание по умолчанию, добавляя к нему название категории.
        Cot::$out['desc'] = Cot::$cfg['forums']['cat___default']['metadesc'] . ' - ' . $catTitle;
    }

    // Определяем заголовок страницы (title):
    if (!empty(Cot::$cfg['forums']['cat_' . $c]['metatitle'])) {
        // Если в настройках есть заголовок для данной категории, используем его.
        Cot::$out['subtitle'] = Cot::$cfg['forums']['cat_' . $c]['metatitle'];
    } else {
        // В противном случае формируем заголовок из названия категории и общего заголовка "Форумы".
        Cot::$out['subtitle'] = $catTitle . ' - ' . Cot::$L['Forums'];
    }

    // Определяем ключевые слова (meta keywords) для страницы:
    if (!empty(Cot::$cfg['forums']['cat_' . $c]['keywords'])) {
        // Если в настройках есть ключевые слова для данной категории, используем их.
        Cot::$out['keywords'] = Cot::$cfg['forums']['cat_' . $c]['keywords'];
    } elseif (!empty(Cot::$cfg['forums']['cat___default']['keywords'])) {
        // Если у категории нет своих ключевых слов, используем ключевые слова по умолчанию.
        Cot::$out['keywords'] = Cot::$cfg['forums']['cat___default']['keywords'];
    }
}

// Подключаем файл заголовка (header.php), который отвечает за отображение шапки сайта.
require_once Cot::$cfg['system_dir'] . '/header.php';

 

// Создаем новый объект шаблонизатора XTemplate и загружаем шаблон 'forums.sections'.
// Шаблон используется для вывода списка разделов форума.
$t = new XTemplate(cot_tplfile('forums.sections'));

/* === Хук === */
// Выполняем подключение всех доступных плагинов, которые взаимодействуют с основным кодом разделов форума.
// Плагины могут расширять функциональность, добавляя или изменяя поведение кода.
foreach (cot_getextplugins('forums.sections.main') as $pl) {
	include $pl;
}
/* ===== */

// Формируем URL для отметки всех сообщений как прочитанных.
$url_markall = cot_url('forums', "n=markall");

// Создаем массив с элементами хлебных крошек (навигации).
// Добавляем в навигацию ссылку на главную страницу форума.
$title[] = [cot_url('forums'), Cot::$L['Forums']];

// Передаем переменные в шаблон.
$t->assign([
	// Ссылка на RSS-ленту форума.
	'FORUMS_RSS' => cot_url('rss', 'm=forums'),

	// Формируем заголовок страницы с хлебными крошками.
	'FORUMS_SECTIONS_PAGETITLE' => cot_breadcrumbs($title, Cot::$cfg['homebreadcrumb']),

	// Если пользователь авторизован (его ID больше 0), создаем ссылку на отметку всех сообщений как прочитанных.
	'FORUMS_SECTIONS_MARKALL' => (Cot::$usr['id'] > 0) ? cot_rc_link($url_markall, Cot::$L['forums_markallasread']) : '',

	// Сохраняем URL для отметки всех сообщений как прочитанных (если пользователь авторизован).
	'FORUMS_SECTIONS_MARKALL_URL' => (Cot::$usr['id'] > 0) ? $url_markall : '',
]);

 

// Инициализируем счетчик для подсчета разделов форума.
$xx = 0;

/* === Хук - Часть 1: Установка === */
// Получаем плагины, связанные с обработкой главных разделов форума.
$extp = cot_getextplugins('forums.sections.loop');
/* ===== */

/* === Хук - Часть 1: Установка === */
// Получаем плагины, связанные с обработкой подкатегорий форумов (второй уровень).
$extps = cot_getextplugins('forums.sections.loop.sections');
/* ===== */

/* === Хук - Часть 1: Установка === */
// Получаем плагины, связанные с обработкой вложенных подкатегорий форумов (третий уровень).
$extpss = cot_getextplugins('forums.sections.loop.subsections');
/* ===== */

// Перебираем все основные (первого уровня) категории форумов.
foreach ($fstlvl as $x) {
	// Проверяем, есть ли у текущей категории подкатегории и являются ли они массивом.
	if (isset($nxtlvl[$x]) && is_array($nxtlvl[$x])) {
		// Инициализируем счетчик для второго уровня категорий.
		$yy = 0;

		// Перебираем все подкатегории второго уровня.
		foreach ($nxtlvl[$x] as $y) {
			// Проверяем, есть ли у текущей подкатегории свои подкатегории (третий уровень) 
			// и является ли она массивом, а также задан ли параметр 'defstate' в конфигурации.
			if (isset($nxtlvl[$y]) && is_array($nxtlvl[$y]) && Cot::$cfg['forums']['cat_' . $y]['defstate']) {
				// Инициализируем счетчик для третьего уровня категорий.
				$zz = 0;

 

				// Перебираем все подкатегории третьего уровня внутри текущей подкатегории второго уровня.
				foreach ($nxtlvl[$y] as $z) {
					// Увеличиваем счетчик третьего уровня категорий.
					$zz++;

					// Генерируем теги для подкатегории третьего уровня и передаем их в шаблон.
                    $t->assign(cot_generate_sectiontags(
                        $z,
                        'FORUMS_SECTIONS_ROW_',
                        isset($cat_top[$z]) ? $cat_top[$z] : null)
                    );

					// Добавляем в шаблон дополнительные данные:
					$t->assign(array(
						// Чередование строк (odd/even) для стилизации вывода.
						'FORUMS_SECTIONS_ROW_ODDEVEN' => cot_build_oddeven($zz),
						// Номер строки (порядковый номер подкатегории).
						'FORUMS_SECTIONS_ROW_NUM' => $zz,
					));

					/* === Хук - Часть 2: Включение === */
					// Выполняем плагины, связанные с обработкой третьего уровня подкатегорий.
					foreach ($extpss as $pl) {
						include $pl;
					}
					/* ===== */

					// Парсим шаблонный блок для вывода третьего уровня подкатегорий.
					$t->parse('MAIN.FORUMS_SECTIONS.CAT.SECTION.SUBSECTION');
				}
			}
			// Увеличиваем счетчик второго уровня категорий.
			$yy++;

			// Определяем статистические данные для текущей подкатегории второго уровня.
            $stat = isset($cat_top[$y]) ? $cat_top[$y] : null;

			// Генерируем теги для подкатегории второго уровня и передаем их в шаблон.
			$t->assign(cot_generate_sectiontags($y, 'FORUMS_SECTIONS_ROW_', $stat));

 

			// Переменная для активности категории, используется для определения уровня активности по количеству сообщений.
			$secact_num = 0;
			
			// Если существует максимальный уровень активности для категории, рассчитываем его.
			if ($secact_max) {
				// Определяем уровень активности для данной категории, основываясь на числе сообщений в ней.
				$secact_num = isset($cot_sections_act[$y]) ? round(6.25 * $cot_sections_act[$y] / $secact_max) : 0;
				// Ограничиваем максимальное значение активности значением 5.
				$secact_num = ($secact_num > 5) ? 5 : $secact_num;
				// Если уровень активности равен 0, но сообщений больше 1, устанавливаем минимальный уровень активности.
				$secact_num = (!$secact_num && !empty($cot_sections_act[$y]) && $cot_sections_act[$y] > 1) ?
                    1 : $secact_num;
			}

			// Присваиваем переменные шаблону.
			$t->assign(array(
				// Определяем, есть ли у категории подкатегории и в каком состоянии они.
				'FORUMS_SECTIONS_ROW_SUBITEMS' => (isset($nxtlvl[$y]) && Cot::$cfg['forums']['cat_' . $y]['defstate']) ? 1 : 0,
				
				// Отображаем иконку активности категории с вычисленным уровнем активности.
				'FORUMS_SECTIONS_ROW_ACTIVITY' => cot_rc('forums_icon_section_activity', array('secact_num'=>$secact_num)),
				
				// Значение уровня активности категории.
				'FORUMS_SECTIONS_ROW_ACTIVITYVALUE' => $secact_num,
				
				// Чередование строк (odd/even) для стилизации вывода.
				'FORUMS_SECTIONS_ROW_ODDEVEN' => cot_build_oddeven($yy),
				
				// Порядковый номер категории.
				'FORUMS_SECTIONS_ROW_NUM' => $yy,
			));

			/* === Хук - Часть 2: Включение === */
			// Выполняем плагины, связанные с обработкой категории.
			foreach ($extps as $pl) {
				include $pl;
			}
			/* ===== */
			
			// Парсим шаблон для вывода текущей категории.
			$t->parse('MAIN.FORUMS_SECTIONS.CAT.SECTION');
		}
	}

	// Увеличиваем счетчик категорий.
	$xx++;

	// Определяем, свернута ли категория по умолчанию.
	$fold = !Cot::$cfg['forums']['cat_' . $x]['defstate'];
	
	// Если переменная $c не пуста, проверяем, необходимо ли свернуть или развернуть категорию.
	if ($c) {
		$fold = (int) ($c == 'fold' ? true : ($c == 'unfold' ? false : ($c == $x ? false : true)));
	}

 

    // Определяем статистику для текущей категории, если она существует в массиве $cat_top.
    $stat = isset($cat_top[$x]) ? $cat_top[$x] : null;

    // Генерируем и присваиваем шаблонные теги для категории форума.
    $t->assign(cot_generate_sectiontags($x, 'FORUMS_SECTIONS_ROW_', $stat));

    // Присваиваем переменные шаблону, связанные с отображением категории.
    $t->assign([
        // Определяет, должна ли категория быть свернута или развернута.
        'FORUMS_SECTIONS_ROW_FOLD' => $fold,

        // Проверяем, содержит ли текущая категория подкатегории.
        'FORUMS_SECTIONS_ROW_SUBITEMS' => (isset($nxtlvl[$x]) && is_array($nxtlvl[$x])) ? 1 : 0,

        // Определяем четность строки для стилизации (odd/even).
        'FORUMS_SECTIONS_ROW_ODDEVEN' => cot_build_oddeven($xx),

        // Порядковый номер категории.
        'FORUMS_SECTIONS_ROW_NUM' => $xx,
    ]);

    /* === Хук - Часть 2: Включение === */
    // Подключаем плагины, обрабатывающие категорию форума.
    foreach ($extp as $pl) {
        include $pl;
    }
    /* ===== */

    // Парсим шаблон категории форума.
    $t->parse('MAIN.FORUMS_SECTIONS.CAT');
}

// Парсим шаблон для секции форумов.
$t->parse('MAIN.FORUMS_SECTIONS');

/* === Хук === */
// Подключаем плагины, относящиеся к тегам форумов.
foreach (cot_getextplugins('forums.sections.tags') as $pl) {
    include $pl;
}
/* ===== */

// Парсим основной шаблон.
$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();
}

 

17 minutes read Sodium Carbonate

Comments (0)

No comments yet
Only registered users can post new comments

Article multicategories

Additional categories where this article is shown as similar.

Content author

webitproff

Offline

Sodium Carbonate

Last logged: 2026-09-18 20:01

About me briefly
Support and development of web projects on the CMF Cotonti: private messengers via the website, open and closed small social networks, trading platforms and marketplaces, freelance and services exchange portal, catalogs of goods from wholesale suppliers, dropshipping platforms, online stores, and much more.
View developments and download
Public portfolio of my works and developments
Telegram for messages
@webitproff
Telegram channel
@s/aBuyFILE
  • Page published: 2025-02-10 17:50
  • Last update: 2025-02-11 19:56
  • Attachment available

    Download file now

    Downloaded: 30 times

Similar pages

Файл forums.setup.php в Cotonti
1 Описание файла forums.setup.php в Cotonti CMF 1. Основное назначение файла и его место в системе Cotonti Файл
Файл forums.php в Cotonti
2 Файл forums.php является основным скриптом, отвечающим за работу модуля форума в системе Cotonti CMF. Он расположен в
Файл "forums.extrafields.php" в системе Cotonti CMF
3 Файл "forums.extrafields.php" в системе Cotonti CMF является частью модуля Forums и используется для
Файл "forums.admin.php" в Cotonti
4 Файл "forums.admin.php" в Cotonti CMF — это административный скрипт, который управляет функциональностью
Файл forums.trashcan.php в Cotonti
5 Файл forums.trashcan.php в Cotonti CMF предназначен для обработки и поддержки функционала корзины для модуля форумов.