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

предназначен для обработки запросов на редактирование профиля пользователя, а также для отображения формы редактирования с возможностью изменения различных данных пользователя

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

Основное назначение:

Основная цель файла — обработка и вывод формы редактирования профиля пользователя. Он выполняет следующие задачи:

  1. Загружает и обрабатывает данные о пользователе.
  2. Отображает данные пользователя в форме редактирования.
  3. Обрабатывает изменения, внесенные пользователем.
  4. Обрабатывает и выводит сообщения об ошибках и успешных действиях.
  5. Взаимодействует с базой данных для получения и обновления информации о пользователе.

Взаимодействие с сайтом:

Файл работает с несколькими компонентами Cotonti CMF:

  • Модуль "users" — взаимодействует с основным функционалом управления пользователями.
  • Шаблоны — файл генерирует данные, которые затем передаются в шаблон для отображения пользователю.
  • База данных — извлекает информацию о пользователе, а также записывает изменения в профиль.
  • Плагины — возможность использования расширений через хуки для добавления дополнительных функций (например, поля).

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

  1. Cot::$cfg — глобальная конфигурация сайта.
  2. Cot::$out — глобальный объект для вывода данных на страницу, например, для задания заголовков.
  3. Cot::$R — массив с ресурсами, такими как стили и скрипты.
  4. $urr — переменная, содержащая информацию о пользователе, полученную из базы данных.
  5. $usersHelper — объект для работы с пользовательскими данными (например, для формирования полного имени пользователя).
  6. cot_url() — функция для создания URL с учетом маршрутов.
  7. cot_inputbox() — создание поля ввода в форме.
  8. cot_selectbox_*() — функции для генерации выпадающих списков (например, для выбора языка, страны, темы).
  9. cot_radiobox() — функция для создания радиокнопок (например, для выбора, скрывать ли email).
  10. cot_textarea() — создание поля для ввода многострочного текста.
  11. cot_build_group() — создание информации о группе пользователя.
  12. cot_display_messages() — функция для отображения сообщений (например, об ошибках).
  13. cot_getextplugins() — загрузка плагинов, если они подключены.
  14. XTemplate — класс для работы с шаблонами в Cotonti.
  15. UsersHelper::getInstance() — создание или получение экземпляра класса для работы с пользователями.

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

  1. Обработка запроса: Файл начинается с получения данных о пользователе из базы данных на основе его ID.
  2. Подготовка данных для отображения: Данные о пользователе подготавливаются в массивы и передаются в шаблон.
  3. Генерация HTML-формы: Для каждого поля редактируемого профиля создается HTML-форма.
  4. Обработка изменений: После изменения данных, форма отправляется на сервер, и соответствующие данные обновляются в базе.
  5. Отображение сообщений: В случае успеха или ошибки выводятся соответствующие сообщения.

Как использовать владельцу сайта:

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

Стиль написания и совместимость с PHP:

Код написан с соблюдением основных принципов ООП (например, использование объектов и методов), а также поддерживает работу с массивами и стандартными функциями PHP. Он совместим с современными версиями PHP (PHP 7 и выше), поскольку использует такие конструкции, как массивы, объекты и функции, которые поддерживаются начиная с PHP 5.4.

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

 

