diff --git a/.gitattributes b/.gitattributes index 37f66b6..366ae55 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ .gitattributes export-ignore .gitignore export-ignore +phpcs.xml export-ignore +phpstan.neon export-ignore diff --git a/composer.json b/composer.json index 0d183d7..077c2c9 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,24 @@ "nette/di": "^3.0", "nette/utils": "^3.2" }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.3", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "phpstan/phpstan": "^0.12.99", + "phpstan/phpstan-nette": "^0.12.21", + "spaze/coding-standard": "^0.0", + "spaze/encryption": "^0.4.0" + }, + "scripts": { + "lint": "vendor/bin/parallel-lint --colors src/", + "phpcs": "vendor/bin/phpcs src/", + "phpstan": "vendor/phpstan/phpstan/phpstan --ansi analyse --configuration phpstan.neon", + "test": [ + "@lint", + "@phpcs", + "@phpstan" + ] + }, "autoload": { "classmap": ["src/"] }, diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..d5af649 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..24b4d98 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,8 @@ +parameters: + paths: + - src + level: 7 + +includes: + - vendor/phpstan/phpstan-nette/extension.neon + - vendor/phpstan/phpstan-nette/rules.neon diff --git a/src/DI/MysqlSessionHandlerExtension.php b/src/DI/MysqlSessionHandlerExtension.php index 8259d5c..d70cb30 100644 --- a/src/DI/MysqlSessionHandlerExtension.php +++ b/src/DI/MysqlSessionHandlerExtension.php @@ -9,7 +9,7 @@ class MysqlSessionHandlerExtension extends CompilerExtension { - private $defaults = [ + private array $defaults = [ 'tableName' => 'sessions', 'lockTimeout' => 5, 'unchangedUpdateDelay' => 300, diff --git a/src/MysqlSessionHandler.php b/src/MysqlSessionHandler.php index 810c598..65e3fc0 100644 --- a/src/MysqlSessionHandler.php +++ b/src/MysqlSessionHandler.php @@ -18,35 +18,30 @@ class MysqlSessionHandler implements SessionHandlerInterface use SmartObject; - /** @var string */ - private $tableName; - /** @var integer */ - private $lockTimeout = 5; + private Context $context; - /** @var integer */ - private $unchangedUpdateDelay = 300; + private ?StaticKeyEncryption $encryptionService = null; - /** @var Context */ - private $context; + private string $tableName; - /** @var string */ - private $lockId; + private int $lockTimeout = 5; + + private int $unchangedUpdateDelay = 300; + + private ?string $lockId = null; /** @var string[] */ - private $idHashes = []; + private array $idHashes = []; - /** @var ActiveRow */ - private $row; + /** @var ActiveRow{data:string, timestamp:int}|null */ + private ?ActiveRow $row; /** @var string[] */ - private $data = []; + private array $data = []; /** @var mixed[] */ - private $additionalData = []; - - /** @var StaticKeyEncryption */ - private $encryptionService; + private array $additionalData = []; /** * Occurs before the data is written to session. @@ -108,8 +103,11 @@ private function hash(string $id, bool $rawOutput = true): string private function lock(): void { if ($this->lockId === null) { - $this->lockId = $this->hash(\session_id(), false); - $this->context->query('SELECT GET_LOCK(?, ?) as `lock`', $this->lockId, $this->lockTimeout); + $sessionId = \session_id(); + if ($sessionId) { + $this->lockId = $this->hash($sessionId, false); + $this->context->query('SELECT GET_LOCK(?, ?) as `lock`', $this->lockId, $this->lockTimeout); + } } } @@ -128,7 +126,7 @@ private function unlock(): void /** * @param string $savePath * @param string $name - * @return boolean + * @return bool */ public function open($savePath, $name): bool { @@ -146,7 +144,7 @@ public function close(): bool /** * @param string $sessionId - * @return boolean + * @return bool */ public function destroy($sessionId): bool { @@ -178,7 +176,7 @@ public function read($sessionId): string /** * @param string $sessionId * @param string $sessionData - * @return boolean + * @return bool */ public function write($sessionId, $sessionData): bool { @@ -191,7 +189,8 @@ public function write($sessionId, $sessionData): bool $sessionData = $this->encryptionService->encrypt($sessionData); } $this->onBeforeDataWrite(); - if ($row = $this->context->table($this->tableName)->get($hashedSessionId)) { + $row = $this->context->table($this->tableName)->get($hashedSessionId); + if ($row) { $row->update([ 'timestamp' => $time, 'data' => $sessionData, @@ -203,7 +202,7 @@ public function write($sessionId, $sessionData): bool 'data' => $sessionData, ] + $this->additionalData); } - } elseif ($this->unchangedUpdateDelay === 0 || $time - $this->row->timestamp > $this->unchangedUpdateDelay) { + } elseif (($this->unchangedUpdateDelay === 0 || $time - $this->row->timestamp > $this->unchangedUpdateDelay) && $this->row) { // Optimization: When data has not been changed, only update // the timestamp after a configured delay, if any. $this->row->update([ @@ -216,8 +215,8 @@ public function write($sessionId, $sessionData): bool /** - * @param integer $maxLifeTime - * @return boolean + * @param int $maxLifeTime + * @return bool */ public function gc($maxLifeTime): bool {