Исправления

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-03-29 10:19:31 +10:00
parent 8809a05c1b
commit e709d3d914
3 changed files with 134 additions and 63 deletions

View File

@ -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",

View File

@ -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 <red@hood.su>
*
* @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)
*

View File

@ -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;
}