Модуль "Users", -users.main.php в Cotonti CMF

Файл "users.main.php" является частью модуля users в системе Cotonti CMF. Этот файл отвечает за обработку и отображение списка пользователей на сайте, включая функции сортировки, фильтрации и динамической загрузки данных. Он взаимодействует с различными компонентами системы, включая плагины, обработку URL-параметров и взаимодействие с базой данных для генерации информации о пользователях.

Основное назначение файла и его место в системе Cotonti

Этот файл является компонентом модуля, который управляет списками пользователей, их фильтрацией и сортировкой. Он хранится в директории /modules/users/inc, что указывает на его тесную связь с модулем users, который обеспечивает функциональность для управления пользователями на сайте. Основная задача файла — это подготовка и вывод данных о пользователях на страницу сайта, а также управление их отображением в зависимости от параметров фильтрации и сортировки.

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

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

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

  1. Шаблоны: Этот файл активно взаимодействует с системой шаблонов XTemplate для динамической генерации HTML-кода. Он использует методы, такие как $t->assign() и $t->parse(), для присвоения значений переменным и последующего вывода с помощью шаблонов.
  2. Плагины: Он поддерживает хуки, которые позволяют другим плагинам расширять функциональность, например, добавляя дополнительные поля или теги для пользователей.
  3. URL и параметры запроса: Взаимодействует с параметрами URL для фильтрации, сортировки и пагинации данных о пользователях.
  4. JavaScript: Включает динамическую обработку форм для фильтрации, скрывая пустые элементы и автоматически отправляя форму при изменении значений.

Переменные, хуки, методы, функции и классы

  • Переменные:

    • $jj: Счетчик для определения четности строк при выводе пользователей, используется для стилизации таблицы.
    • $extp: Массив плагинов, которые подключаются через хуки, расширяя функциональность обработки пользователей.
    • $usersSortFields: Массив полей сортировки и их заголовков, использующийся для генерации ссылок сортировки.
    • $users_url_path: Параметры URL для отображения списка пользователей с параметрами фильтрации и сортировки.
    • $sortWayParams: Параметры для изменения порядка сортировки пользователей.
    • $s и $w: Параметры сортировки и направления сортировки, получаемые из URL.
  • Методы и функции:

    • cot_getextplugins(): Функция для получения плагинов, которые могут быть подключены для расширения функциональности в процессе вывода пользователей.
    • cot_build_oddeven(): Генерирует классы для четных и нечетных строк в таблице (для стилизации).
    • cot_generate_usertags(): Генерирует теги для пользователя, чтобы вставить их в шаблон для отображения.
    • cot_url(): Генерирует URL с необходимыми параметрами для фильтрации, сортировки и пагинации.
    • cot_rc(): Функция для создания динамических ссылок и HTML-элементов, например, для сортировки.
    • cot_selectbox(): Создает HTML-элемент select для выбора сортировки.
    • Resources::embedFooter(): Встраивает JavaScript в подвал страницы для динамичного обновления фильтров.
  • Хуки:

описание каждого хука:

  1. users.first
    Этот хук вызывается на самом первом этапе работы с пользователями, когда происходит начальная загрузка или обработка данных о пользователе. Плагины, подключенные к этому хуку, могут изменять или добавлять функциональность, которая нужна сразу после начала обработки.

  2. users.query
    Хук выполняется после того, как запрос к базе данных для получения данных о пользователе был сформирован, но до того, как эти данные будут обработаны. Плагины могут изменять или фильтровать SQL-запросы, использовать его для создания дополнительных запросов или просто взаимодействовать с базой данных.

  3. users.main
    Этот хук выполняется в основной части работы с пользователями, когда обрабатываются или отображаются данные, которые были получены из базы данных. Плагины, подключенные к этому хуку, могут изменять основные данные о пользователях или добавлять новый функционал на этом этапе.

  4. users.filters
    Хук, предназначенный для фильтрации данных. Он может быть использован для добавления дополнительных фильтров или настроек, позволяющих изменять то, как пользователи или их данные отображаются, например, по категориям или статусам. Плагины могут подключаться к этому хука для добавления логики фильтрации.

  5. users.loop
    Этот хук делится на два этапа:

    • Part 1: Set — Здесь происходит подготовка данных, возможно, настройка массива плагинов, которые должны быть подключены к данному хуку.
    • Part 2: Include — На этом этапе происходит включение самих плагинов, которые будут обрабатывать или использовать данные, подготовленные на первом этапе.
  6. users.tags
    Этот хук связан с тегами, с метками или дополнительными атрибутами, которые могут быть добавлены к пользователям. Плагины, подключенные к этому хуку, могут работать с этими тегами, модифицировать их или выводить дополнительные данные.

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

 

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

  1. Обработка сортировки и фильтрации:

    • В коде реализована логика для сортировки пользователей по различным полям. Параметры сортировки (asc или desc) передаются через URL.
    • Для каждого поля сортировки генерируются динамические URL, которые позволяют пользователю изменять порядок сортировки.
  2. Подключение плагинов:

    • Используются хуки для подключения плагинов, которые могут добавлять дополнительную информацию или изменять вывод данных. Плагины могут расширять функциональность модуля, добавляя дополнительные поля или изменяя логику вывода.
  3. Формы фильтрации:

    • Встроен JavaScript, который динамически управляет элементами фильтрации, скрывая пустые поля и отправляя форму при изменении значений.
    • Это позволяет улучшить взаимодействие с пользователем, облегчая процесс фильтрации и сортировки данных.
  4. Генерация списка пользователей:

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

    • JavaScript обрабатывает изменения формы фильтрации, автоматически отправляя данные формы для обновления списка пользователей.

Использование владельцем сайта

Владелец сайта может использовать этот код для:

  • Отображения и управления списком пользователей на сайте.
  • Настройки фильтров и сортировки для улучшенного взаимодействия с пользователями.
  • Расширения функционала модуля с помощью плагинов.
  • Добавления дополнительных пользовательских полей и тегов для вывода на странице списка пользователей.

Стиль написания кода и совместимость с версиями PHP

  1. Стиль кода:

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

 

 