/**
 * Edit User Profile
 *
 * @package Users
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

use cot\users\UsersHelper;  // Подключение класса UsersHelper для работы с данными пользователей

defined('COT_CODE') or die('Wrong URL');  // Проверка, что файл вызывается внутри движка Cotonti, если нет — прекращение выполнения скрипта

require_once cot_incfile('auth');  // Подключение файла с функционалом авторизации пользователей

$y = cot_import('y','P','TXT');  // Получение параметра 'y' из POST-запроса, тип данных — текст (TXT)

$id = (int) cot_import('id','G','INT');  // Получение параметра 'id' из GET-запроса, тип данных — целое число (INT), присваиваем переменной $id

$s = cot_import('s','G','ALP',13);  // Получение параметра 's' из GET-запроса, тип данных — строка из алфавитных символов (ALP), длина до 13 символов

$w = cot_import('w','G','ALP',4);  // Получение параметра 'w' из GET-запроса, тип данных — строка из алфавитных символов (ALP), длина до 4 символов

$d = cot_import('d','G','INT');  // Получение параметра 'd' из GET-запроса, тип данных — целое число (INT)

$f = cot_import('f','G','TXT');  // Получение параметра 'f' из GET-запроса, тип данных — текст (TXT)

$g = cot_import('g','G','INT');  // Получение параметра 'g' из GET-запроса, тип данных — целое число (INT)

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

cot_block(Cot::$usr['isadmin']);  // Проверка прав администратора (если не администратор, выполнение кода будет остановлено)

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

 

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

cot_die(empty($id), true);  // Прекращение выполнения, если параметр 'id' пуст, вывод ошибки

$sql = Cot::$db->query("SELECT * FROM $db_users WHERE user_id = ?", $id);  // Выполнение SQL-запроса для получения данных пользователя по его ID

cot_die($sql->rowCount()==0, true);  // Прекращение выполнения, если пользователь с таким ID не найден, вывод ошибки

$urr = $sql->fetch();  // Извлечение данных пользователя из результата запроса и присваивание их переменной $urr

$sql1 = Cot::$db->query("SELECT gru_groupid FROM $db_groups_users WHERE gru_userid=$id and gru_groupid=".COT_GROUP_SUPERADMINS);  // Выполнение SQL-запроса для проверки, состоит ли пользователь в группе супер-администраторов

$sys['edited_istopadmin'] = ($sql1->rowCount()>0) ? TRUE : FALSE;  // Проверка, если пользователь является супер-администратором, и присваивание результата в переменную $sys['edited_istopadmin']

$sys['user_istopadmin'] = cot_auth('admin', 'a', 'A');  // Проверка, имеет ли текущий пользователь права супер-администратора

$sys['protecttopadmin'] = $sys['edited_istopadmin'] && !$sys['user_istopadmin'];  // Если редактируемый пользователь является супер-администратором, а текущий пользователь — нет, включаем защиту

 

if ($sys['protecttopadmin']) {  // Если защита от редактирования супер-администратора включена
    cot_die_message(930, TRUE);  // Завершаем выполнение с сообщением об ошибке (код 930), пользователь не может редактировать супер-администратора
}

 

if ($a == 'update') {  // Если действие 'update', то продолжаем обработку
    cot_check_xg();  // Проверка на корректность CSRF-токена для безопасности

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

 

$ruserdelete = cot_import('ruserdelete','P','BOL');  // Получаем параметр 'ruserdelete' из POST-запроса, тип данных - булев (проверка на удаление пользователя)
if ($ruserdelete) {  // Если был выбран параметр для удаления пользователя

    Cot::$db->delete($db_users, "user_id=$id");  // Удаляем пользователя из основной таблицы пользователей
    Cot::$db->delete($db_groups_users, "gru_userid=$id");  // Удаляем записи о пользователе из таблицы групп пользователей

    foreach($cot_extrafields[$db_users] as $exfld) {  // Пробегаем все дополнительные поля пользователей
        cot_extrafield_unlinkfiles($urr['user_'.$exfld['field_name']], $exfld);  // Удаляем файлы, связанные с пользовательскими дополнительными полями
    }

    if (cot_module_active('pfs') && cot_import('ruserdelpfs','P','BOL')) {  // Если активирован модуль pfs и был запрашиваем параметр для удаления файлов из pfs
        require_once cot_incfile('pfs', 'module');  // Подключаем файл модуля pfs
        cot_pfs_deleteall($id);  // Удаляем все файлы, связанные с пользователем из pfs
    }

    /* === Hook === */
    foreach (cot_getextplugins('users.edit.update.delete') as $pl) {  // Обрабатываем хук для плагинов, связанных с удалением пользователя
        include $pl;  // Подключаем и выполняем каждый плагин
    }
    /* ===== */

    cot_log("Deleted user #".$id, 'users', 'delete', 'done');  // Логируем событие удаления пользователя
    cot_redirect(cot_url('message', "msg=109&rc=200&id=".$id, '', true));  // Перенаправляем на страницу с сообщением об успешном удалении
}

Пояснение: Этот фрагмент кода реализует удаление пользователя. Если флаг $ruserdelete установлен (например, через форму), то происходит:

  1. Удаление записи о пользователе из базы данных.
  2. Удаление информации о его группах.
  3. Удаление файлов, связанных с пользовательскими дополнительными полями.
  4. При наличии модуля pfs (Personal File Storage) и установленном флаге для удаления файлов, происходит удаление всех файлов пользователя из pfs.
  5. Если есть подключённые плагины для хука 'users.edit.update.delete', они обрабатываются.
  6. Логируется факт удаления пользователя, и происходит редирект на страницу с сообщением об успешном удалении.

 

$ruser['user_name'] = cot_import('rusername','P','TXT');  // Получаем имя пользователя из POST-запроса, тип данных - строка (TEXT)
$ruser['user_maingrp'] = cot_import('rusermaingrp','P','INT');  // Получаем основной идентификатор группы пользователя из POST-запроса, тип данных - целое число (INT)
$ruser['user_banexpire'] = cot_import('ruserbanexpire','P','INT');  // Получаем дату истечения бана пользователя из POST-запроса, тип данных - целое число (INT)
$ruser['user_country'] = cot_import('rusercountry','P','ALP');  // Получаем страну пользователя из POST-запроса, тип данных - строка с буквами (ALP)
$ruser['user_text'] = cot_import('rusertext','P','HTM');  // Получаем текстовое описание пользователя из POST-запроса, тип данных - HTML
$rtheme = cot_import('rusertheme','P','TXT');  // Получаем строку с темой пользователя из POST-запроса, тип данных - строка (TXT)
$rtheme = !empty($rtheme) ? explode(':', $rtheme) : [];  // Разделяем строку темы по двоеточию, если строка не пуста
$ruser['user_theme'] = $rtheme[0];  // Сохраняем первую часть разделённой строки как тему пользователя
$ruser['user_scheme'] = $rtheme[1];  // Сохраняем вторую часть разделённой строки как схему оформления пользователя
$ruser['user_email'] = cot_import('ruseremail','P','TXT');  // Получаем email пользователя из POST-запроса, тип данных - строка (TXT)
$ruser['user_hideemail'] = cot_import('ruserhideemail','P','INT');  // Получаем флаг скрытия email пользователя из POST-запроса, тип данных - целое число (INT)
$ruser['user_lang'] = cot_import('ruserlang','P','ALP');  // Получаем язык пользователя из POST-запроса, тип данных - строка с буквами (ALP)
$ruser['user_gender'] = cot_import('rusergender','P','TXT');  // Получаем пол пользователя из POST-запроса, тип данных - строка (TXT)

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

  1. Имя пользователя, группа, email, пол, страна и другие данные импортируются через функцию cot_import(), которая очищает и проверяет тип данных (например, строки, числа, HTML).
  2. В строке с темой (ruser.theme) выполняется разбиение на две части (например, тему и схему оформления), которые затем сохраняются в массиве $ruser.
  3. Полученные данные сохраняются в ассоциативном массиве $ruser, который будет использоваться далее в коде для обновления информации о пользователе.

 


