Просмотр файла delta_framework-main/core/lib/Core/Models/User.class.php

Размер файла: 34.79Kb
<?php
    /**
     * Copyright (c) 2022 Roman Grinko <rsgrinko@gmail.com>
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */

    /**
     * Класс для работы с пользователями
     */

    namespace Core\Models;

    use Core\CoreException;
    use Core\Helpers\{Cache, Log, Mail, Sanitize, SystemFunctions};
    use Core\DataBases\DB;
    use Core\DTO\User\FilterUser;
    use Throwable;

    class User
    {

        /**
         * ID текущего пользователя
         *
         * @var int
         */
        public int $id;

        /**
         * Объект групп
         *
         * @var Roles|null
         */
        public ?Roles $rolesObject = null;

        /**
         * Объект Mail
         *
         * @var Mail|null
         */
        public ?Mail $mailObject = null;

        /**
         * Объект Dialog
         *
         * @var Dialog|null
         */
        public ?Dialog $dialogObject = null;

        /**
         * Объект мета данных
         *
         * @var UserMeta|null
         */
        public ?UserMeta $metaObject = null;

        /**
         * Таблица с пользователями
         */
        private const TABLE = DB_TABLE_PREFIX . 'users';

        /**
         * @var string $cryptoSalt Соль для шифрования
         */
        private static string $cryptoSalt = 'BKH92FdiQvEW2aOy0giywXasYAMl0pFvIrlop8Sz';

        /**
         * Конструктор класса
         *
         * @param int|null $id Идентификатор пользователя
         *
         * @throws CoreException
         */
        public function __construct(?int $id)
        {
            if (empty($id)) {
                throw new CoreException('Передан некорректный идентификатор пользователя', CoreException::ERROR_INCORRECT_USER_ID);
            }
            if (!self::isUserExistsByParams(['id' => $id])) {
                throw new CoreException('Пользователь с идентификатором ' . $id . ' отсутствует в базе', CoreException::ERROR_USER_NOT_FOUND);
            }

            $this->id = $id;
        }

        /**
         * Получение аватара пользователя
         *
         * @return array|null
         * @throws CoreException
         */
        public function getImage(): ?array
        {
            $result  = null;
            $imageId = $this->getAllUserData()['image_id'];

            if (!empty($imageId)) {
                try {
                    $result = (new File($imageId))->getAllProps();
                } catch (CoreException $e) {
                }
            }

            return $result;
        }

        /**
         * Получение всех полей пользователя
         *
         * @param bool $onlySecureData Флаг получения только безопасных данных
         *
         * @return array|null
         * @throws CoreException
         */
        public function getAllUserData(bool $onlySecureData = false): ?array
        {
            $onlySecureDataCacheKey = (int)$onlySecureData;
            $cacheId = md5('User_getAllUserData_' . $onlySecureDataCacheKey . '_' . $this->id);
            if (Cache::check($cacheId)) {
                $result = Cache::get($cacheId);
            } else {
                $result = (DB::getInstance())->getItem(self::TABLE, ['id' => $this->id]);
                $result = array_merge($result, ['roles' => $this->getRolesObject()->getRoles()]);
                $result['nameForDisplay'] = '[' . $result['id'] . '] (' . $result['login'] . ') ' . $result['name'];

                // В случае запроса безопасных данных убираем лишнее
                if ($onlySecureData) {
                    foreach($result as $key => $value) {
                        if (in_array($key, ['password', 'email_confirmed', 'verification_code', 'token', 'roles', ''], true)) {
                            unset($result[$key]);
                        }
                    }
                }

                Cache::set($cacheId, $result);
            }

            if (!empty($result)) {
                return $result;
            }

            return null;
        }

        /**
         * Получение логина текущего пользователя
         *
         * @return string|null
         * @throws CoreException
         */
        public function getLogin(): ?string
        {
            return $this->getAllUserData() ? $this->getAllUserData()['login'] : null;
        }

        /**
         * Получение E-Mail'а текущего пользователя
         *
         * @return string|null
         * @throws CoreException
         */
        public function getEmail(): ?string
        {
            return $this->getAllUserData() ? $this->getAllUserData()['email'] : null;
        }

        /**
         * Получение имени текущего пользователя
         *
         * @return string|null
         * @throws CoreException
         */
        public function getName(): ?string
        {
            return $this->getAllUserData() ? $this->getAllUserData()['name'] : null;
        }

        /**
         * Получение токена текущего пользователя
         *
         * @return string|null
         * @throws CoreException
         */
        public function getToken(): ?string
        {
            return $this->getAllUserData() ? $this->getAllUserData()['token'] : null;
        }

        /**
         * Получение времени последней активности
         *
         * @return int|null
         * @throws CoreException
         */
        public function getLastActive(): ?int
        {
            return $this->getAllUserData() ? (int)$this->getAllUserData()['last_active'] : null;
        }

        /**
         * Получение идентификатора текущего пользователя
         *
         * @return int|null
         */
        public function getId(): ?int
        {
            return $this->id;
        }

        /**
         * Получение кода верификации
         *
         * @return string|null
         * @throws CoreException
         */
        public function getVerificationCode(): ?string
        {
            return $this->getAllUserData() ? $this->getAllUserData()['verification_code'] : null;
        }

        /**
         * Получение всех пользователей панели
         *
         * @param string $limit Лимит
         * @param string $sort  Сортировка
         *
         * @return array
         * @throws CoreException
         */
        public static function getUsers(string $limit = '10', string $sort = 'ASC'): array
        {
            $cacheId = md5('User_getUsers_' . $limit . '_' . $sort);
            if (Cache::check($cacheId)) {
                $res = Cache::get($cacheId);
            } else {
                $res = (DB::getInstance())->query('SELECT * FROM `' . self::TABLE . '` ORDER BY `id` ' . $sort . ' LIMIT ' . $limit);
                Cache::set($cacheId, $res);
            }
            return $res;
        }

        /**
         * Создание пользовательского токена
         *
         * @return string
         * @throws CoreException
         */
        public function createToken(): string
        {
            $newToken = self::generateGUID();
            (DB::getInstance())->update(self::TABLE, ['id' => $this->id], ['token' => $newToken]);
            Log::logToFile('Создан токен', 'User.log', ['userId' => $this->id, 'token' => $newToken]);
            return $newToken;
        }

        /**
         * Генерация GUID
         *
         * @return string
         * @throws \Exception
         */
        private static function generateGUID(): string
        {
            $uid  = dechex(microtime(true) * 1000) . bin2hex(random_bytes(8));
            $guid = vsprintf('RG%s-1000-%s-8%.3s-%s%s%s0', str_split($uid, 4));
            Log::logToFile('Сгенерирован GUID', 'User.log', ['GUID' => $guid]);
            return strtoupper($guid);
        }


        /**
         * Проверка существования токена
         *
         * @param string $token Токен
         *
         * @return bool
         */
        public static function isTokenExists(string $token): bool
        {
            $result = (DB::getInstance())->getItem(self::TABLE, ['token' => $token]);
            if ($result) {
                return true;
            }

            return false;
        }

        /**
         * Получение пользователя по токену
         *
         * @param string $token Токен
         *
         * @return User|null
         * @throws CoreException
         */
        public static function getByToken(string $token): ?self
        {
            $result = (DB::getInstance())->getItem(self::TABLE, ['token' => $token]);
            if ($result) {
                return (new self((int)$result['id']));
            }

            return null;
        }

        /**
         * Проверка пользователя на существование по параметрам
         *
         * @param array $where Массив параметров фильтра
         *
         * @return bool
         */
        public static function isUserExistsByParams(array $where): bool
        {
            $result = (DB::getInstance())->getItem(self::TABLE, $where);
            if (!empty($result)) {
                return true;
            }

            return false;
        }

        /**
         * Получение объекта пользователя по параметрам
         *
         * @param array $where Массив параметров фильтра
         *
         * @return self
         * @throws CoreException
         */
        public static function getByParams(array $where): ?self
        {
            $result = (DB::getInstance())->getItem(self::TABLE, $where);
            if (!empty($result)) {
                return (new self((int)$result['id']));
            }

            return null;
        }

        /**
         * Получить объект пользователя по ID при его существовании
         *
         * @throws CoreException
         */
        public static function getById(int $id): ?self
        {
            if (self::isUserExistsByParams(['id' => $id])) {
                return new self($id);
            }
            return null;
        }

        /**
         * Получение строки с данными о пользователе по ID
         *
         * @return string [123] (admin) Роман
         * @throws CoreException
         */
        public static function getInfoById(int $id): string
        {
            if (self::isUserExistsByParams(['id' => $id])) {
                $objectUser = new self($id);
                return '[' . $id . '] (' . $objectUser->getLogin() . ') ' . $objectUser->getName();
            }
            return 'Неизвестно';
        }

        /**
         * Проверка пользователя на онлайн
         *
         * @param int $id
         *
         * @return bool
         */
        public static function isOnline(int $id): bool
        {
            $res         = (DB::getInstance())->query('SELECT last_active FROM `' . self::TABLE . '` WHERE id=' . $id);
            $last_active = $res[0]['last_active'];
            $timeNow     = time();
            if ($last_active > ($timeNow - USER_ONLINE_TIME)) {
                return true;
            }

            return false;
        }

        /**
         * Шифрование пароля
         *
         * @param string $password Пароль
         *
         * @return string
         */
        public static function passwordEncryption(string $password): string
        {
            return md5(self::$cryptoSalt . $password);
        }


        /**
         * Выполняет регистрацию пользователя в системе
         *
         * @param string $login    Логин
         * @param string $password Пароль
         * @param string $email    E-Mail
         * @param string $name     Имя
         *
         * @return int
         * @throws CoreException
         */
        public static function create(string $login, string $password, string $email, string $name = ''): int
        {
            $login = Sanitize::sanitizeString($login);
            $email = Sanitize::sanitizeEmail($email);
            $name  = Sanitize::sanitizeString($name);

            if (self::isUserExists($login)) {
                throw new CoreException('Пользователь с данным логином уже существует', CoreException::ERROR_CREATE_USER);
            }

            if (self::isUserExistsByParams(['email' => $email])) {
                throw new CoreException('Пользователь с данным E-Mail уже существует', CoreException::ERROR_CREATE_USER);
            }

            Log::logToFile('Создание нового пользователя', 'User.log', func_get_args());
            $verificationCode = md5(self::$cryptoSalt . $email . $login . time());

            /** @var $DB DB Объект базы данных */
            $DB         = DB::getInstance();
            $userId     = $DB->addItem(self::TABLE, [
                'login'             => $login,
                'password'          => self::passwordEncryption($password),
                'name'              => $name,
                'image_id'          => 0,
                'token'             => null,
                'email'             => $email,
                'email_confirmed'   => CODE_VALUE_N,
                'verification_code' => $verificationCode,
                'last_active'       => time(),
            ]);
            $objectUser = null;

            try {
                $objectUser = (new self($userId));
            } catch (CoreException $e) {
                Log::logToFile('Ошибка создания объекта пользователя', 'User.log', func_get_args());
                throw new CoreException('Ошибка создания объекта пользователя', CoreException::ERROR_CREATE_USER);
            }

            try {
                $objectUser->getRolesObject()->addRole(Roles::USER_ROLE_ID);
            } catch (CoreException $e) {
                Log::logToFile('Ошибка добавления ролей пользователю', 'User.log', func_get_args());
                throw new CoreException('Ошибка добавления ролей пользователю', CoreException::ERROR_ADD_USER_ROLES);
            }

            try {
                $objectUser->sendVerificationCode();
            } catch (CoreException $e) {
                Log::logToFile('Ошибка отправки кода верификации пользователю', 'User.log', func_get_args());
                throw new CoreException('Ошибка отправки кода верификации пользователю', CoreException::ERROR_SEND_VERIFICATION_CODE);
            }
            Log::logToFile('Пользователь успешно создан', 'User.log', ['userId' => $userId]);

            $objectUser->getMailObject()->setSubject('Регистрация на сайте')->setBody(
                    '<b>Логин:</b> ' . $objectUser->getLogin() . PHP_EOL . '<b>Пароль:</b> ' . $password
                )->setTemplateVars(['TITLE' => 'Создана учетная запись'])->send();

            return $userId;
        }

        /**
         * Обновление данных пользователя
         *
         * @param array $fields Массив полей для обновления
         *
         * @return bool
         * @throws CoreException
         */
        public function update(array $fields): bool
        {
            foreach ($fields as $key => $value) {
                $fields[$key] = Sanitize::sanitizeString($value);
            }
            $cacheId = md5('User_getAllUserData_' . $this->id);
            $beforeData = [];
            foreach($fields as $key => $value) {
                $beforeData[$key] = $this->getAllUserData()[$key];
            }
            /** @var $DB DB Объект базы данных */
            $DB = DB::getInstance();
            Log::logToFile(
                'Данные пользователя изменены', 'User.log', ['userId' => $this->id, 'before' => $beforeData, 'after' => $fields]
            );
            Cache::delete($cacheId);
            return $DB->update(self::TABLE, ['id' => $this->id], $fields);
        }

        /**
         * Проверяет логин на существование
         *
         * @param string $login
         *
         * @return bool
         */
        public static function isUserExists(string $login): bool
        {
            $cacheId = md5('isUserExists_' . $login);
            if (Cache::check($cacheId)) {
                $result = Cache::get($cacheId);
            } else {
                /** @var $DB DB Объект базы данных */
                $DB     = DB::getInstance();
                $result = $DB->getItem(self::TABLE, ['login' => $login]);
                Cache::set($cacheId, $result);
            }

            if ($result) {
                return true;
            }

            return false;
        }

        /**
         * Получение количества пользователей
         *
         * @return int
         */
        public static function getAllCount(): int
        {
            $cacheId = md5('User::getAllCount');
            if (Cache::check($cacheId) && Cache::getAge($cacheId) < 300) {
                $result = Cache::get($cacheId);
            } else {
                /** @var $DB DB Объект базы данных */
                $DB     = DB::getInstance();
                $result = $DB->getItems(self::TABLE, ['id' => '>0']);
                Cache::set($cacheId, $result);
            }

            if ($result) {
                return count($result);
            }

            return 0;
        }

        /**
         * Выполняет авторизацию пользователя в системе по ID
         *
         * @param int|null $id       Идентификатор пользователя
         * @param bool     $remember Запомнить
         *
         * @return bool
         * @throws CoreException
         */
        public static function authorize(?int $id = null, bool $remember = false): bool
        {
            if ($id === null) {
                throw new CoreException('Передан некорректный идентификатор пользователя');
            }
            self::logout();
            /** @var $DB DB Объект базы данных */
            $DB     = DB::getInstance();
            $result = $DB->getItem(self::TABLE, ['id' => $id], true);

            if ($result) {
                $_SESSION['id']        = $result['id'];
                $_SESSION['authorize'] = CODE_VALUE_Y;
                $_SESSION['login']     = $result['login'];
                $_SESSION['password']  = self::passwordEncryption($result['password']);
                $_SESSION['token']     = $result['token'];
                $_SESSION['user']      = $result;
                if ($remember) {
                    setcookie('userId', $result['id'], time() + 3600 * 24);
                    setcookie('userLogin', $result['login'], time() + 3600 * 24);
                    setcookie('token', md5(self::$cryptoSalt . $result['id'] . $result['login'] . $result['password']), time() + 3600 * 24);
                }
                return true;
            }

            return false;
        }

        /**
         * Выполняет авторизацию пользователя в системе по логину и паролю
         *
         * @param string $login    Логин
         * @param string $password Пароль
         * @param bool   $remember Запомнить
         *
         * @return bool
         */
        public static function securityAuthorize(string $login, string $password, bool $remember = false): bool
        {
            /** @var $DB DB Объект базы данных */
            $DB     = DB::getInstance();
            $result = $DB->getItem(self::TABLE, ['login' => $login, 'password' => self::passwordEncryption($password)], true);
            if ($result) {
                $_SESSION['id']        = $result['id'];
                $_SESSION['authorize'] = 'Y';
                $_SESSION['login']     = $result['login'];
                $_SESSION['password']  = self::passwordEncryption($result['password']);
                $_SESSION['token']     = $result['token'];
                $_SESSION['user']      = $result;
                if ($remember) {
                    setcookie('userId', $result['id'], time() + 3600 * 24);
                    setcookie('userLogin', $result['login'], time() + 3600 * 24);
                    setcookie('token', md5(self::$cryptoSalt . $result['id'] . $result['login'] . $result['password']), time() + 3600 * 24);
                }
                return true;
            }

            return false;
        }

        /**
         * Получение идентификатора текущего пользователя
         *
         * @return int|null
         * @throws CoreException
         */
        public static function getCurrentUserId(): ?int
        {
            if (self::isAuthorized()) {
                return $_SESSION['id'];
            }

            return null;
        }

        /**
         * Проверка на пользователя
         *
         * @return bool
         * @throws CoreException
         */
        public static function isAuthorized(): bool
        {
            /** @var $DB DB Объект базы данных */
            $DB = DB::getInstance();

            if (!empty($_COOKIE['userId'])
                && !empty($_COOKIE['userLogin'])
                && self::isUserExists($_COOKIE['userLogin'])) {
                $arUser = $DB->getItem(self::TABLE, ['id' => $_COOKIE['userId']]);
                if ($_COOKIE['token'] == md5(self::$cryptoSalt . $arUser['id'] . $arUser['login'] . $arUser['password'])) {
                    if (empty($_SESSION['authorize'])) {
                        self::authorize($arUser['id']);
                    }
                    return true;
                }
            }
            if (empty($_SESSION['authorize']) || $_SESSION['authorize'] !== 'Y') {
                return false;
            }
            $result = $DB->getItem(self::TABLE, ['login' => $_SESSION['login']]);
            if ($result) {
                if (self::passwordEncryption($result['password']) == $_SESSION['password']) {
                    $DB->update(self::TABLE, ['id' => $result['id']], ['last_active' => time()]);
                    $_SESSION['id'] = $result['id'];
                    return true;
                }
                return false;
            }
            return false;
        }

        /**
         * Проверка на админа
         *
         * @return bool
         * @throws CoreException
         */
        public function isAdmin(): bool
        {
            return in_array(Roles::ADMIN_ROLE_ID, $this->getRolesObject()->getRoles(), true);
        }

        /**
         * Проверка на менеджера
         *
         * @return bool
         * @throws CoreException
         */
        public function isManager(): bool
        {
            return in_array(Roles::MANAGER_ROLE_ID, $this->getRolesObject()->getRoles(), true);
        }

        /**
         * Проверка на доступ в админку
         *
         * @return bool
         * @throws CoreException
         */
        public function haveAccessToAdminPanel(): bool
        {
            return in_array(Roles::ADMIN_PANEL_ROLE_ID, $this->getRolesObject()->getRoles(), true);
        }

        /**
         * Метод выхода из системы
         */
        public static function logout(): void
        {
            unset($_SESSION['id']);
            unset($_SESSION['authorize']);
            unset($_SESSION['login']);
            unset($_SESSION['password']);
            unset($_SESSION['token']);
            unset($_SESSION['user']);

            setcookie('userId', '', time() - 3600);
            setcookie('userLogin', '', time() - 3600);
            setcookie('token', '', time() - 3600);
        }

        /**
         * Получить объект для работы с ролями
         *
         * @return Roles
         */
        public function getRolesObject(): Roles
        {
            if (empty($this->rolesObject)) {
                $this->rolesObject = (new Roles($this));
            }
            return $this->rolesObject;
        }

        /**
         * Получить объект для работы с ролями
         *
         * @return UserMeta
         */
        public function getMetaObject(): UserMeta
        {
            if (empty($this->metaObject)) {
                $this->metaObject = (new UserMeta($this));
            }
            return $this->metaObject;
        }

        /**
         * Получить объект для работы с почтой
         *
         * @return Mail
         */
        public function getMailObject(): Mail
        {
            if (empty($this->mailObject)) {
                $this->mailObject = (new Mail($this));
            }
            return $this->mailObject;
        }

        /**
         * Получить объект для работы с диалогами
         *
         * @return Dialog
         */
        public function getDialogObject(): Dialog
        {
            if (empty($this->dialogObject)) {
                $this->dialogObject = (new Dialog($this));
            }
            return $this->dialogObject;
        }

        /**
         * Экспорт всех данных из таблицы пользователей
         *
         * @return string XML данные
         * @throws CoreException
         */
        public static function exportUsers(): string
        {
            /** @var $DB DB Объект базы данных */
            $DB  = DB::getInstance();
            $res = $DB->query('SELECT * FROM ' . self::TABLE);
            foreach ($res as $key => $element) {
                $res[$key]['roles'] = (new self($element['id']))->getRolesObject()->getRoles();
            }
            return SystemFunctions::arrayToXml($res, self::TABLE);
        }

        /**
         * Выборка пользователей по роли
         *
         * @param int $roleId Идентификатор роли
         *
         * @return self[]
         * @throws CoreException
         */
        public static function getListByRole(int $roleId): array
        {
            $result = [];
            /** @var $DB DB Объект базы данных */
            $DB  = DB::getInstance();
            $res = $DB->getItems(Roles::USER_ROLES_TABLE, ['id' => $roleId]);
            foreach ($res as $element) {
                $result[] = new self((int)$element['user_id']);
            }
            return $result;
        }

        /**
         * Проверка электронной почты на подтвержденность
         *
         * @return bool
         * @throws CoreException
         */
        public function isEmailConfirmed(): bool
        {
            return $this->getAllUserData()['email_confirmed'] === CODE_VALUE_Y;
        }

        /**
         * Верификация E-Mail
         *
         * @throws CoreException
         */
        public static function verification(string $verificationCode): bool
        {
            $verificationCode = Sanitize::sanitizeString($verificationCode);

            /** @var $DB DB Объект базы данных */
            $DB  = DB::getInstance();
            $res = $DB->getItem(self::TABLE, ['verification_code' => $verificationCode]);
            if ($res) {
                if ($res['email_confirmed'] === CODE_VALUE_Y) {
                    Log::logToFile('E-Mail уже верифицирован', 'User.log', ['userId' => $res['id'], 'code' => $verificationCode]);
                    return false;
                }
                (new self($res['id']))->update(['email_confirmed' => CODE_VALUE_Y]);
                Log::logToFile('E-Mail успешно верифицирован', 'User.log', ['userId' => $res['id'], 'code' => $verificationCode]);
                return true;
            }
            Log::logToFile('Ошибка верификации E-Mail', 'User.log', ['code' => $verificationCode]);
            return false;
        }

        /**
         * Отправка кода верификации пользователю на почту
         *
         * @return bool Результат отправки
         * @throws CoreException
         */
        public function sendVerificationCode(): bool
        {
            if (empty($this->getAllUserData()['verification_code'])) {
                Log::logToFile('Ошибка отправки кода верификации: код отсутствует', 'User.log', ['userId' => $this->id]);
                throw new CoreException('Ошибка отправки кода верификации: код отсутствует');
            }
            Log::logToFile('Выслан код верификаци', 'User.log', ['userId' => $this->id, 'code' => $this->getAllUserData()['verification_code']]);
            return (bool)$this->getMailObject()->setSubject('Подтверждение E-Mail')->setBody(
                    'Код верификации: <b>' . $this->getVerificationCode() . '</b>' . PHP_EOL . 'Для подтверждения E-Mail перейдите по <a href="'
                    . SITE_URL_CORE . '/verification.php?code=' . $this->getVerificationCode() . '">ссылке</a>'
                )->setTemplateVars(['TITLE' => 'Подтверждение E-Mail'])->send()[0];
        }

        public function resetPassword(): bool
        {
            $newPassword = SystemFunctions::generatePassword();

            try {
                $this->update(['password' => self::passwordEncryption($newPassword)]);
            } catch (CoreException $e) {
                return false;
            }

            Log::logToFile('Произведен сброс пароля', 'User.log', ['userId' => $this->id, 'password' => $newPassword]);

            $this->getMailObject()->setSubject('Произведен сброс пароля')->setBody(
                    '<b>Логин:</b> ' . $this->getLogin() . PHP_EOL . '<b>Пароль:</b> ' . $newPassword
                )->setTemplateVars(['TITLE' => 'Ваши учетные данные'])->send();
            return true;
        }

        /**
         * Получение количества пользователей
         *
         * @param bool $onlyConfirmed Только с подтвержденным E-Mail
         *
         * @return int Количество
         */
        public static function getUsersCount($onlyConfirmed = false): int
        {
            /** @var $DB DB Объект базы данных */
            $DB  = DB::getInstance();
            $sql = 'SELECT COUNT(*) as count FROM ' . self::TABLE;
            if ($onlyConfirmed) {
                $sql .= ' WHERE email_confirmed="' . CODE_VALUE_Y . '"';
            }
            $res = $DB->query($sql);
            return (int)$res[0]['count'];
        }

        /**
         * Получение диалогов
         *
         * @return array
         * @throws CoreException
         */
        public function getDialogs(): array
        {
            $dialogs = $this->getDialogObject()->getDialogs();
            foreach ($dialogs as $key => $dialog) {
                $dialogs[$key]['companionId'] = $this->getDialogObject()->getDialogCompanionId((int)$dialog['id']);
                $dialogs[$key]['companionData'] = (new self((int)$dialogs[$key]['companionId']))->getAllUserData(true);
                $dialogs[$key]['unviewedCount'] = $this->getDialogObject()->getDialogUnviewedMessagesCount((int)$dialog['id']);
            }

            return $dialogs;
        }

        /**
         * Получение диалогов
         *
         * @param int  $dialogId   Идентификатор диалога
         * @param bool $markViewed Пометить прочитанным
         *
         * @return array
         * @throws CoreException
         */
        public function getMessages(int $dialogId, bool $markViewed = false): array
        {
            $messages = $this->getDialogObject()->getMessages($dialogId, $markViewed);
            foreach ($messages as $key => $message) {
                $messages[$key]['user_from_data'] = (new self((int)$message['user_from']))->getAllUserData(true);
                $messages[$key]['user_to_data'] = (new self((int)$message['user_to']))->getAllUserData(true);
                if ($message['type'] !== Dialog::MESSAGE_TYPE_TEXT) {
                    $messages[$key]['file'] = (new File((int)$message['text']))->getAllProps();
                    if ($messages[$key]['file'] === null) {
                        $messages[$key]['file']['error'] = true;
                    } else {
                        $messages[$key]['file']['error'] = false;
                    }
                }
            }

            return $messages;
        }
    }