<?php
/**
 * Users list
 *
 * @package Users
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

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

$id = cot_import('id', 'G', 'INT'); // Получение параметра 'id' из глобального массива GET, преобразование в целое число.
$s = cot_import('s', 'G', 'ALP', 16); // Получение параметра 's' из глобального массива GET, преобразование в строку (буквы и цифры), максимальная длина 16 символов.
$w = cot_import('w', 'G', 'ALP', 4); // Получение параметра 'w' из глобального массива GET, преобразование в строку (буквы и цифры), максимальная длина 4 символа.

list($pg, $d, $durl) = cot_import_pagenav('d', Cot::$cfg['users']['maxusersperpage']); // Получение данных о пагинации: текущая страница, смещение и URL для пагинации.
$g = cot_import('g', 'G', 'INT'); // Получение параметра 'g' из глобального массива GET, преобразование в целое число (группа пользователей).
$gm = cot_import('gm', 'G', 'INT'); // Получение параметра 'gm' из глобального массива GET, преобразование в целое число (подгруппа пользователей).
$sq = cot_import('sq', 'G', 'TXT', 16); // Получение параметра 'sq' из глобального массива GET, преобразование в строку, максимальная длина 16 символов.
$country = cot_import('country', 'G', 'ALP', 2); // Получение параметра 'country' из глобального массива GET, преобразование в строку (2 символа).
if (!empty($country)) { 
    $country = mb_strtolower($country); // Преобразование значения страны в нижний регистр.
}
unset($localskin, $grpms); // Удаление переменных $localskin и $grpms, чтобы они не оставались в памяти.

list(Cot::$usr['auth_read'], Cot::$usr['auth_write'], Cot::$usr['isadmin']) = cot_auth('users', 'a'); // Проверка прав доступа текущего пользователя для модуля 'users' (чтение, запись, администратор).
cot_block(Cot::$usr['auth_read']); // Если у пользователя нет прав на чтение, выполнение скрипта будет остановлено.

require_once cot_langfile('users', 'module'); // Подключение языкового файла для модуля 'users'.
require_once cot_langfile('countries', 'core'); // Подключение языкового файла для модуля 'countries'.

В этом фрагменте кода происходит подготовка данных для отображения списка пользователей. Загрузка различных параметров из глобального массива $_GET для дальнейшей обработки, а также проверка прав пользователя.

 

$defaultSortField = 'name'; // Установка значения по умолчанию для поля сортировки - 'name'.
$defaultSortWay = 'asc'; // Установка значения по умолчанию для направления сортировки - 'asc' (по возрастанию).

$users_sort_tags = [ // Массив с определением доступных колонок для сортировки пользователей.
	// columns in $db_users table
	'id' => ['USERS_TOP_USER_ID', &Cot::$L['Userid']], // Сортировка по идентификатору пользователя, метка 'USERS_TOP_USER_ID' и перевод 'Userid'.
	'name' => ['USERS_TOP_NAME', Cot::$L['Username'] . ' (login)'], // Сортировка по имени пользователя, метка 'USERS_TOP_NAME' и перевод 'Username (login)'.
	'maingrp' => ['USERS_TOP_MAIN_GROUP', &Cot::$L['Maingroup']], // Сортировка по основной группе пользователя, метка 'USERS_TOP_MAIN_GROUP' и перевод 'Maingroup'.
	'country' => ['USERS_TOP_COUNTRY', &Cot::$L['Country']], // Сортировка по стране пользователя, метка 'USERS_TOP_COUNTRY' и перевод 'Country'.
	'timezone' => ['USERS_TOP_TIMEZONE', &Cot::$L['Timezone']], // Сортировка по часовой зоне пользователя, метка 'USERS_TOP_TIMEZONE' и перевод 'Timezone'.
	'birthdate' => ['USERS_TOP_BIRTHDATE', &Cot::$L['Birthdate']], // Сортировка по дате рождения пользователя, метка 'USERS_TOP_BIRTHDATE' и перевод 'Birthdate'.
	'gender' => ['USERS_TOP_GENDER', &Cot::$L['Gender']], // Сортировка по полу пользователя, метка 'USERS_TOP_GENDER' и перевод 'Gender'.
	'regdate' => ['USERS_TOP_REGISTRATION_DATE', &Cot::$L['Registered']], // Сортировка по дате регистрации пользователя, метка 'USERS_TOP_REGISTRATION_DATE' и перевод 'Registered'.
	'lastlog' => ['USERS_TOP_LAST_LOGGED', &Cot::$L['Lastlogged']], // Сортировка по последнему входу пользователя, метка 'USERS_TOP_LAST_LOGGED' и перевод 'Lastlogged'.
	'logcount' => ['USERS_TOP_LOGINS_COUNT', &Cot::$L['users_logcounter']], // Сортировка по количеству входов пользователя, метка 'USERS_TOP_LOGINS_COUNT' и перевод 'users_logcounter'.
	// like columns in $db_groups table
	'grplevel' => ['USERS_TOP_GROUP_LEVEL', &Cot::$L['Level']], // Сортировка по уровню группы пользователя, метка 'USERS_TOP_GROUP_LEVEL' и перевод 'Level'.
	//'grpname' => ['USERS_TOP_GROUP_TITLE', &Cot::$L['Maingroup']], // (закомментировано) Сортировка по названию группы пользователя, метка 'USERS_TOP_GROUP_TITLE' и перевод 'Maingroup'.
];

Этот код создает массив $users_sort_tags, который содержит информацию о доступных столбцах для сортировки в таблице пользователей. Массив определяет, по каким полям можно сортировать, и какие метки и переводы будут использованы для отображения этих полей. Поля включают информацию о пользователе, такую как ID, имя, группа, страна, часовой пояс, дата рождения, пол, дата регистрации, последний вход и количество входов.

 

/* @todo move to Forums module */ // TODO комментарий: переместить этот код в модуль форума.

if (cot_module_active('forums')) { // Проверка, активен ли модуль 'forums' (форумы).
    if (empty(Cot::$L['forums_posts'])) { // Если в языке не определен перевод для 'forums_posts' (посты форума).
        include_once cot_langfile('forums', 'module'); // Подключение языкового файла модуля 'forums', если перевод для 'forums_posts' отсутствует.
    }
    $users_sort_tags['postcount'] = ['USERS_TOP_POSTS_COUNT', &Cot::$L['forums_posts']]; // Добавление нового поля 'postcount' в массив $users_sort_tags для сортировки по количеству постов форума. Используется метка 'USERS_TOP_POSTS_COUNT' и перевод 'forums_posts'.
}

Этот код проверяет, активен ли модуль форумов, и если он активен, добавляет в массив $users_sort_tags новое поле для сортировки по количеству постов пользователей на форуме. В случае отсутствия перевода для "forums_posts", подключается языковой файл модуля форумов.

 

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

$usersSortFieldsBlacklist = [ // Массив черного списка полей, которые не будут использоваться для сортировки.
    'banexpire', // Время окончания бана пользователя.
    'password', // Пароль пользователя.
    'passfunc', // Функция хеширования пароля.
    'passsalt', // Соль пароля.
    'email', // Электронная почта пользователя.
    'lastip', // Последний IP-адрес пользователя.
    'sid', // Сессия пользователя.
    'sidtime', // Время сессии пользователя.
    'lostpass', // Данные для восстановления пароля.
    'auth', // Права пользователя.
    'token' // Токен безопасности пользователя.
];

$users_url_path = []; // Инициализация пустого массива для хранения путей URL пользователей.
$where = []; // Инициализация пустого массива для условий SQL-запроса.
$params = []; // Инициализация пустого массива для параметров SQL-запроса.
$joinColumns = []; // Инициализация пустого массива для столбцов SQL JOIN.
$joinCondition = []; // Инициализация пустого массива для условий SQL JOIN.
$filterOrSortActive = false; // Флаг для проверки активности фильтрации или сортировки.

 /* === Hook === */
foreach (cot_getextplugins('users.first') as $pl) { // Цикл для обработки всех плагинов, зарегистрированных в хук 'users.first'.
    include $pl; // Включение каждого плагина.
}
/* ===== */

Этот участок кода инициализирует переменные для сортировки пользователей, фильтрации, а также для работы с условиями SQL-запросов. Включает в себя массив с полями, которые не должны быть использованы для сортировки, и обрабатывает плагины, зарегистрированные в хуке 'users.first'.

 

if (empty($d)) { // Проверка, если переменная $d пуста.
	$d = 0; // Если пуста, то присваивается значение 0.
}

$title = []; // Инициализация пустого массива для заголовков страницы.
$metaTitle = []; // Инициализация пустого массива для мета-заголовков.
$metaDesc = []; // Инициализация пустого массива для мета-описаний.
$localskin = cot_tplfile('users', 'module'); // Получение имени шаблона для модуля пользователей.