$ruser['user_birthdate'] = cot_import_date('ruserbirthdate', false);  // Получаем дату рождения пользователя из POST-запроса с помощью функции cot_import_date(). Если дата не указана, будет возвращено значение null.
if (!is_null($ruser['user_birthdate']) && $ruser['user_birthdate'] > Cot::$sys['now']) {  // Проверяем, что дата рождения не пустая и не больше текущей даты
    cot_error('pro_invalidbirthdate', 'ruserbirthdate');  // Если дата рождения некорректная (больше текущей даты), генерируем ошибку с кодом 'pro_invalidbirthdate'.
}

$ruser['user_timezone'] = cot_import('rusertimezone','P','TXT');  // Получаем временную зону пользователя из POST-запроса, тип данных - строка (TXT)
$rusernewpass = (string) cot_import('rusernewpass','P','NOC', 32);  // Получаем новый пароль пользователя из POST-запроса, тип данных - строка (NOC), ограничиваем длину до 32 символов

Пояснение:

  1. В первом блоке проверяется дата рождения пользователя. Если она указана, но больше текущей даты, генерируется ошибка, сообщающая о некорректности введенной даты.
  2. Во втором блоке из POST-запроса получаем временную зону и новый пароль пользователя. Данные сохраняются в массиве $ruser для последующего использования.
    • Для пароля используется фильтр NOC с ограничением длины в 32 символа, что предотвращает атаки через слишком длинные строки.
    • Также временная зона сохраняется в строковом формате.

 

// Extra fields
if (!empty(Cot::$extrafields[Cot::$db->users])) {  // Проверяем, существуют ли дополнительные поля для пользователей
    foreach (Cot::$extrafields[Cot::$db->users] as $exfld) {  // Проходим по всем дополнительным полям для пользователей
        $ruser['user_' . $exfld['field_name']] = cot_import_extrafields('ruser' . $exfld['field_name'], $exfld, 'P',  // Импортируем значения дополнительных полей пользователя из POST-запроса
            $urr['user_' . $exfld['field_name']], 'user_');  // Используем текущие значения из базы данных в качестве значений по умолчанию для дополнительных полей
    }
}

Пояснение:

  1. Проверяется наличие дополнительных полей (extrafields) для пользователей в глобальном массиве Cot::$extrafields для текущей таблицы пользователей (Cot::$db->users).
  2. Если такие поля существуют, они обрабатываются через цикл foreach. Для каждого поля выполняется импорт данных из POST-запроса с использованием функции cot_import_extrafields().
  3. При этом для каждого дополнительного поля используется его текущее значение в базе данных как значение по умолчанию, если оно не было передано в запросе. Это позволяет корректно обновлять поля пользователя без потери данных.

 

$rusergroupsms = cot_import('rusergroupsms', 'P', 'ARR');  // Импортируем список групп сообщений для пользователя из POST-запроса (массив)

// Проверка имени пользователя
if (mb_strlen($ruser['user_name']) < 2 || mb_strpos($ruser['user_name'], ',') !== false || mb_strpos($ruser['user_name'], "'") !== false) {  // Проверяем, что имя пользователя не слишком короткое (менее 2 символов) и не содержит недопустимые символы (запятая или апостроф)
    cot_error('aut_usernametooshort', 'rusername');  // Если имя пользователя не соответствует условиям, генерируем ошибку
}

// Проверка уникальности имени пользователя
if ($ruser['user_name'] != $urr['user_name'] && Cot::$db->query("SELECT COUNT(*) FROM ".Cot::$db->users." WHERE user_name = ?",  // Если имя пользователя изменяется, проверяем, не существует ли уже такое имя в базе данных
            array($ruser['user_name']))->fetchColumn() > 0) {  // Запрос на проверку наличия такого имени в базе
    cot_error('aut_usernamealreadyindb', 'rusername');  // Если имя уже существует в базе, генерируем ошибку
}

