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

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

Опубликовано в: Модули в Cotonti из коробки

Файл "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 минут чтения Sodium Carbonate

Комментарии (0)

Комментарии отсутствуют
Добавление комментариев доступно только зарегистрированным пользователям

Автор контента

webitproff

Оффлайн

Sodium Carbonate

Последняя авторизация: 20.07.2026 04:22

  • Страница размещена: 31.01.2025 00:43
  • Последнее обновление: 31.01.2025 01:12

Похожие страницы

Модуль "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 — это обработка административной панели