if ($s === 'grplevel' || $s === 'grpname' || $gm > 1) { // Условие для проверки параметра сортировки $s или уровня группы $gm.
	$joinCondition['mainGroup'] = 'LEFT JOIN ' . Cot::$db->groups . ' as g ON g.grp_id = u.user_maingrp'; // Добавление условия для SQL JOIN с таблицей групп, если выполняются условия.
}

if ($sq !== null && $sq !== '') { // Проверка, если параметр поиска $sq не пуст и не равен null.
    $titleString = Cot::$L['Search'] . " '{$sq}'"; // Формирование строки заголовка для страницы поиска.
	$title[] = htmlspecialchars($titleString); // Добавление строки в массив заголовков, с экранированием HTML.
    $metaTitle[] = $titleString; // Добавление строки в массив мета-заголовков.
    $metaDesc[] = $titleString; // Добавление строки в массив мета-описаний.

    $searchCondition = ['name' => 'user_name LIKE :search']; // Инициализация условия для поиска по имени пользователя.
    $params['search'] = "%{$sq}%"; // Добавление параметра для поиска в базу данных, с подстановкой строки поиска.

    if (!empty(Cot::$extrafields[Cot::$db->users])) { // Проверка, если существуют дополнительные поля для пользователей.
        $searchFields = ['first_name', 'firstname', 'last_name', 'lastname', 'middle_name', 'middlename']; // Определение полей, по которым будет происходить поиск.
        foreach ($searchFields as $searchField) { // Цикл по всем дополнительным полям.
            if (!isset(Cot::$extrafields[Cot::$db->users][$searchField])) { // Проверка, если поле не существует в данных.
                continue; // Если поле не существует, пропустить итерацию.
            }
            $searchCondition[$searchField] =  "user_{$searchField} LIKE :search"; // Добавление условия поиска по дополнительным полям.
        }
    }
    $where['namelike'] = '(' . implode(' OR ', $searchCondition) . ')'; // Формирование общего условия для поиска по имени и дополнительным полям.
    $users_url_path['sq'] = $sq; // Добавление строки поиска в путь URL для использования при пагинации.
    $filterOrSortActive = true; // Установка флага активности фильтрации или сортировки.
}

Этот участок кода отвечает за обработку поискового запроса на странице пользователей, настройку условий поиска и фильтрации, а также за создание заголовков страницы и мета-данных. Включает в себя проверку параметров сортировки, фильтрации по группам и создание SQL-запросов для поиска по полям базы данных пользователей и их дополнительным полям.

 

if ( // Начало условия для проверки параметра группы $g.
    !empty($g) // Проверка, если параметр $g не пуст.
    && ( // Если $g не пуст, продолжаем проверку условий.
        !isset($cot_groups[$g]) // Проверка, существует ли группа с идентификатором $g в массиве $cot_groups.
        || ( // Или проверка дополнительных условий.
            !Cot::$usr['isadmin'] // Если пользователь не является администратором.
            && ( // Дополнительные условия, если пользователь не администратор.
                $cot_groups[$g]['hidden'] // Если группа скрыта.
                || $cot_groups[$g]['disabled'] // Или если группа отключена.
            )
        )
    )
) {
    cot_die_message(404); // Если одно из условий выполнено, выводим ошибку 404 (группа не найдена или доступ запрещен).
}

if ( // Начало условия для проверки параметра группы $gm.
    !empty($gm) // Проверка, если параметр $gm не пуст.
    && ( // Если $gm не пуст, продолжаем проверку условий.
        !isset($cot_groups[$gm]) // Проверка, существует ли группа с идентификатором $gm в массиве $cot_groups.
        || ( // Или проверка дополнительных условий.
            !Cot::$usr['isadmin'] // Если пользователь не является администратором.
            && ( // Дополнительные условия, если пользователь не администратор.
                $cot_groups[$gm]['hidden'] // Если группа скрыта.
                || $cot_groups[$gm]['disabled'] // Или если группа отключена.
            )
        )
    )
) {
    cot_die_message(404); // Если одно из условий выполнено, выводим ошибку 404 (группа не найдена или доступ запрещен).
}

Этот участок кода проверяет параметры групп $g и $gm. Если указаны идентификаторы групп, которые либо не существуют, либо скрыты или отключены для пользователей, не являющихся администраторами, то выводится ошибка 404, чтобы предотвратить доступ к этим группам.

 

if ($g > 1) { // Если параметр $g больше 1, то продолжаем выполнение условий.
    $grpTitle = Cot::$L['Group'] . ": '" . cot_build_group($g) . "'"; // Формируем название группы с использованием функции cot_build_group для получения имени группы по ID $g.
    $grpTitleDesc = []; // Инициализация массива для описания группы.

    if ($cot_groups[$g]['hidden']) { // Проверка, если группа скрыта.
        $grpTitleDesc[] = Cot::$L['Hidden']; // Добавляем в описание группы "Hidden", если группа скрыта.
    }

    if ($cot_groups[$g]['disabled']) { // Проверка, если группа отключена.
        $grpTitleDesc[] = Cot::$L['Disabled']; // Добавляем в описание группы "Disabled", если группа отключена.
    }

    if (!empty($grpTitleDesc)) { // Если есть описание группы.
        $grpTitle .= ' (' . implode(', ', $grpTitleDesc) . ')'; // Добавляем описание группы в заголовок, объединяя элементы через запятую.
    }

    $title[] = $grpTitle; // Добавляем заголовок группы в массив заголовков.
    $titleString = strip_tags($grpTitle); // Убираем все HTML-теги из строки заголовка группы.
    $metaTitle[] = $titleString; // Добавляем мета-заголовок.
    $metaDesc[] = $titleString // Добавляем мета-описание (без HTML-тегов) с дополнительным описанием группы, если оно существует.
        . (!empty($cot_groups[$g]['desc']) ? ' - ' . $cot_groups[$g]['desc'] : ''); // Если описание группы есть, добавляем его к мета-описанию.

    $joinCondition['groupsUsers'] = ' LEFT JOIN ' . Cot::$db->groups_users . ' as m ON m.gru_userid = u.user_id '; // Добавляем условие для соединения с таблицей групп пользователей.
    $where['group'] = 'm.gru_groupid = ' . $g; // Условие для фильтрации пользователей по группе с ID $g.
    $users_url_path['g'] = $g; // Добавляем параметр группы в путь URL.
    $filterOrSortActive = true; // Устанавливаем флаг, что фильтрация или сортировка активны.
}

Этот участок кода выполняет несколько действий, если параметр $g (идентификатор группы) больше 1:

  1. Формирует заголовок для группы, добавляя описание (если группа скрыта или отключена).
  2. Устанавливает мета-заголовок и описание, а также обновляет массивы заголовков и мета-данных.
  3. Добавляет SQL-условия для соединения с таблицей пользователей, состоящих в группе, и фильтрует пользователей по группе с заданным идентификатором.
  4. Устанавливает флаг, что фильтрация или сортировка активны.

 