Пояснение:

  1. Первая строка импортирует массив rusergroupsms, который содержит группы сообщений для пользователя из POST-запроса.
  2. Далее идет проверка:
    • Имя пользователя должно быть не менее двух символов и не содержать запятых или апострофов. Если одно из этих условий нарушено, вызывается ошибка с сообщением "Имя пользователя слишком короткое" или с указанием на недопустимые символы.
    • Затем проверяется, изменяется ли имя пользователя и если да, то делается запрос к базе данных для проверки уникальности нового имени пользователя. Если в базе уже есть такое имя, вызывается ошибка "Имя пользователя уже существует".

 

if (!cot_check_email($ruser['user_email']))  // Проверяем, что введенный email имеет правильный формат
{
    cot_error('aut_emailtooshort', 'ruseremail');  // Если email некорректен, генерируем ошибку с сообщением о неправильном формате email
}

if ($ruser['user_email'] != $urr['user_email'] && Cot::$db->query("SELECT COUNT(*) FROM ".Cot::$db->users." WHERE user_email = ?",  // Если email был изменен, проверяем, не существует ли уже такой email в базе данных
            array($ruser['user_email']))->fetchColumn() > 0)  // Запрос на проверку существования такого email в базе
{
    cot_error('aut_emailalreadyindb', 'ruseremail');  // Если email уже существует в базе, генерируем ошибку с сообщением "Email уже зарегистрирован"
}

if (!empty($rusernewpass) && mb_strlen($rusernewpass) < 4)  // Проверяем, что новый пароль введен и его длина не менее 4 символов
{
    cot_error('aut_passwordtooshort', 'rusernewpass');  // Если пароль слишком короткий, генерируем ошибку с сообщением "Пароль слишком короткий"
}

Пояснение:

  1. Первая проверка касается email:
    • Функция cot_check_email() проверяет, что введенный email имеет правильный формат. Если email некорректен, вызывается ошибка с сообщением "Email слишком короткий" (что является стандартным сообщением для всех неверных форматов email в системе).
  2. Вторая проверка проверяет уникальность email:
    • Если email был изменен, выполняется запрос к базе данных для проверки, не занят ли этот email уже другим пользователем. Если такой email найден, выводится ошибка с сообщением "Email уже существует в базе".
  3. Третья проверка проверяет новый пароль:
    • Если новый пароль введен, но его длина меньше 4 символов, генерируется ошибка с сообщением "Пароль слишком короткий".

 

