*/ final class session_model extends core { /** * Коллекция */ public const COLLECTION = 'session'; /** * Инициализация * * @param ?string $hash Хеш сессии в базе данных * @param ?int $expires Дата окончания работы сессии (используется при создании новой сессии) * @param array &$errors Журнал ошибок * * @return ?_document Инстанция сессии, если удалось найти или создать */ public static function initialization(?string $hash = null, ?int $expires = null, array &$errors = []): ?_document { try { if (collection::init(static::$db->session, self::COLLECTION)) { // Инициализирована коллекция if (isset($hash) && $session = collection::search(static::$db->session, sprintf( << %d RETURN d AQL, self::COLLECTION, time() ))) { // Найдена сессия по хешу // Возврат сессии return $session; } else if ($session = collection::search(static::$db->session, sprintf( << %d RETURN d AQL, self::COLLECTION, $_SERVER['REMOTE_ADDR'], time() ))) { // Найдена сессия по данным пользователя // Возврат сессии return $session; } else { // Не найдена сессия // Запись сессии в базу данных $_id = document::write(static::$db->session, self::COLLECTION, [ 'ip' => $_SERVER['REMOTE_ADDR'], 'expires' => $expires ?? time() + 604800 ]); if ($session = collection::search(static::$db->session, sprintf( << %d RETURN d AQL, self::COLLECTION, time() ))) { // Найдена созданная сессия // Запись хеша $session->hash = sodium_bin2hex(sodium_crypto_generichash($_id)); if (document::update(static::$db->session, $session)) { // Записано обновление return $session; } else throw new exception('Не удалось записать данные сессии'); } else throw new exception('Не удалось создать или найти созданную сессию'); } } else throw new exception('Не удалось инициализировать коллекцию'); } catch (exception $e) { // Запись в журнал ошибок $errors[] = [ 'text' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'stack' => $e->getTrace() ]; } return null; } /** * Связь сессии с аккаунтом * * @param _document $session Инстанция сессии * @param _document $account Инстанция аккаунта * @param array &$errors Журнал ошибок * * @return bool Статус выполнения */ public static function connect(_document $session, _document $account, array &$errors = []): bool { try { if ( collection::init(static::$db->session, self::COLLECTION) && collection::init(static::$db->session, account::COLLECTION) && collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true) ) { // Инициализирована коллекция if (document::write(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, [ '_from' => $session->getId(), '_to' => $account->getId() ])) { // Создано ребро: session -> account return true; } else throw new exception('Не удалось создать ребро: session -> account'); } else throw new exception('Не удалось инициализировать коллекцию'); } catch (exception $e) { // Запись в журнал ошибок $errors[] = [ 'text' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'stack' => $e->getTrace() ]; } return false; } /** * Поиск связанного аккаунта * * @param _document $session Инстанция сессии * @param array &$errors Журнал ошибок * * @return ?_document Инстанция аккаунта, если удалось найти */ public static function account(_document $session, array &$errors = []): ?_document { try { if ( collection::init(static::$db->session, self::COLLECTION) && collection::init(static::$db->session, account::COLLECTION) && collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true) ) { // Инициализированы коллекции if ($account = collection::search(static::$db->session, sprintf( <<getId() ))) { // Найден аккаунт return $account; } else throw new exception('Не удалось найти аккаунт'); } else throw new exception('Не удалось инициализировать коллекцию'); } catch (exception $e) { // Запись в журнал ошибок $errors[] = [ 'text' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'stack' => $e->getTrace() ]; } return null; } }