if ($gm > 1) { // Если параметр $gm больше 1, то продолжаем выполнение условий.
    $grpTitle = Cot::$L['Maingroup'] . ": '" . cot_build_group($gm) . "'"; // Формируем название основной группы с использованием функции cot_build_group для получения имени группы по ID $gm.
    $grpTitleDesc = []; // Инициализация массива для описания группы.

    if ($cot_groups[$gm]['hidden']) { // Проверка, если основная группа скрыта.
        $grpTitleDesc[] = Cot::$L['Hidden']; // Добавляем в описание группы "Hidden", если группа скрыта.
    }

    if ($cot_groups[$gm]['disabled']) { // Проверка, если основная группа отключена.
        $grpTitleDesc[] = Cot::$L['Disabled']; // Добавляем в описание группы "Disabled", если группа отключена.
    }

    if (!empty($grpTitleDesc)) { // Если есть описание группы.
        $grpTitle .= ' (' . implode(', ', $grpTitleDesc) . ')'; // Добавляем описание группы в заголовок, объединяя элементы через запятую.
    }

    $title[] = $grpTitle; // Добавляем заголовок основной группы в массив заголовков.
    $titleString = strip_tags($grpTitle); // Убираем все HTML-теги из строки заголовка основной группы.
    $metaTitle[] = $titleString; // Добавляем мета-заголовок.
    $metaDesc[] = $titleString // Добавляем мета-описание (без HTML-тегов) с дополнительным описанием группы, если оно существует.
        . (!empty($cot_groups[$gm]['desc']) ? ' - ' . $cot_groups[$gm]['desc'] : ''); // Если описание группы есть, добавляем его к мета-описанию.

    $where['mainGroup'] = 'user_maingrp = ' . $gm; // Условие для фильтрации пользователей по основной группе с ID $gm.
    $users_url_path['gm'] = $gm; // Добавляем параметр основной группы в путь URL.
    $filterOrSortActive = true; // Устанавливаем флаг, что фильтрация или сортировка активны.
}

Этот участок кода выполняет несколько действий, если параметр $gm (идентификатор основной группы) больше 1:

  1. Формирует заголовок для основной группы, добавляя описание (если группа скрыта или отключена).
  2. Устанавливает мета-заголовок и описание, а также обновляет массивы заголовков и мета-данных.
  3. Добавляет SQL-условие для фильтрации пользователей по основной группе с заданным идентификатором.
  4. Устанавливает флаг, что фильтрация или сортировка активны.

 

if ($country !== null && $country !== '') { // Проверяем, что переменная $country не пуста и не равна null.
    if ($country !== '00' && !isset($cot_countries[$country])) { // Если $country не равно '00' и такого кода страны нет в массиве $cot_countries.
        cot_die_message(404); // Прерываем выполнение и выводим ошибку 404 (страница не найдена), если страна не найдена.
    }
    $titleString = Cot::$L['Country'] . ": '" . ($country === '00' ? Cot::$L['None'] : $cot_countries[$country]) . "'"; // Формируем строку заголовка: если код страны '00', выводим "None", иначе - название страны.
    $title[] = htmlspecialchars($titleString); // Добавляем обработанную строку заголовка в массив $title (с защитой от XSS).
    $metaTitle[] = $titleString; // Добавляем строку заголовка в массив мета-заголовков.
    $metaDesc[] = $titleString; // Добавляем строку заголовка в массив мета-описаний.

    $where['country'] = "user_country = :country"; // Создаем SQL-условие для фильтрации пользователей по стране.
    $params['country'] = $country; // Добавляем параметр для SQL-запроса.
    $users_url_path['country'] = $country; // Добавляем параметр страны в URL путь.
    $filterOrSortActive = true; // Устанавливаем флаг, что фильтрация или сортировка активны.
}

Этот участок кода выполняет следующие действия, если параметр $country (код страны) задан:

  1. Проверяет, существует ли указанная страна в массиве $cot_countries. Если код страны неверный (отличается от '00' и отсутствует в массиве), выводится ошибка 404.
  2. Формирует строку для заголовка и мета-данных, где отображается либо название страны, либо "None" (для страны с кодом '00').
  3. Добавляет SQL-условие для фильтрации пользователей по стране.
  4. Устанавливает параметр страны в URL и активирует флаг фильтрации или сортировки.

 

$titleString = ''; // Инициализируем переменную для строки заголовка.

if (empty($s)) { // Если параметр $s (поле для сортировки) не задан.
    $s = $defaultSortField; // Присваиваем значение поля для сортировки по умолчанию.
} elseif (
    in_array(mb_strtolower($s), $usersSortFieldsBlacklist) // Если значение $s содержится в списке запрещенных полей для сортировки.
    || (!isset($users_sort_tags[$s]) && !Cot::$db->fieldExists(Cot::$db->users, "user_$s")) // Или если поле не существует в списке сортировки или в базе данных.
) {
    cot_die_message(404); // Если одно из условий истинно, выводим ошибку 404.
} elseif ($s !== $defaultSortField) { // Если значение $s не равно полю сортировки по умолчанию.
    $users_url_path['s'] = $s; // Добавляем параметр сортировки в URL.

    $fieldTitle = $s; // Присваиваем значение поля сортировки переменной $fieldTitle.
    if (isset($users_sort_tags[$s])) { // Если в массиве $users_sort_tags существует ключ, соответствующий значению $s.
        $fieldTitle = $users_sort_tags[$s][1]; // Присваиваем описание поля сортировки из массива.
    } elseif (isset(Cot::$L['user_' . $s . '_title'])) { // Если существует перевод для этого поля.
        $fieldTitle = Cot::$L['user_' . $s . '_title']; // Используем перевод в качестве заголовка.
    } elseif (
        isset(Cot::$extrafields[Cot::$db->users][$s]) // Если для поля есть дополнительное описание в экстра-полях.
        && !empty(Cot::$extrafields[Cot::$db->users][$s]['field_description'])
    ) {
        $fieldTitle = Cot::$extrafields[Cot::$db->users][$s]['field_description']; // Используем описание из экстра-полей.
    }

    $titleString = Cot::$L['OrderBy'] . " '" . $fieldTitle ."'"; // Формируем строку заголовка с указанием поля сортировки.
    $filterOrSortActive = true; // Устанавливаем флаг, что фильтрация или сортировка активированы.
}

if (!in_array($w, ['asc', 'desc'])) { // Если параметр $w (направление сортировки) не задан или не соответствует 'asc' или 'desc'.
    $w = $defaultSortWay; // Присваиваем значение по умолчанию для сортировки (восходящий порядок).
} elseif ($w !== $defaultSortWay) { // Если направление сортировки отличается от дефолтного.
    $users_url_path['w'] = $w; // Добавляем параметр сортировки в URL.

    // @todo translate
    $titleString .= ($titleString === '' ? Cot::$L['Order'] : '') . ' descending'; // Если нет строки заголовка, добавляем описание направления сортировки как "descending".
    $filterOrSortActive = true; // Устанавливаем флаг активной сортировки.
}

if ($titleString !== '') { // Если строка заголовка не пуста.
    //$title[] = $titleString; // (Закомментировано) Добавляем строку заголовка в массив $title.
    $metaTitle[] = $titleString; // Добавляем строку заголовка в мета-заголовок.
    $metaDesc[] = $titleString; // Добавляем строку заголовка в мета-описание.
}

Этот участок кода отвечает за обработку параметров сортировки:

  1. Проверяется наличие параметра $s (поле сортировки) и его корректность.
  2. Если параметр $s не задан или некорректен, используется значение по умолчанию.
  3. При корректном значении $s (если оно не в черном списке) добавляется описание для выбранного поля сортировки, которое будет отображаться в заголовке страницы и мета-данных.
  4. Параметр $w (направление сортировки) проверяется на корректность. Если он не указан или некорректен, используется дефолтное направление сортировки.
  5. Формируется строка заголовка и мета-данных с информацией о порядке сортировки.
  6. Если параметры сортировки активированы, соответствующие флаги устанавливаются в true и добавляются в URL.

 