if (!cot_error_found())  // Если ошибок не найдено
{
    if (!empty($rusernewpass))  // Если новый пароль был введен
    {
        $ruser['user_passsalt'] = cot_unique(16);  // Генерируем уникальную соль для пароля
        $ruser['user_passfunc'] = empty($cfg['hashfunc']) ? 'sha256' : $cfg['hashfunc'];  // Выбираем хеш-функцию, по умолчанию sha256
        $ruser['user_password'] = cot_hash($rusernewpass, $ruser['user_passsalt'], $ruser['user_passfunc']);  // Хешируем пароль с солью
    }

    $ruser['user_name'] = ($ruser['user_name'] == '') ? $urr['user_name'] : $ruser['user_name'];  // Если имя не изменено, оставляем старое имя

    // Обработка даты рождения
    if (is_null($ruser['user_birthdate']))  // Если дата рождения не задана
    {
        if (isset($_POST['ruserbirthdate']))  // Если дата рождения была удалена в форме
        {
            $ruser['user_birthdate'] = 'NULL';  // Устанавливаем NULL для даты рождения
        } else {
            unset($ruser['user_birthdate']);  // Убираем дату рождения, если она не задана
        }
    } else {
        $ruser['user_birthdate'] = cot_stamp2date($ruser['user_birthdate']);  // Преобразуем метку времени в формат даты
    }

    // Если имя пользователя изменилось, обновляем данные в других модулях
    if ($ruser['user_name'] != $urr['user_name']) {
        $newname = $ruser['user_name'];  // Новое имя пользователя
        $oldname = $urr['user_name'];  // Старое имя пользователя
        // Обновляем имя пользователя в различных модулях, если они активированы
        if (cot_module_active('forums'))
        {
            require_once cot_incfile('forums', 'module');  // Подключаем модуль форумов
            $db->update($db_forum_topics, array('ft_lastpostername' => $newname), 'ft_lastpostername = ?', array($oldname));  // Обновляем имя последнего автора в темах форума
            $db->update($db_forum_topics, array('ft_firstpostername' => $newname), 'ft_firstpostername = ?', array($oldname));  // Обновляем имя первого автора в темах форума
            $db->update($db_forum_posts, array('fp_postername' => $newname), 'fp_postername = ?', array($oldname));  // Обновляем имя автора в сообщениях форума
            $db->update($db_forum_stats, array('fs_lt_postername' => $newname), 'fs_lt_postername = ?', array($oldname));  // Обновляем имя последнего автора в статистике форума
            if (!empty(Cot::$cache)) {
                Cot::$cache->db->remove('cot_sections_act', 'system');  // Очистка кэша секций
            }
        }
        if (cot_module_active('page'))
        {
            require_once cot_incfile('page', 'module');  // Подключаем модуль страниц
            $db->update($db_pages, array('page_author' => $newname), 'page_author = ?', array($oldname));  // Обновляем имя автора страниц
        }
        if (cot_plugin_active('comments'))
        {
            require_once cot_incfile('comments', 'plug');  // Подключаем плагин комментариев
            $db->update($db_com, array('com_author' => $newname), 'com_author = ?', array($oldname));  // Обновляем имя автора комментариев
        }
        if (cot_module_active('pm'))
        {
            require_once cot_incfile('pm', 'module');  // Подключаем модуль личных сообщений
            $db->update($db_pm, array('pm_fromuser' => $newname), 'pm_fromuser = ?', array($oldname));  // Обновляем имя отправителя в личных сообщениях
        }
        if (cot_plugin_active('whosonline'))
        {
            $db->update($db_online, array('online_name' => $newname), 'online_name = ?', array($oldname));  // Обновляем имя пользователя в списке онлайн
        }
    }

    $ruser['user_auth'] = '';  // Очищаем поле аутентификации пользователя

    $sql = $db->update($db_users, $ruser, 'user_id=' . $id);  // Обновляем информацию о пользователе в базе данных
    cot_extrafield_movefiles();  // Перемещаем файлы экстраполя (если они есть)

    // Проверка и установка основной группы пользователя
    $ruser['user_maingrp'] = ($ruser['user_maingrp'] < COT_GROUP_MEMBERS && $id == 1) ? COT_GROUP_SUPERADMINS : $ruser['user_maingrp'];  // Если это суперпользователь, устанавливаем группу суперадминистратора

    if (!$rusergroupsms[$ruser['user_maingrp']])
    {
        $rusergroupsms[$ruser['user_maingrp']] = 1;  // Устанавливаем флаг для основной группы
    }
    $db->update($db_users, array('user_maingrp' => $ruser['user_maingrp']), 'user_id=' . $id);  // Обновляем основную группу пользователя

    // Обновляем группы пользователя в таблице групп
    foreach ($cot_groups as $k => $i)
    {
        if (isset($rusergroupsms[$k]))  // Если группа активирована
        {
            if ($db->query("SELECT gru_userid FROM $db_groups_users WHERE gru_userid=$id AND gru_groupid=$k")->rowCount() == 0
                && !($id == 1 && in_array($k, array(COT_GROUP_BANNED, COT_GROUP_INACTIVE))))  // Проверка на существование записи о пользователе в группе
            {
                $db->insert($db_groups_users, array('gru_userid' => (int)$id, 'gru_groupid' => (int)$k));  // Добавляем пользователя в группу
            }
        }
        else
        {
            $db->delete($db_groups_users, "gru_userid=$id AND gru_groupid=$k");  // Удаляем пользователя из группы
        }
    }

    // Если пользователь активировал свою учетную запись, отправляем уведомление по email
    if ($ruser['user_maingrp'] == COT_GROUP_MEMBERS && $urr['user_maingrp'] == COT_GROUP_INACTIVE) {
        $rsubject = Cot::$L['useed_accountactivated'];  // Тема письма
        $rbody = Cot::$L['Hi'] . " " . $urr['user_name'] . ",\n\n";  // Текст письма
        $rbody .= Cot::$L['useed_email'];
        $rbody .= "\n\n" . Cot::$L['aut_contactadmin'];
        cot_mail($urr['user_email'], $rsubject, $rbody);  // Отправка email
    }

    /* === Hook === */
    foreach (cot_getextplugins('users.edit.update.done') as $pl) {
        include $pl;  // Выполнение хуков, если есть
    }
    /* ===== */

    cot_auth_clear($id);  // Очищаем кэш авторизации для пользователя
    cot_log("Edited user #".$id, 'users', 'edit', 'done');  // Логируем изменение пользователя
    cot_message('User_data_updated');  // Сообщение об успешном обновлении данных пользователя
    cot_redirect(cot_url('users', "m=edit&id=" . $id, '', true));  // Перенаправление на страницу редактирования пользователя
}
else
{
    cot_redirect(cot_url('users', "m=edit&id=$id", '', true));  // Перенаправление, если были ошибки
}

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

  1. Проверка на наличие ошибок: Сначала проверяется, были ли найдены ошибки. Если ошибок нет, продолжаем обновление.

  2. Обработка пароля: Если был введен новый пароль, генерируется соль и выбирается хеш-функция для пароля. Пароль хешируется с использованием этой соли и функции.

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

  4. Обработка даты рождения: Если дата рождения была удалена, она устанавливается как NULL. В противном случае, она преобразуется в формат даты.

  5. Обновление данных пользователя: Все изменения (например, пароль, имя пользователя, дата рождения) сохраняются в базе данных.

  6. Обновление группы пользователя: Основная группа пользователя проверяется и обновляется, если необходимо. Например, если пользователь является суперпользователем, его основная группа устанавливается в группу "суперадминистраторов".

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

  8. Отправка уведомления по электронной почте: Если пользователь был неактивным и теперь активирован, ему отправляется уведомление на электронную почту о том, что его аккаунт был активирован.

  9. Выполнение хуков: В случае наличия плагинов или расширений, которые обрабатывают события редактирования пользователя, они выполняются.

  10. Очистка кэша авторизации: После обновления данных очищается кэш авторизации пользователя.

  11. Логирование: Все изменения логируются для дальнейшего аудита.

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

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

 

