From e709d3d9145ccdec0dc2c50390d3b73b73fb1109 Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Mon, 29 Mar 2021 10:19:31 +1000 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- .../arangodb/sessions/ArangoDbSession.php | 180 +++++++++++++----- .../arangodb/sessions/MultiFieldSession.php | 15 +- 3 files changed, 134 insertions(+), 63 deletions(-) diff --git a/composer.json b/composer.json index 498c6a5..f04cedd 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "mirzaev/yii2-arangodb-sessions", - "description": "Yii\\web\\DbSession implementation for use with ArangoDB", + "description": "yii\\web\\DbSession implementation for use with ArangoDB", "keywords": [ "Yii2", "ArangoDB", diff --git a/mirzaev/yii2/arangodb/sessions/ArangoDbSession.php b/mirzaev/yii2/arangodb/sessions/ArangoDbSession.php index ffeec20..7ff4e7e 100644 --- a/mirzaev/yii2/arangodb/sessions/ArangoDbSession.php +++ b/mirzaev/yii2/arangodb/sessions/ArangoDbSession.php @@ -16,7 +16,7 @@ use Exception; /** * Реализация DbSession под ArangoDB * - * @property Connection|array|string $database Идентификатор компонента (Component ID) + * @property Connection|array|string $database Идентификатор компонента с базой данных (Component ID) * @property string $document Название документа для хранения данных сеанса (Document name for storing session data) * @property array $buffer Буфер данных для записи в документ сессии (Data buffer for write to session document) * @@ -31,6 +31,7 @@ use Exception; * @method public destroySession() Удалить сессию (Delete session) * @method public gcSession() Удалить неиспользуемые данные (Delete garbage) * @method protected getReadQuery() Генерация запроса для чтения сеанса (Generating a query to read a session) + * @method protected genBuffer() Генерация массива данных для записи (Generating an array of data to writing) * @method protected typecastFields() Конвертация для отправки в PDO (Convertation for sending to PDO) * * @example ./Migrations/create_sessions_collection.php @@ -45,12 +46,14 @@ use Exception; * * @package yii2\ArangoDB * @author Arsen Mirzaev Tatyano-Muradovich + * + * @since 2.0 */ final class ArangoDbSession extends MultiFieldSession { /** - * Идентификатор компонента (Component ID) + * Идентификатор компонента с базой данных (Component ID) */ public Connection|array|string $database = 'arangodb'; @@ -141,7 +144,7 @@ final class ArangoDbSession extends MultiFieldSession return; } - // parent::regenerateID(false); + parent::regenerateID(false); $newID = session_id(); @@ -153,9 +156,9 @@ final class ArangoDbSession extends MultiFieldSession } $row = (new Query()) - ->in($this->document) - ->where(['hash' => $oldID]) - ->one($this->database); + ->in($this->document) + ->where(['hash' => $oldID]) + ->one($this->database); if ($row) { if ($rewrite) { @@ -163,20 +166,28 @@ final class ArangoDbSession extends MultiFieldSession (new Query()) ->in($this->document) - ->where(['hash' => $newID]) - ->update(['hash' => $oldID], db: $this->database); + ->where(['hash' => $oldID]) + ->update($this->genBuffer($newID), db: $this->database); } else { // Создать + // Инициализация + $new = $row; + $new['id'] = $newID; + (new Query()) ->in($this->document) - ->insert(['hash' => $newID], db: $this->database); + ->insert($new, db: $this->database); } } else { // shouldn't reach here normally (new Query()) ->in($this->document) - ->insert($this->composeFields($newID, ''), db: $this->database); + ->insert($this->genBuffer($newID), db: $this->database); + + // (new Query()) + // ->in($this->document) + // ->insert($this->composeFields($newID, ''), db: $this->database); !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } } @@ -187,11 +198,10 @@ final class ArangoDbSession extends MultiFieldSession * * @return string Данные сессии (The session data) */ - public function readSession($id): string - // public function readSession(string $id): string + public function readSession($hash): string + // public function readSession(string $hash): string { - $query = $this->getReadQuery($id); - + $query = $this->getReadQuery($hash); if ($this->readCallback !== null) { $data = $query->one($this->database); @@ -207,15 +217,22 @@ final class ArangoDbSession extends MultiFieldSession /** * Найти сессию (Search session) * - * @param string $id Идентификатор сессии (Session ID) + * @param string $hash Идентификатор сессии (Session ID) * * @return array|null Сессия, если найдена (Session, if founded) */ - public function searchSession(string $id): ?array + public function searchSession(string $hash): ?array { + if (empty($hash)) { + return false; + } + $session = (new Query()) ->in($this->document) - ->where(['hash' => $id]) + ->where([ + 'hash' => $hash, + 'status' => 'active' + ]) ->one($this->database); return $session ? $session : null; @@ -224,15 +241,35 @@ final class ArangoDbSession extends MultiFieldSession /** * Инициализировать сессию (Initialize session) * - * @param string $id Идентификатор сессии (Session ID) + * @param string $hash Идентификатор сессии (Session ID) + * @param string|null $data Данные сессии (Session data) * - * @return array Сессия (Session) + * @return array Сессия или статус обновления (Session or update status) */ - public function initSession(string $id): array + public function initSession(string $hash, string|null $data = null): array|bool|null { - return $this->searchSession($id) ?? (new Query()) + if (empty($hash)) { + return null; + } + + if ($session = $this->searchSession($hash)) { + if (isset($data, $session['data']) && $session['data'] !== $data) { + // Необходима синхронизация (данные не идентичны) + + return (new Query()) + ->in($this->document) + ->where(['hash' => $session['hash']]) + ->update(['data' => $data], db: $this->database); + } + + return $session; + } + + $query = (new Query()) ->in($this->document) - ->insert($this->buffer, db: $this->database); + ->insert($this->genBuffer($hash, $data), db: $this->database); + + return $query ? $query : null; } /** @@ -248,6 +285,7 @@ final class ArangoDbSession extends MultiFieldSession { if ($this->getUseStrictMode() && $id === $this->_forceRegenerateId) { //Ignore write when forceRegenerate is active for this id + return true; } @@ -261,25 +299,20 @@ final class ArangoDbSession extends MultiFieldSession // ensure data consistency if (isset($this->buffer['data'])) { + $_SESSION = $this->buffer['data']; } else { + $this->buffer['data'] = $data; } - $this->buffer = array_merge($this->buffer, [ - 'hash' => $id, - 'from' => time(), - 'to' => time() + $this->getTimeout(), - ]); + $this->genBuffer($id, $data); // Конвертация или сериализация, не пойму $this->buffer = $this->typecastFields($this->buffer); // Инициализация сессии - $this->initSession($id); - - // Деинициализация буфера данных сессии - $this->buffer = []; + $this->initSession($id, $data); } catch (Exception $e) { yii::$app->errorHandler->handleException($e); @@ -289,21 +322,45 @@ final class ArangoDbSession extends MultiFieldSession return true; } + /** + * Закрыть сессию (Close session) + * + * @return bool Статус закрытия сессии (Session closing status) + * + * @todo Разобраться почему вызывается destroySession и избавиться от перезаписи (сделать обновление существующей) + */ + public function closeSession(): bool + { + // try { + // $this->buffer['status'] = 'inactive'; + + // (new Query()) + // ->in($this->document) + // ->insert($this->buffer, db: $this->database); + // } catch (Exception $e) { + // yii::$app->errorHandler->handleException($e); + + // return false; + // } + + return true; + } + + + /** * Удалить сессию (Delete session) * - * @param string $id Идентификатор сессии (Session ID) + * @param string $hash Идентификатор сессии (Session ID) * * @return bool Статус удаления сессии (Session deleting status) */ - public function destroySession($id): bool - // public function destroySession(string $id): bool + public function destroySession($hash): bool + // public function destroySession(string $hash): bool { return (new Query()) ->in($this->document) - ->where([ - 'hash' => $id - ]) + ->where(['hash' => $hash]) ->remove(db: $this->database); } @@ -327,20 +384,20 @@ final class ArangoDbSession extends MultiFieldSession [ 'to' => time() ], - 'operator' => '>=' + 'operator' => '<=' ] ]) ->remove(db: $this->database); } /** - * Генерация запроса для чтения сеанса (Generating a query to read a session) + * Генерация запроса для чтения сессии (Generating a query to read a session) * - * @param string $id Идентификатор сессии (Session ID) + * @param string $hash Идентификатор сессии (Session ID) * * @return Query Инстанция запроса на чтение (Read query instance) */ - protected function getReadQuery(string $id): Query + protected function getReadQuery(string $hash): Query { return (new Query()) ->in($this->document) @@ -349,21 +406,40 @@ final class ArangoDbSession extends MultiFieldSession [ 'to' => time() ], - 'operator' => '<=' - ] - ]) - ->where([ - [ - 'to' => null - ] - ], 'OR') - ->where([ - [ - 'hash' => $id, + 'operator' => '>=' ], + [ + [ + 'hash' => $hash, + ], + [ + 'status' => 'active' + ] + ] ]); } + /** + * Генерация массива данных для записи (Generating an array of data to writing) + * + * @param string $hash Идентификатор сессии (Session ID) + * @param string $data Данные сессии (Session data) + * + * @return array Обработанный буфер (Handled buffer) + */ + protected function genBuffer(string $hash, string|null $data = null): array + { + return $this->buffer = array_merge( + $this->buffer, + $this->composeFields($hash, $data), + [ + 'from' => time(), + 'to' => time() + $this->getTimeout(), + 'status' => 'active' + ] + ); + } + /** * Конвертация для отправки в PDO (Convertation for sending to PDO) * diff --git a/mirzaev/yii2/arangodb/sessions/MultiFieldSession.php b/mirzaev/yii2/arangodb/sessions/MultiFieldSession.php index 4c60528..53aba50 100644 --- a/mirzaev/yii2/arangodb/sessions/MultiFieldSession.php +++ b/mirzaev/yii2/arangodb/sessions/MultiFieldSession.php @@ -82,22 +82,17 @@ abstract class MultiFieldSession extends Session /** * Composes storage field set for session writing. * - * @param string $id Optional session id - * @param string $data Optional session data + * @param string $hash Session id + * @param string $data Session data * * @return array storage fields */ - protected function composeFields($id = null, $data = null): array + protected function composeFields($hash = null, $data = null): array { $buffer = $this->writeCallback ? call_user_func($this->writeCallback, $this) : []; - if ($id !== null) { - $buffer['hash'] = $id; - } - - if ($data !== null) { - $buffer['data'] = $data; - } + isset($hash) and $buffer['hash'] = $hash; + isset($data) and $buffer['data'] = $data; return $buffer; }