switch ($s) { // Переходим к условной конструкции для выбора поля сортировки.
	case 'grplevel': // Если поле сортировки — 'grplevel' (уровень группы).
		$sqlorder = "g.grp_level $w"; // Устанавливаем порядок сортировки по уровню группы.
		break; // Завершаем обработку этого случая.
	case 'grpname': // Если поле сортировки — 'grpname' (имя группы).
		$sqlorder = "g.grp_name $w"; // Устанавливаем порядок сортировки по имени группы.
		break; // Завершаем обработку этого случая.
	default: // Если ни одно из условий не подошло.
		$sqlorder = "user_$s $w"; // Используем имя поля пользователя для сортировки, с направлением сортировки $w.
		break; // Завершаем обработку.
}

Этот участок кода выполняет сортировку пользователей по различным полям, в зависимости от значения переменной $s (поле сортировки). В случае выбора сортировки по группе (grplevel, grpname), используются соответствующие поля группы. В других случаях выбирается поле пользователя с префиксом user_. Сортировка осуществляется в направлении, заданном переменной $w (восходящем или нисходящем).

 

/* === Hook === */
foreach (cot_getextplugins('users.query') as $pl) { // Цикл для подключения дополнительных плагинов, которые могут изменить или расширить запрос.
	include $pl; // Подключение плагинов, если таковые существуют.
}
/* ===== */

if (!isset($join_condition)) { // Если переменная $join_condition не определена.
    $join_condition = ''; // Инициализация переменной с пустым значением.
}
if (!empty($joinCondition)) { // Если массив $joinCondition не пуст.
    if ($join_condition !== '') { // Если переменная $join_condition уже содержит данные.
        $join_condition .= " \n"; // Добавляем разрыв строки для улучшения читаемости.
    }
    $join_condition .= implode(" \n", $joinCondition); // Соединяем элементы массива $joinCondition в строку.
}
if (!isset($join_columns)) { // Если переменная $join_columns не определена.
    $join_columns = ''; // Инициализация переменной с пустым значением.
}
if (!empty($joinColumns)) { // Если массив $joinColumns не пуст.
    if ($join_columns !== '') { // Если переменная $join_columns уже содержит данные.
        $join_columns .= ", "; // Добавляем запятую для разделения столбцов.
    }
    $join_columns .= implode(", ", $joinColumns); // Соединяем элементы массива $joinColumns в строку.
}

$sqlWhere = ''; // Инициализация переменной для условия WHERE.
if (!empty($where)) { // Если массив $where не пуст.
    $sqlWhere = ' WHERE ' . implode(' AND ', $where); // Формируем строку с условиями WHERE.
}

$totalusers = Cot::$db->query( // Выполняем SQL-запрос для подсчета общего числа пользователей.
    'SELECT COUNT(*) FROM ' . Cot::$db->users . ' AS u ' . $join_condition . $sqlWhere, // Запрос для подсчета количества пользователей с учетом соединений и условий.
    $params // Параметры для подстановки значений в запрос.
)->fetchColumn(); // Извлекаем результат (общее количество пользователей).

// Disallow accessing non-existent pages
if ($totalusers > 0 && $d > $totalusers) { // Если запрашиваемая страница существует, но номер страницы $d превышает общее количество пользователей.
	cot_die_message(404); // Вызываем ошибку 404 (страница не найдена).
}

Этот блок кода отвечает за подготовку SQL-запроса для получения информации о пользователях и подсчета их количества. Он учитывает дополнительные условия сортировки, объединения таблиц и фильтры. Также в нем выполняется проверка, чтобы предотвратить доступ к несуществующим страницам.

 

$users = Cot::$db->query( // Выполняем SQL-запрос для извлечения пользователей.
	"SELECT u.* $join_columns FROM " . Cot::$db->users . ' AS u ' . $join_condition . $sqlWhere
	. " ORDER BY $sqlorder LIMIT $d, " . Cot::$cfg['users']['maxusersperpage'], // Формируем запрос с учетом условий сортировки и ограничений по страницам.
    $params // Параметры для подстановки значений в запрос.
)->fetchAll(); // Извлекаем все результаты в массив.

if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // Проверка на наличие устаревшей конфигурации.
    /** @deprecated in 0.9.24 */
    $sqlusers = &$users; // Ссылочное присваивание устаревшей переменной (не рекомендуется).
}

$pagenav = cot_pagenav('users', $users_url_path, $d, $totalusers, Cot::$cfg['users']['maxusersperpage']); // Генерация навигации по страницам пользователей.

$titleAddon = ''; // Инициализация переменной для дополнительного титула страницы.
if (!empty($title)) { // Если массив $title не пуст.
    $titleAddon = implode(', ', $title); // Объединяем элементы массива $title в строку.
    if ($titleAddon !== '') { // Если строка $titleAddon не пуста.
        $titleAddon = ', ' . $titleAddon; // Добавляем запятую в начало строки.
    }
}

Cot::$out['subtitle'] = Cot::$L['users_meta_title'] . $titleAddon; // Устанавливаем подзаголовок страницы.
Cot::$out['desc'] = Cot::$L['users_meta_desc']; // Устанавливаем описание страницы.
if (!empty($metaTitle)) { // Если массив $metaTitle не пуст.
    Cot::$out['subtitle'] .= '. ' . implode(', ', $metaTitle); // Добавляем дополнительные титулы в подзаголовок.
}
if (!empty($metaDesc)) { // Если массив $metaDesc не пуст.
    Cot::$out['desc'] .= '. ' . implode(', ', $metaDesc); // Добавляем дополнительные описания в метаописание.
}

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

 

// Building the canonical URL
$canonicalUrlParams = $users_url_path; // Создаем массив параметров URL для канонической ссылки.
if ($durl > 1) { // Если страница не первая.
    $canonicalUrlParams['d'] = $durl; // Добавляем параметр страницы.
}
Cot::$out['canonical_uri'] = cot_url('users', $canonicalUrlParams); // Формируем канонический URL и записываем его в переменную для использования в мета-тегах.

if ($filterOrSortActive === true) { // Если активированы фильтры или сортировка.
    if (!isset(Cot::$out['head'])) { // Если переменная 'head' еще не задана.
        Cot::$out['head'] = ''; // Инициализируем переменную 'head' как пустую строку.
    }
    Cot::$out['head'] .= Cot::$R['code_noindex']; // Добавляем мета-тег noindex в голову страницы, чтобы поисковые системы не индексировали эту страницу.
}

/* === Hook === */
foreach (cot_getextplugins('users.main') as $pl) { // Подключаем внешние плагины для раздела "users.main".
	include $pl; // Включаем каждый плагин.
}
/* ===== */

require_once Cot::$cfg['system_dir'] . '/header.php'; // Подключаем заголовок страницы из системы.

$t = new XTemplate($localskin); // Инициализируем объект XTemplate для рендеринга шаблона, используя локальный файл шаблона для пользователей.

require_once cot_incfile('forms'); // Подключаем файл с формами, чтобы обработать отправку данных форм на странице.

Этот код отвечает за построение канонического URL для текущей страницы пользователей, добавление мета-тега noindex, если применены фильтры или сортировка, и подключение необходимых файлов и плагинов для обработки страницы. Также создается объект шаблона для рендеринга и подключается файл для работы с формами.

 

$filtersCountryTitles = [
    Cot::$R['users_sel_def_l'] . Cot::$L['Country'] . Cot::$R['users_sel_def_r'], // Добавляем в массив титулы для фильтра страны: текст "Country" с декоративными элементами.
    Cot::$L['Not_indicated'], // Добавляем текст "Not indicated" (Не указано) для значения по умолчанию.
];
$filtersCountryValues = ['', '00']; // Значения фильтра: пустое значение и значение "00" для стран без указания.