$sql = $db->query("SELECT * FROM $db_users WHERE user_id=$id LIMIT 1"); // Выполняется SQL-запрос для получения данных пользователя по ID
$urr = $sql->fetch(); // Получаем результат запроса в виде ассоциативного массива

$title_params = array( // Создается массив параметров для заголовка
    'EDIT' => $L['Edit'], // Заголовок страницы: "Edit"
    'NAME' => $urr['user_name'] // Имя пользователя для отображения в заголовке
);
Cot::$out['subtitle'] = cot_title('{EDIT} - {NAME}', $title_params); // Формируем подзаголовок с использованием шаблона и параметров

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

$mskin = cot_tplfile(['users', 'edit', $urr['user_maingrp']], 'module'); // Выбираем шаблон для редактирования, учитывая основную группу пользователя

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

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

$t = new XTemplate($mskin); // Инициализируем объект шаблона XTemplate с выбранным шаблоном

require_once cot_incfile('forms'); // Подключаем файл с функциями для обработки форм

что происходит в данном участке кода:

  1. Запрос к базе данных: Выполняется SQL-запрос для получения информации о пользователе по его user_id. Результат запроса сохраняется в переменной $urr.

  2. Установка заголовка страницы: В массиве $title_params формируются параметры для заголовка страницы. Заголовок страницы устанавливается с помощью функции cot_title, которая подставляет значения из массива (например, название "Edit" и имя пользователя).

  3. Установка мета-тегов: Проверяется, был ли уже установлен элемент head. Если нет, он инициализируется пустой строкой. Затем добавляется мета-тег noindex, чтобы поисковые системы не индексировали эту страницу.

  4. Выбор шаблона: Выбирается шаблон для страницы редактирования пользователя. Шаблон подбирается в зависимости от основной группы пользователя, что позволяет использовать различные шаблоны для разных групп пользователей (например, для обычных пользователей или администраторов).

  5. Хуки (расширения): Выполняются хуки через плагинную систему Cotonti. Если существуют подключенные плагины, которые реагируют на событие редактирования пользователя, их код будет включен и выполнен.

  6. Загрузка заголовка: Подключается файл заголовка, который находится в директории system_dir. Это может быть стандартный или кастомизированный заголовок страницы.

  7. Инициализация шаблона: Инициализируется объект XTemplate для выбранного шаблона. Это позволяет работать с переменными шаблона и динамически выводить данные на странице.

  8. Подключение формы: Подключается файл с функциями для работы с формами, что позволяет использовать различные утилиты для обработки данных формы на странице редактирования пользователя.

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

 

$protected = $sys['protecttopadmin'] ? array('disabled' => 'disabled') : array(); // Проверка, если защита от изменений для админа активирована, то массив будет содержать атрибут "disabled"

$editor_class = $cfg['users']['usertextimg'] ? 'minieditor' : ''; // Если в настройках включена возможность вставки изображений, то присваиваем классу значение 'minieditor', иначе строка остается пустой

$delete_pfs = cot_module_active('pfs') ? cot_checkbox(false, 'ruserdelpfs', $L['PFS']) : ''; // Если активен модуль pfs, добавляется чекбокс для удаления файлов пользователя, иначе оставляется пусто

$usersHelper = UsersHelper::getInstance(); // Инициализация экземпляра класса UsersHelper для работы с пользователями

$breadCrumbs = [ // Массив для формирования хлебных крошек
    [cot_url('users'), Cot::$L['Users']], // Первая крошка с ссылкой на страницу пользователей
    [
        cot_url('users', ['m' => 'details', 'id' => $urr['user_id'], 'u' => $urr['user_name']]), // Вторая крошка со ссылкой на детальную информацию о пользователе
        $usersHelper->getFullName($urr), // Имя пользователя, полученное с помощью хелпера
    ],
    [cot_url('users', ['m' => 'edit', 'id' => $urr['user_id']]), Cot::$L['Edit']], // Третья крошка со ссылкой на страницу редактирования пользователя
];

 

