Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
"license": "MIT",

"require": {
"php": ">=7.2"
"php": ">=8.0",
"phpgt/typesafegetter": "^v1.2"
},
"require-dev": {
"phpunit/phpunit": "9.*",
"phpstan/phpstan": "1.0.2"
"phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^v1.4"
},

"autoload": {
Expand Down
216 changes: 133 additions & 83 deletions composer.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions src/FileHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class FileHandler extends Handler {
* @param string $save_path The path where to store/retrieve the session.
* @param string $name The session name.
*/
public function open($save_path, $name):bool {
public function open(string $save_path, string $name):bool {
$success = true;

$save_path = str_replace(
Expand Down Expand Up @@ -45,7 +45,7 @@ public function close():bool {
* @link http://php.net/manual/en/sessionhandlerinterface.read.php
* @param string $session_id
*/
public function read($session_id):string {
public function read(string $session_id):string {
if(isset($this->cache[$session_id])) {
return $this->cache[$session_id];
}
Expand All @@ -65,7 +65,7 @@ public function read($session_id):string {
* @param string $session_id
* @param string $session_data
*/
public function write($session_id, $session_data):bool {
public function write(string $session_id, string $session_data):bool {
if($session_data === self::EMPTY_PHP_ARRAY) {
return true;
}
Expand All @@ -76,10 +76,10 @@ public function write($session_id, $session_data):bool {

/**
* @link http://php.net/manual/en/sessionhandlerinterface.destroy.php
* @param string $session_id
* @param string $id
*/
public function destroy($session_id):bool {
$filePath = $this->getFilePath($session_id);
public function destroy($id):bool {
$filePath = $this->getFilePath($id);

if(file_exists($filePath)) {
return unlink($filePath);
Expand Down
16 changes: 8 additions & 8 deletions src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@ abstract public function close():bool;

/**
* @link http://php.net/manual/en/sessionhandlerinterface.destroy.php
* @param string $session_id
* @param string $id
*/
abstract public function destroy($session_id);
abstract public function destroy(string $id = ""):bool;

/**
* @link http://php.net/manual/en/sessionhandlerinterface.gc.php
* @param int $maxlifetime
* @param int $max_lifetime
*/
abstract public function gc($maxlifetime):bool;
abstract public function gc(int $max_lifetime):int|false;

/**
* @link http://php.net/manual/en/sessionhandlerinterface.open.php
* @param string $save_path The path where to store/retrieve the session.
* @param string $name The session name.
*/
abstract public function open($save_path, $name):bool;
abstract public function open(string $save_path, string $name):bool;

/**
* @link http://php.net/manual/en/sessionhandlerinterface.read.php
* @param string $session_id
*/
abstract public function read($session_id):string;
abstract public function read(string $session_id):string;

/**
* @link http://php.net/manual/en/sessionhandlerinterface.write.php
* @param string $session_id
* @param string $session_data
*/
abstract public function write($session_id, $session_data):bool;
}
abstract public function write(string $session_id, string $session_data):bool;
}
40 changes: 23 additions & 17 deletions src/Session.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<?php
namespace Gt\Session;

use DateTimeInterface;
use Gt\TypeSafeGetter\NullableTypeSafeGetter;
use Gt\TypeSafeGetter\TypeSafeGetter;
use SessionHandlerInterface;

class Session implements SessionContainer {
class Session implements SessionContainer, TypeSafeGetter {
use NullableTypeSafeGetter;

const DEFAULT_SESSION_NAME = "PHPSESSID";
const DEFAULT_SESSION_LIFETIME = 0;
const DEFAULT_SESSION_PATH = "/tmp";
Expand Down Expand Up @@ -37,21 +42,23 @@ public function __construct(
);
$sessionName = $config["name"] ?? self::DEFAULT_SESSION_NAME;

$success = session_start([
"save_path" => $sessionPath,
"name" => $sessionName,
"serialize_handler" => "php_serialize",
"cookie_lifetime" => $config["cookie_lifetime"] ?? self::DEFAULT_SESSION_LIFETIME,
"cookie_path" => $config["cookie_path"] ?? self::DEFAULT_COOKIE_PATH,
"cookie_domain" => $config["cookie_domain"] ?? self::DEFAULT_SESSION_DOMAIN,
"cookie_secure" => $config["cookie_secure"] ?? self::DEFAULT_SESSION_SECURE,
"cookie_httponly" => $config["cookie_httponly"] ?? self::DEFAULT_SESSION_HTTPONLY,
]);

if(!$success) {
// TODO: Throw exception after #131 investigated.
var_dump($sessionPath, $sessionName, $this->id);die("Session starting failed");
do {
$success = session_start([
"save_path" => $sessionPath,
"name" => $sessionName,
"serialize_handler" => "php_serialize",
"cookie_lifetime" => $config["cookie_lifetime"] ?? self::DEFAULT_SESSION_LIFETIME,
"cookie_path" => $config["cookie_path"] ?? self::DEFAULT_COOKIE_PATH,
"cookie_domain" => $config["cookie_domain"] ?? self::DEFAULT_SESSION_DOMAIN,
"cookie_secure" => $config["cookie_secure"] ?? self::DEFAULT_SESSION_SECURE,
"cookie_httponly" => $config["cookie_httponly"] ?? self::DEFAULT_SESSION_HTTPONLY,
]);

if(!$success) {
session_destroy();
}
}
while(!$success);

$this->sessionHandler->open($sessionPath, $sessionName);
$this->store = $this->readSessionData() ?: null;
Expand Down Expand Up @@ -84,10 +91,9 @@ public function getStore(
);
}

public function get(string $key) {
public function get(string $key):mixed {
return $this->store->get($key);
}

public function set(string $key, $value):void {
$this->store->set($key, $value);
}
Expand Down
15 changes: 11 additions & 4 deletions src/SessionStore.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<?php
namespace Gt\Session;

class SessionStore implements SessionContainer {
use DateTime;
use DateTimeInterface;
use Gt\TypeSafeGetter\NullableTypeSafeGetter;
use Gt\TypeSafeGetter\TypeSafeGetter;

class SessionStore implements SessionContainer, TypeSafeGetter {
use NullableTypeSafeGetter;

/** @var string */
protected $name;
/** @var Session */
Expand All @@ -25,7 +32,7 @@ public function __construct(
$this->data = [];
}

public function setData(string $key, $value):void {
public function setData(string $key, mixed $value):void {
$this->data[$key] = $value;
}

Expand Down Expand Up @@ -117,7 +124,7 @@ public function createStore(string $namespace):SessionStore {
return $this->getStore($namespace);
}

public function get(string $key) {
public function get(string $key):mixed {
$store = $this;
$lastDotPosition = strrpos($key, ".");

Expand Down Expand Up @@ -220,4 +227,4 @@ protected function getNamespaceFromKey(string $key):?string {

return substr($key, 0, $lastDotPostition);
}
}
}
4 changes: 2 additions & 2 deletions test/phpunit/Helper/FunctionOverride/session_start.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
function session_start() {
FunctionMocker::$mockCalls["session_start"] []= func_get_args();

if(FunctionMocker::$callState["session_start__fail"]) {
if(isset(FunctionMocker::$callState["session_start__fail"])) {
return false;
}

return true;
}
}
55 changes: 54 additions & 1 deletion test/phpunit/SessionStoreTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Gt\Session\Test;

use DateTime;
use Gt\Session\Handler;
use Gt\Session\Session;
use Gt\Session\SessionStore;
Expand Down Expand Up @@ -81,4 +82,56 @@ public function testGetCreatesNonExistantStore() {

self::assertNotNull($leafStore);
}
}

public function testGetString():void {
$session = $this->createMock(Session::class);
$sut = new SessionStore("test", $session);

$numericValue = rand(1000, 9999);
$sut->set("test.value", $numericValue);

self::assertSame((string)$numericValue, $sut->getString("test.value"));
}

public function testGetInt():void {
$session = $this->createMock(Session::class);
$sut = new SessionStore("test", $session);

$numericStringValue = (string)rand(1000, 9999);
$sut->set("test.value", $numericStringValue);

self::assertSame((int)$numericStringValue, $sut->getInt("test.value"));
}

public function testGetFloat():void {
$session = $this->createMock(Session::class);
$sut = new SessionStore("test", $session);

$numericStringValue = (string)(rand(1000, 9999) - 0.105);
$sut->set("test.value", $numericStringValue);

self::assertSame((float)$numericStringValue, $sut->getFloat("test.value"));
}

public function testGetBool():void {
$session = $this->createMock(Session::class);
$sut = new SessionStore("test", $session);

$numericValue = rand(0, 1);
$sut->set("test.value", $numericValue);

self::assertSame((bool)$numericValue, $sut->getBool("test.value"));
}

public function testGetDateTime():void {
$session = $this->createMock(Session::class);
$sut = new SessionStore("test", $session);

$numericValue = time();
$sut->set("test.value", $numericValue);

$dateTime = new DateTime();
$dateTime->setTimestamp($numericValue);
self::assertEquals($dateTime, $sut->getDateTime("test.value"));
}
}
65 changes: 64 additions & 1 deletion test/phpunit/SessionTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Gt\Session\Test;

use DateTime;
use Gt\Session\Handler;
use Gt\Session\Session;
use Gt\Session\Test\Helper\DataProvider\ConfigProvider;
Expand Down Expand Up @@ -464,4 +465,66 @@ public function testRemoveSiblingNamespace(array $keyValuePairs) {
);
}
}
}

public function testGetString():void {
/** @var Handler|MockObject $handler */
$handler = $this->getMockBuilder(Handler::class)
->getMock();
$sut = new Session($handler);

$numericValue = rand(1000, 9999);
$sut->set("test.value", $numericValue);

self::assertSame((string)$numericValue, $sut->getString("test.value"));
}

public function testGetInt():void {
/** @var Handler|MockObject $handler */
$handler = $this->getMockBuilder(Handler::class)
->getMock();
$sut = new Session($handler);

$numericStringValue = (string)rand(1000, 9999);
$sut->set("test.value", $numericStringValue);

self::assertSame((int)$numericStringValue, $sut->getInt("test.value"));
}

public function testGetFloat():void {
/** @var Handler|MockObject $handler */
$handler = $this->getMockBuilder(Handler::class)
->getMock();
$sut = new Session($handler);

$numericStringValue = (string)(rand(1000, 9999) - 0.105);
$sut->set("test.value", $numericStringValue);

self::assertSame((float)$numericStringValue, $sut->getFloat("test.value"));
}

public function testGetBool():void {
/** @var Handler|MockObject $handler */
$handler = $this->getMockBuilder(Handler::class)
->getMock();
$sut = new Session($handler);

$numericValue = rand(0, 1);
$sut->set("test.value", $numericValue);

self::assertSame((bool)$numericValue, $sut->getBool("test.value"));
}

public function testGetDateTime():void {
/** @var Handler|MockObject $handler */
$handler = $this->getMockBuilder(Handler::class)
->getMock();
$sut = new Session($handler);

$numericValue = time();
$sut->set("test.value", $numericValue);

$dateTime = new DateTime();
$dateTime->setTimestamp($numericValue);
self::assertEquals($dateTime, $sut->getDateTime("test.value"));
}
}