foreach ($cot_countries as $id => $countryRow) { // Проходим по всем странам, сохраненным в массиве $cot_countries.
    $filtersCountryTitles[] = cot_cutstring($countryRow, 23); // Добавляем строку страны, обрезанную до 23 символов.
    $filtersCountryValues[] = $id; // Добавляем идентификатор страны в массив значений.
}

$filtersFormCountry = cot_selectbox(
    $country, // Текущее значение фильтра, выбранное пользователем.
    'country', // Имя поля в форме (используется в атрибуте name).
    $filtersCountryValues, // Массив значений для фильтра.
    $filtersCountryTitles, // Массив титулов для фильтра.
    false, // Не использовать опцию "По умолчанию" в селекте.
    ['class' => 'filter-submit'] // CSS-класс для стилизации.
); 

Этот код генерирует выпадающий список для фильтрации пользователей по стране. Массивы $filtersCountryTitles и $filtersCountryValues содержат наименования и значения для стран, включая дефолтные значения. В цикле добавляются страны из массива $cot_countries, после чего формируется HTML-элемент <select> с помощью функции cot_selectbox.

 

$filtersGroupTitles = [Cot::$R['users_sel_def_l'] . Cot::$L['Maingroup'] . Cot::$R['users_sel_def_r']]; // Добавляем заголовок для основного фильтра группы (Main Group) с декоративными элементами.
$filtersGroupValues = ['']; // Инициализируем массив значений фильтра с пустым значением.

foreach ($cot_groups as $filterGroupRow) { // Перебираем все группы из массива $cot_groups.
    if (
        (($filterGroupRow['hidden'] || $filterGroupRow['disabled']) && !Cot::$usr['isadmin']) // Если группа скрыта или отключена и текущий пользователь не администратор,
        || $filterGroupRow['id'] == COT_GROUP_GUESTS // или группа — это группа гостей,
    ) {
        continue; // Пропускаем эту группу.
    }

    $filtersGroupTitles[] = $filterGroupRow['name']; // Добавляем название группы в массив заголовков.
    $filtersGroupValues[] = $filterGroupRow['id']; // Добавляем идентификатор группы в массив значений.
}

$filtersFormMainGroup = cot_selectbox(
    $gm, // Текущее выбранное значение для фильтра основной группы.
    'gm', // Имя поля в форме для фильтра основной группы.
    $filtersGroupValues, // Массив значений для фильтра группы.
    $filtersGroupTitles, // Массив титулов для фильтра группы.
    false, // Не использовать опцию "По умолчанию".
    ['class' => 'filter-submit'] // CSS-класс для стилизации.
);

$filtersGroupTitles[0] = Cot::$R['users_sel_def_l'] . Cot::$L['Group'] . Cot::$R['users_sel_def_r']; // Изменяем первый заголовок на "Group" (Группа).
$filtersFormGroup = cot_selectbox(
    $g, // Текущее выбранное значение для фильтра группы.
    'g', // Имя поля в форме для фильтра группы.
    $filtersGroupValues, // Массив значений для фильтра группы.
    $filtersGroupTitles, // Массив титулов для фильтра группы.
    false, // Не использовать опцию "По умолчанию".
    ['class' => 'filter-submit'] // CSS-класс для стилизации.
); 

Этот код генерирует два выпадающих списка для фильтрации пользователей по группам: один для фильтрации по основной группе (gm), и второй для фильтрации по любой другой группе (g). Массивы $filtersGroupTitles и $filtersGroupValues заполняются данными из массива $cot_groups, исключая скрытые или отключенные группы, а также группу гостей. Функция cot_selectbox используется для создания HTML-форм для этих фильтров.

 

$filtersFormAction = cot_url('users', '', '', true); // Формируем URL для действия формы, указывая, что форма будет отправлена на страницу пользователей.
$parts = explode('?', $filtersFormAction); // Разбиваем URL на две части по символу "?" (если он присутствует) — базовый URL и параметры.
$filtersFormAction = $parts[0]; // Базовый URL для формы, без параметров.
$actionVars = []; // Инициализируем массив для хранения параметров действия, если они будут.
if (isset($parts[1])) { // Если в URL есть параметры (часть после "?"),
    parse_str($parts[1], $actionVars); // Разбираем строку параметров и сохраняем в массив $actionVars.
}
$filtersFormParams = ''; // Инициализируем переменную для хранения скрытых полей формы с параметрами.
foreach ($actionVars as $key => $val) { // Перебираем все параметры действия.
    $filtersFormParams .= cot_inputbox('hidden', $key, $val); // Добавляем скрытые поля для каждого параметра.
}
if (isset($users_url_path['s']) && !$t->hasTag('USERS_FILTERS_SORT')) { // Если есть параметр сортировки (s) и фильтрация по сортировке не активна,
    $filtersFormParams .= cot_inputbox('hidden', 's', $users_url_path['s']); // Добавляем скрытое поле для сортировки.
}
if (isset($users_url_path['w'])) { // Если есть параметр порядка сортировки (w),
    $filtersFormParams .= cot_inputbox('hidden', 'w', $users_url_path['w']); // Добавляем скрытое поле для порядка сортировки.
}

Этот код отвечает за подготовку скрытых полей для формы фильтрации, чтобы передать все нужные параметры при её отправке. Вначале URL разбивается на две части: сам путь и строку параметров. Затем параметры добавляются как скрытые поля в форму, используя функцию cot_inputbox('hidden', ...). Это позволяет сохранить значения фильтров и сортировки между запросами, без их явного отображения на странице.

 

$excludeParams = ['sq', 'gm', 'g', 'country', 's', 'w']; // Определяем массив параметров, которые должны быть исключены из формы.
foreach ($users_url_path as $key => $val) { // Перебираем все параметры из массива $users_url_path.
    if (in_array($key, $excludeParams)) { // Если текущий параметр входит в массив исключений,
        continue; // Пропускаем его и не добавляем в форму.
    }
    $filtersFormParams .= cot_inputbox('hidden', $key, $val); // Для остальных параметров добавляем скрытые поля в форму.
}

/* === Hook === */
foreach (cot_getextplugins('users.filters') as $pl) { // Выполняем дополнительные действия с помощью плагинов, если они есть.
    include $pl; // Подключаем и выполняем плагин.
}
/* ===== */

Этот код добавляет в форму скрытые поля для всех параметров из массива $users_url_path, за исключением тех, которые перечислены в массиве $excludeParams. Например, параметры сортировки или фильтрации, такие как gm, g, country, s, и w, не будут передаваться через форму. После этого, если есть плагины для фильтров (users.filters), они будут подключены и выполнены.

 

$breadCrumbs = [[cot_url('users'), Cot::$L['Users']]]; // Массив хлебных крошек для навигации, начальный элемент с ссылкой на список пользователей и названием.
if (!empty($title)) { // Если есть дополнительные элементы в массиве $title, добавляем их в хлебные крошки.
    $breadCrumbs[] = implode(', ', $title); // Добавляем строку, составленную из элементов массива $title, в хлебные крошки.
}