$t->assign([ // Назначение значений для шаблона через XTemplate
	'USERS_EDIT_TITLE' => htmlspecialchars($usersHelper->getFullName($urr)), // Заголовок редактирования пользователя: полное имя пользователя
    'USERS_EDIT_SUBTITLE' => $L['useed_subtitle'], // Подзаголовок редактирования пользователя
    'USERS_EDIT_BREADCRUMBS' => cot_breadcrumbs($breadCrumbs, Cot::$cfg['homebreadcrumb']), // Хлебные крошки для навигации
    'USERS_EDIT_DETAILS_URL' => cot_url( // URL для перехода к подробной информации о пользователе
        'users',
        ['m' => 'details', 'id' => $urr['user_id'], 'u' => $urr['user_name']]
    ),
	'USERS_EDIT_EDIT_URL' => cot_url('users', ['m' => 'edit', 'id' => $urr['user_id']]), // URL для редактирования пользователя
	'USERS_EDIT_SEND' => cot_url('users', 'm=edit&a=update&'.cot_xg().'&id='.$urr['user_id']), // URL для отправки данных обновления
	'USERS_EDIT_ID' => $urr['user_id'], // Идентификатор пользователя
	'USERS_EDIT_NAME' => cot_inputbox('text', 'rusername', $urr['user_name'], array('size' => 32, 'maxlength' => 100) + $protected), // Поле для ввода имени пользователя
	'USERS_EDIT_THEME' => cot_selectbox_theme($urr['user_theme'], $urr['user_scheme'], 'rusertheme'), // Выбор темы для пользователя
	'USERS_EDIT_LANG' => cot_selectbox_lang($urr['user_lang'], 'ruserlang'), // Выбор языка для пользователя
	'USERS_EDIT_NEWPASS' => cot_inputbox('password', 'rusernewpass', '', array('size' => 12, 'maxlength' => 32, 'autocomplete' => 'off') + $protected), // Поле для ввода нового пароля пользователя
	'USERS_EDIT_MAIN_GROUP' => cot_build_group($urr['user_maingrp']), // Основная группа пользователя
	'USERS_EDIT_GROUPS' => cot_build_groupsms($urr['user_id'], $usr['isadmin'], $urr['user_maingrp']), // Группы пользователя
	'USERS_EDIT_COUNTRY' => cot_selectbox_countries($urr['user_country'], 'rusercountry'), // Выбор страны для пользователя
	'USERS_EDIT_EMAIL' => cot_inputbox('text', 'ruseremail', $urr['user_email'], array('size' => 32, 'maxlength' => 64)), // Поле для ввода email пользователя
	'USERS_EDIT_HIDEEMAIL' => cot_radiobox($urr['user_hideemail'], 'ruserhideemail', array(1, 0), array($L['Yes'], $L['No'])), // Радио кнопки для скрытия email
	'USERS_EDIT_TEXT' => cot_textarea('rusertext', $urr['user_text'], 4, 56, array('class' => $editor_class)), // Поле для текста пользователя (с редактором, если активирован)
	'USERS_EDIT_GENDER' => cot_selectbox_gender($urr['user_gender'], 'rusergender'), // Выбор пола пользователя
	'USERS_EDIT_BIRTHDATE' => cot_selectbox_date(cot_date2stamp($urr['user_birthdate']), 'short', 'ruserbirthdate', cot_date('Y', $sys['now']), cot_date('Y', $sys['now']) - 100, false), // Выбор даты рождения
	'USERS_EDIT_TIMEZONE' => cot_selectbox_timezone($urr['user_timezone'], 'rusertimezone'), // Выбор часового пояса пользователя
	'USERS_EDIT_REGDATE' => cot_date('datetime_medium', $urr['user_regdate']), // Дата регистрации пользователя
	'USERS_EDIT_REGDATE_STAMP' => $urr['user_regdate'], // Временная метка регистрации
	'USERS_EDIT_LASTLOG' => cot_date('datetime_medium', $urr['user_lastlog']), // Дата последнего входа пользователя
	'USERS_EDIT_LASTLOG_STAMP' => $urr['user_lastlog'], // Временная метка последнего входа
	'USERS_EDIT_LOGCOUNT' => $urr['user_logcount'], // Количество логинов пользователя
	'USERS_EDIT_LASTIP' => cot_build_ipsearch($urr['user_lastip']), // IP-адрес последнего входа пользователя
	'USERS_EDIT_DELETE' => (Cot::$sys['user_istopadmin']) // Если пользователь - топ-администратор, добавляется возможность удалить пользователя
        ? cot_radiobox(0, 'ruserdelete', [1, 0], [Cot::$L['Yes'], Cot::$L['No']]) . $delete_pfs // Радио кнопки для удаления пользователя
        : Cot::$L['na'], // В противном случае выводится 'не доступно'
]);

В этом фрагменте кода происходит следующее:

  1. Присваиваются данные для отображения на странице редактирования пользователя. Через объект $t и метод assign() заполняются переменные шаблона, которые будут использоваться для отображения информации о пользователе.

  2. Для каждого поля редактирования (например, имени, темы, языка, email и т.д.) подготавливаются значения, которые будут вставлены в форму. Эти значения включают в себя данные пользователя, такие как имя, email, дата регистрации, страна, пол, дата рождения и другие параметры, полученные из базы данных.

  3. В некоторых случаях добавляются дополнительные настройки, например, для редактора текста или выпадающих списков с темами и языками. Если установлены определенные параметры (например, для полей "редактирование" или "удаление"), они обрабатываются с дополнительной логикой (например, условие для отображения радио кнопок для удаления пользователя, если текущий пользователь является топ-администратором).

  4. Для каждого поля формы создаются соответствующие элементы, такие как текстовые поля, выпадающие списки, радиокнопки или текстовые области. Это позволяет администратору редактировать данные пользователя, такие как имя, email, группы, темы и другие параметры.

  5. В конце концов, собранные данные передаются в шаблон, который будет отображать форму редактирования на веб-странице.

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

 