$t->assign([ // Присваиваем переменные шаблона для вывода на странице.
	'USERS_TITLE' => Cot::$L['use_title'] . $titleAddon, // Заголовок страницы, который включает в себя основной текст и дополнение из $titleAddon.
	'USERS_SUBTITLE' => Cot::$L['use_subtitle'], // Подзаголовок страницы.
    'USERS_BREADCRUMBS' => cot_breadcrumbs($breadCrumbs, Cot::$cfg['homebreadcrumb']), // Генерация и присваивание хлебных крошек.
    'USERS_FILTERS_ACTION' => $filtersFormAction, // Действие формы фильтрации (URL, на который будет отправлен запрос).
    'USERS_FILTERS_PARAMS' => $filtersFormParams, // Параметры формы фильтрации (скрытые поля).
    'USERS_FILTERS_COUNTRY' => $filtersFormCountry, // Поле выбора страны для фильтрации.
    'USERS_FILTERS_MAIN_GROUP' => $filtersFormMainGroup, // Поле выбора основной группы для фильтрации.
    'USERS_FILTERS_GROUP' => $filtersFormGroup, // Поле выбора группы для фильтрации.
    'USERS_FILTERS_SEARCH' => cot_inputbox('text', 'sq', $sq, ['maxlength' => 16]), // Поле поиска с ограничением на 16 символов.
    'USERS_FILTERS_SUBMIT' => cot_inputbox('submit', 'submit', Cot::$L['Search']), // Кнопка отправки формы.
]);

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

 

if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) { // Если включен режим совместимости (legacy mode).
    // @deprecated in 0.9.24
    $t->assign([ // Присваиваем значения для шаблона.
        //'USERS_CURRENTFILTER' => $f, // Закомментированное присваивание фильтра (устаревшее).
        'USERS_TOP_CURRENTPAGE' => $pagenav['current'], // Текущая страница в навигации.
        'USERS_TOP_TOTALPAGE' => $pagenav['total'], // Общее количество страниц.
        'USERS_TOP_MAXPERPAGE' => Cot::$cfg['users']['maxusersperpage'], // Максимальное количество пользователей на странице.
        'USERS_TOP_TOTALUSERS' => $totalusers, // Общее количество пользователей.
        'USERS_TOP_PAGNAV' => $pagenav['main'], // Основная навигация по страницам.
        'USERS_TOP_PAGEPREV' => $pagenav['prev'], // Навигация на предыдущую страницу.
        'USERS_TOP_PAGENEXT' => $pagenav['next'], // Навигация на следующую страницу.
        'USERS_TOP_FILTER_ACTION' => $filtersFormAction, // Действие формы фильтрации.
        'USERS_TOP_FILTERS_COUNTRY' => $filtersFormCountry, // Поле выбора страны для фильтрации.
        'USERS_TOP_FILTERS_MAINGROUP' => $filtersFormMainGroup, // Поле выбора основной группы для фильтрации.
        'USERS_TOP_FILTERS_GROUP' => $filtersFormGroup, // Поле выбора группы для фильтрации.
        'USERS_TOP_FILTERS_SEARCH' => cot_inputbox('text', 'sq', $sq, ['size' => 16, 'maxlength' => 16]), // Поле для поиска с ограничениями.
        'USERS_TOP_FILTERS_SUBMIT' => cot_inputbox('submit', 'submit', Cot::$L['Search']), // Кнопка отправки формы фильтрации.
        //'USERS_TOP_PM' => 'PM', // Закомментированное присваивание для личных сообщений.
    ]);
}

В этом коде, если активирован режим совместимости, выполняется присваивание данных в шаблон для отображения информации о текущей и общей страницах, фильтры для поиска и навигации, а также другие параметры страницы пользователей. Закомментированные строки ('USERS_CURRENTFILTER' и 'USERS_TOP_PM') были ранее использованы, но теперь считаются устаревшими или неактуальными.

 


$t->assign(cot_generatePaginationTags($pagenav));

Функция cot_generatePaginationTags() в данном случае, судя по всему, генерирует теги для пагинации (перелистывания страниц) и передает их в шаблон через метод $t->assign(). Это позволяет использовать переменные пагинации внутри шаблона для отображения элементов управления страницами (например, номера страниц, кнопки перехода к следующей или предыдущей странице).

 

 

$k = '_.__._'; // Присваивается разделитель для разбиения URL. Этот разделитель используется позже для создания ссылок с параметрами сортировки.
$asc = explode($k, cot_url('users', array_merge($users_url_path, ['s' => $k, 'w' => 'asc']))); // Формируется URL для сортировки по возрастанию, добавляя параметр 's' и 'w' в массив $users_url_path. Результат разделяется на части с использованием разделителя $k.
$desc = explode($k, cot_url('users', array_merge($users_url_path, ['s' => $k, 'w' => 'desc']))); // Формируется URL для сортировки по убыванию, добавляя параметр 's' и 'w' в массив $users_url_path. Результат разделяется на части с использованием разделителя $k.
foreach ($users_sort_tags as $k => $x) { // Цикл перебора всех элементов массива $users_sort_tags, где $k — ключ, а $x — массив значений для сортировки.
    if (!in_array($k, $usersSortFieldsBlacklist)) { // Если текущий ключ $k не содержится в списке исключений $usersSortFieldsBlacklist, выполняется следующая логика.
        if ($k === $defaultSortField) { // Если текущий ключ $k соответствует полю сортировки по умолчанию.
            $usersSortFields[''] = $x[1]; // Присваиваем значению сортировки по умолчанию значение из массива $x[1] (текст или название).
        } else { // Если текущий ключ не является полем сортировки по умолчанию.
            $usersSortFields[$k] = $x[1]; // Присваиваем значение для текущего поля сортировки в массив $usersSortFields.
        }
    }
	$t->assign( // Присваивание значений шаблону через объект XTemplate.
		$x[0], // Первый элемент массива $x (представляет тег для шаблона).
		!in_array($k, $usersSortFieldsBlacklist) // Если текущий ключ не в черном списке сортировок.
            ? cot_rc('users_link_sort', [ // Формируем ссылку для сортировки с помощью функции cot_rc.
				'asc_url' => implode($k, $asc), // Ссылка для сортировки по возрастанию.
				'desc_url' => implode($k, $desc), // Ссылка для сортировки по убыванию.
				'text' => $x[1], // Текст, который будет отображаться (например, название поля для сортировки).
				'icon_down' => $k == $s && $w == 'asc' ? Cot::$R['icon_vert_active']['asc'] : Cot::$R['icon_down'], // Иконка для сортировки по убыванию, если это текущее состояние сортировки.
				'icon_up' => $k == $s && $w == 'desc' ? Cot::$R['icon_vert_active']['desc'] : Cot::$R['icon_up'] // Иконка для сортировки по возрастанию, если это текущее состояние сортировки.
			])
		    : $x[1] // Если текущий ключ находится в черном списке сортировок, просто отображаем текст без ссылки.
	);
}

 

 

// Extra fields for users
foreach (Cot::$extrafields[Cot::$db->users] as $extraField) { // Перебор всех дополнительных полей пользователей, извлекаемых из массива Cot::$extrafields для таблицы пользователей.
	$uname = strtoupper($extraField['field_name']); // Преобразует название поля в верхний регистр для использования в теге шаблона.
	$fieldTitle = isset(Cot::$L['user_' . $extraField['field_name'] . '_title']) // Проверка, существует ли локализованное название для поля.
        ? Cot::$L['user_' . $extraField['field_name'] . '_title'] // Если существует, берем локализованное название.
        : $extraField['field_description']; // Если локализованного названия нет, используем описание поля как название.

    if (!in_array($extraField['field_name'], $usersSortFieldsBlacklist)) { // Если текущее дополнительное поле не находится в черном списке сортировок.
        if ($k === $defaultSortField) { // Если поле является полем сортировки по умолчанию.
            $usersSortFields[$extraField['field_name']] = $fieldTitle; // Добавляем это поле с его заголовком в массив для сортировки.
        } else { // Если поле не является полем сортировки по умолчанию.
            $usersSortFields[$extraField['field_name']] = $fieldTitle; // Добавляем это поле с его заголовком в массив для сортировки.
        }
    }

	$t->assign( // Присваивание значений шаблону через объект XTemplate.
		'USERS_TOP_' . $uname, // Создание уникального тега для каждого дополнительного поля с использованием его имени.
		!in_array($extraField['field_name'], $usersSortFieldsBlacklist) // Если поле не в черном списке сортировок.
            ? cot_rc('users_link_sort', [ // Формируем ссылку для сортировки для этого поля с помощью функции cot_rc.
				'asc_url' => cot_url( // URL для сортировки по возрастанию.
                    'users',
                    array_merge($users_url_path, ['s' => $extraField['field_name'], 'w'=> 'asc']) // Добавление параметров сортировки в URL.
                ),
				'desc_url' => cot_url( // URL для сортировки по убыванию.
                    'users',
                    array_merge($users_url_path, ['s' => $extraField['field_name'], 'w'=> 'desc']) // Добавление параметров сортировки в URL.
                ),
				'text' => $fieldTitle, // Текст ссылки — это заголовок поля.
				'icon_down' => $s === $extraField['field_name'] && $w === 'asc' // Если текущее поле сортируется по возрастанию.
                    ? Cot::$R['icon_vert_active']['asc'] // Иконка для сортировки по возрастанию.
                    : Cot::$R['icon_down'], // Иконка по умолчанию.
				'icon_up' => $s === $extraField['field_name'] && $w === 'desc' // Если текущее поле сортируется по убыванию.
                    ? Cot::$R['icon_vert_active']['desc'] // Иконка для сортировки по убыванию.
                    : Cot::$R['icon_up'] // Иконка по умолчанию.
			])
		    : $fieldTitle // Если поле находится в черном списке сортировок, отображаем только заголовок без ссылок для сортировки.
	);
}

 

if (!isset($usersSortFields[''])) { // Если в массиве сортировки пользователей еще нет поля по умолчанию (пустой ключ).
    $usersSortFields[''] = isset(Cot::$L['user_' . $defaultSortField . '_title']) // Присваиваем полю по умолчанию локализованное название, если оно существует.
        ? Cot::$L['user_' . $defaultSortField . '_title'] // Если локализованное название существует.
        : $defaultSortField; // Если нет, используем имя поля сортировки по умолчанию.
}

$sortWayParams = $users_url_path; // Копируем текущие параметры URL для сортировки пользователей.
if ($w === 'desc') { // Если текущий порядок сортировки — по убыванию.
    unset($sortWayParams['w']); // Удаляем параметр сортировки (убираем текущую сортировку).
    $sortWayIcon = Cot::$R['icon_order_desc']; // Иконка для сортировки по убыванию.
} else { // Если текущий порядок сортировки — по возрастанию.
    $sortWayParams['w'] = 'desc'; // Меняем порядок сортировки на убывание.
    $sortWayIcon = Cot::$R['icon_order_asc']; // Иконка для сортировки по возрастанию.
}
$sortWayUrl = cot_url('users', $sortWayParams); // Генерируем URL с новыми параметрами сортировки.

$t->assign([ // Присваиваем значения в шаблон через объект XTemplate.
    'USERS_FILTERS_SORT' => cot_selectbox( // Создаем выпадающий список для выбора поля сортировки.
        $s !== $defaultSortField ? $s : '', // Если текущее поле сортировки не по умолчанию, используем его, иначе — пустое значение.
        's', // Название поля для сортировки.
        array_keys($usersSortFields), // Массив с ключами для полей сортировки.
        array_values($usersSortFields), // Массив с заголовками полей сортировки.
        false, // Не использовать обязательный выбор.
        ['class' => 'filter-submit'] // Добавляем CSS класс.
    ),
    'USERS_FILTERS_SORT_WAY_URL' => $sortWayUrl, // Передаем URL для изменения порядка сортировки.
    'USERS_FILTERS_SORT_WAY' => cot_rc_link($sortWayUrl,  $sortWayIcon, ['rel' => 'nofollow']), // Формируем ссылку для изменения порядка сортировки с иконкой.
]);

 

// @todo move to common JS file. To other extensions can use it // TODO: Перенести этот код в общий JS файл, чтобы другие расширения могли его использовать.
Resources::embedFooter( // Встраиваем JavaScript код в подвал страницы.
    <<<JS
const filterForm = document.getElementById('filter-form'); // Получаем форму с фильтром по ID 'filter-form'.
if (filterForm) { // Если форма существует.
    const filterElements = filterForm.querySelectorAll('input:not([type="hidden"]), select'); // Получаем все элементы формы, исключая скрытые поля.

    function processFilterForm() { // Функция для обработки формы фильтрации.
        for (let elem of filterElements) { // Проходим по каждому элементу формы.
            if (elem.value === '') { // Если значение элемента пустое.
                elem.disabled = true; // Отключаем элемент.
            }
        }
    }
    
    for (let elem of filterElements) { // Проходим по каждому элементу формы.
        if (elem.classList.contains('filter-submit')) { // Если элемент имеет класс 'filter-submit'.
            elem.addEventListener('change', function (e) { // Добавляем обработчик события изменения для этого элемента.
                processFilterForm(); // Обрабатываем форму.
                filterForm.submit(); // Отправляем форму.
            });
        }
    }
    
    filterForm.addEventListener('submit', function (e) { // Добавляем обработчик события отправки формы.
        processFilterForm(); // Обрабатываем форму перед отправкой.
    });
}
JS
); // Закрываем вызов метода для встраивания кода в подвал.

 

$jj = 0; // Инициализация переменной $jj для отслеживания номера строки.

 /* === Hook - Part1 : Set === */
$extp = cot_getextplugins('users.loop'); // Получаем плагины, связанные с циклом пользователей.
 /* ===== */

foreach ($users as $urr) { // Проходим по каждому пользователю в массиве $users.
	$jj++; // Увеличиваем номер строки.
	$t->assign([ // Присваиваем значения для шаблона.
		'USERS_ROW_ODDEVEN' => cot_build_oddeven($jj), // Создаем четно/нечетный стиль для строки.
        'USERS_ROW_NUM' => $jj, // Номер текущей строки.
		'USERS_ROW' => $urr // Присваиваем данные пользователя.
	]);
	$t->assign(cot_generate_usertags($urr, 'USERS_ROW_')); // Генерируем теги пользователя для шаблона.

	/* === Hook - Part2 : Include === */
	foreach ($extp as $pl) { // Для каждого плагина в $extp.
		include $pl; // Включаем плагин.
	}
	/* ===== */

	$t->parse('MAIN.USERS_ROW'); // Парсим строку пользователя в основной шаблон.
}

/* === Hook === */
foreach (cot_getextplugins('users.tags') as $pl) { // Для каждого плагина, связанного с тегами пользователей.
	include $pl; // Включаем плагин.
}
/* ===== */

$t->parse('MAIN'); // Парсим основной шаблон.
$t->out('MAIN'); // Выводим результат.

require_once Cot::$cfg['system_dir'] . '/footer.php'; // Подключаем файл подвала сайта.

 

 

 

36 minutes read Sodium Carbonate

Comments (0)

No comments yet
Only registered users can post new comments

Content author

webitproff

Offline

Sodium Carbonate

Last logged: 2026-07-21 00:03

  • Page published: 2025-01-31 02:40
  • Last update: 2025-01-31 03:28

Similar pages

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