if (isset(Cot::$cfg['legacyMode']) && Cot::$cfg['legacyMode']) {  // Проверка наличия и значения параметра legacyMode в конфигурации
    // @deprecated in 0.9.24  // Закомментированное предупреждение об устаревании
    $t->assign([  // Присваивание значений в шаблон
        //'USERS_EDIT_ACTIVE' => $user_form_active,   // It seems it is obsolete code  // Устаревший код, закомментирован
        //'USERS_EDIT_BANNED' => $user_form_banned,   // It seems it is obsolete code  // Устаревший код, закомментирован
        'USERS_EDIT_DETAILSLINK' => cot_url('users', 'm=details&id=' . $urr['user_id']),  // Формирование ссылки на страницу деталей пользователя
        'USERS_EDIT_EDITLINK' => cot_url('users', 'm=edit&id=' . $urr['user_id']),  // Формирование ссылки на страницу редактирования пользователя
        'USERS_EDIT_MAINGRP' => cot_build_group($urr['user_maingrp']),  // Отображение основной группы пользователя
    ]);  // Завершающая скобка массива для присваивания
}  // Закрывающая скобка для условия legacyMode

В этом коде происходит следующее:

  1. Проверяется наличие и значение параметра legacyMode в конфигурации (Cot::$cfg['legacyMode']). Если этот параметр существует и равен true, тогда выполняется блок кода внутри условия.

  2. Внутри блока кода с использованием метода assign() объекта шаблона $t задаются следующие переменные для шаблона:

    • USERS_EDIT_DETAILSLINK: Формируется ссылка на страницу деталей пользователя с использованием функции cot_url() и ID пользователя.
    • USERS_EDIT_EDITLINK: Формируется ссылка на страницу редактирования пользователя с использованием функции cot_url() и ID пользователя.
    • USERS_EDIT_MAINGRP: Используется функция cot_build_group() для отображения основной группы пользователя (например, отображение названия группы, к которой принадлежит пользователь).
  3. В коде закомментированы два устаревших параметра (USERS_EDIT_ACTIVE и USERS_EDIT_BANNED), которые, видимо, больше не используются, и их удаление помечено как "deprecated" (устаревшее). Это может означать, что эти переменные больше не влияют на работу кода и могут быть удалены в будущих версиях.

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

 

// Extra fields  // Комментарий, что обрабатываются дополнительные поля
if (!empty(Cot::$extrafields[Cot::$db->users])) {  // Проверка, есть ли дополнительные поля для пользователей
    foreach (Cot::$extrafields[Cot::$db->users] as $exfld) {  // Процесс перебора всех дополнительных полей пользователей
        $uname = strtoupper($exfld['field_name']);  // Преобразование имени поля в верхний регистр для использования в шаблоне
        $exfld_val = cot_build_extrafields('ruser' . $exfld['field_name'], $exfld, $urr['user_' . $exfld['field_name']]);  // Формирование значения дополнительного поля
        $exfld_title = cot_extrafield_title($exfld, 'user_');  // Получение заголовка для дополнительного поля

        $t->assign([  // Присваивание значений в шаблон
            'USERS_EDIT_' . $uname => $exfld_val,  // Присваивание значения дополнительного поля
            'USERS_EDIT_' . $uname . '_TITLE' => $exfld_title,  // Присваивание заголовка дополнительного поля
            'USERS_EDIT_EXTRAFLD' => $exfld_val,  // Присваивание значения дополнительного поля (возможно, для общего использования)
            'USERS_EDIT_EXTRAFLD_TITLE' => $exfld_title,  // Присваивание заголовка дополнительного поля (возможно, для общего использования)
        ]);
        $t->parse('MAIN.EXTRAFLD');  // Парсинг шаблона блока EXTRAFLD
    }
}  // Закрывающая скобка для условия наличия дополнительных полей

 

// Error and message reporting  // Комментарий, что будет произведен вывод сообщений об ошибках и других уведомлений
cot_display_messages($t);  // Вызов функции для отображения сообщений на странице, передача объекта шаблона для вывода

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

$t->parse('MAIN');  // Парсинг основного блока 'MAIN' шаблона

$t->out('MAIN');  // Вывод обработанного шаблона основного блока 'MAIN'

require_once Cot::$cfg['system_dir'] . '/footer.php';  // Подключение файла футера (нижней части страницы)

В этом фрагменте происходит несколько действий:

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

  2. Подключение плагинов: Затем идет цикл, в котором перебираются все подключенные к системе плагины, связанные с хуком users.edit.tags. Для каждого найденного плагина происходит его подключение. Это позволяет расширять функциональность шаблона с помощью дополнительных плагинов.

  3. Парсинг и вывод основного шаблона: Далее происходит парсинг основного шаблона с помощью метода parse, который обрабатывает контент и присваивает его объекту шаблона. После этого, с помощью метода out, выводится результат парсинга.

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

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

 

 

25 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-09-03 16:57

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-01-31 00:43
  • Last update: 2025-01-31 01:12

Similar pages

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