Skip to content

Commit

Permalink
Implement & test core Session functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
g105b committed Dec 18, 2014
1 parent 85d1a70 commit caf11ad
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 57 deletions.
117 changes: 73 additions & 44 deletions src/Session/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ class Session {
private $config;
private $store;

const DATA_GET = "data_get";
const DATA_SET = "data_set";

const STATUS_ACTIVE = PHP_SESSION_ACTIVE;
const STATUS_INACTIVE = PHP_SESSION_DISABLED;

public function __construct($config) {
$this->config = $config;

Expand All @@ -24,87 +30,110 @@ public function __construct($config) {
$this->store = $_SESSION[$this->config->base_namespace];
}

public function getStatus() {
return session_status();
}

public function setConfig($config) {
$this->config = $config;
}

/**
*
*/
public function get($key) {
return $this->store[$key];
$nsArray = $this->getNamespaceArray($key);
$data = $this->data(self::DATA_GET, $this->store, $nsArray);

return $data;
}

/**
*
*/
public function exists($key) {
return isset($this->store[$key]);
public function set($key, $value) {
$nsArray = $this->getNamespaceArray($key);
return $this->data(self::DATA_SET, $this->store, $nsArray, $value);
}

/**
* Recursive function to iterate through nested Store objects, returning the
* most nested (leaf) value. Set $value to SOMETHING to retrieve the value in
* the nested Store rather than setting it.
*
* @param Store $store The root Store to iterate upon
* @param array $nsArray Array of namespace key names
* @param mixed $value The value to set the leaf Store to
* @param mixed $return The value of the current iteration, used to exit from
* the recursive iteration
*
* @return mixed The value contained by the leaf Store
*/
public function set($key, $value) {
$this->store[$key] = $value;
private function data($direction, $store, $nsArray,
$value = null, $return = null) {
if(empty($nsArray)) {
return $return;
}

$getKey = array_shift($nsArray);
if(!isset($store[$getKey])) {
if($direction === self::DATA_GET) {
throw new SessionStoreNotFoundException($getKey);
}
else if($direction === self::DATA_SET) {


if(empty($nsArray)) {
$store[$getKey] = $value;
}
else {
$store[$getKey] = new Store($this->config);
}
}
}

return $this->data(
$direction,
$store[$getKey],
$nsArray,
$value,
$store[$getKey]
);
}

/**
*
*/
public function delete($key) {
unset($this->store[$key]);
public function exists($key) {
$key = $this->fixCase($key);
return isset($this->store[$key]);
}

/**
*
*/
private function fixCase($key) {
if(!$config->case_sensitive) {
return strtoupper($key);
}

return $key;
public function delete($key) {
$key = $this->fixCase($key);
unset($this->store[$key]);
}

/**
*
*/
private function getNamespaceArray($string) {
$nsArray = array();

if(is_string($ns)) {
$nsArray = explode(".", $ns);
}
else if(is_array($ns)) {
$nsArray = $ns;
}
else {
// TODO: throw exception
die("getNsArray error!!!");
private function fixCase($key) {
if(!$this->config->case_sensitive) {
return strtoupper($key);
}

return $nsArray;
return $key;
}

/**
* Initialises a nested array and returns reference to the deepest (the leaf).
*
* @param array $arrayContainer description
*/
private function initLeaf(&$arrayContainer, $nsToInit, &$leaf = null) {
if(empty($nsToInit)) {
return $leaf;
}

$initKey = array_shift($nsToInit);

if(!isset($arrayContainer[$initKey])) {
$arrayContainer[$initKey] = array();
}

return self::initLeaf(
$arrayContainer[$initKey],
$nsToInit,
$arrayContainer[$initKey]
);
private function getNamespaceArray($key) {
$key = $this->fixCase($key);
return explode($this->config->separator, $key);
}

}#
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
<?php
/**
* Thrown if a key is requested from the Session that does not exist.
*
* PHP.Gt (http://php.gt)
* @copyright Copyright Ⓒ 2014 Bright Flair Ltd. (http://brightflair.com)
* @license Apache Version 2.0, January 2004. http://www.apache.org/licenses
*/
namespace Gt\Session;

class StoreValue {

public function __construct() {
}

}#
class SessionStoreNotFoundException extends \Gt\Core\Exception\GtException {}#
13 changes: 6 additions & 7 deletions src/Session/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
/**
* Represents a branch of a session namespace.
* Session storage Shop.Basket.Intl.value has three stores (Shop that contains
* Basket, that in turn contains Intl, that in turn contains the StoreValue
* represented by value).
* Basket, that in turn contains Intl, that in turn contains the key "value").
*
* PHP.Gt (http://php.gt)
* @copyright Copyright Ⓒ 2014 Bright Flair Ltd. (http://brightflair.com)
Expand All @@ -13,23 +12,23 @@

class Store implements \ArrayAccess {

private $tempStorage = [];
private $storage = [];

public function __construct($config) {
$this->caseSensitive = $config->case_sensitive;
}

public function offsetExists($key) {
return isset($this->tempStorage[$key]);
return array_key_exists($key, $this->storage);
}
public function offsetGet($key) {
return $this->tempStorage[$key];
return $this->storage[$key];
}
public function offsetSet($key, $value) {
$this->tempStorage[$key] = $value;
$this->storage[$key] = $value;
}
public function offsetUnset($key) {
unset($this->tempStorage[$key]);
unset($this->storage[$key]);
}

}#
81 changes: 81 additions & 0 deletions test/Unit/Session/Session.test.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,89 @@

class Session_Test extends \PHPUnit_Framework_TestCase {

private $cfg;
private $session;

public function setUp() {
$this->cfg = new \Gt\Core\ConfigObj([
"case_sensitive" => false,
"separator" => ".",
"base_namespace" => "TestApp",
]);
$this->session = new Session($this->cfg);
}

public function testSessionStarts() {
$this->assertEquals(Session::STATUS_ACTIVE, $this->session->getStatus());
}

public function testSessionCreatesObject() {
$this->assertArrayHasKey("TestApp", $_SESSION,
'Namespace should exist in session');
$this->assertInstanceOf("\Gt\Session\Store", $_SESSION["TestApp"]);
}

public function testAddsSingleStore() {
$key = "TestKey";
$value = "TestValue";
$this->assertFalse($this->session->exists($key));
$this->session->set($key, $value);
$this->assertTrue($this->session->exists($key));
$this->assertEquals($this->session->get($key), $value);
}

public function testDeletesStore() {
$key = "TestKey";
$value = "TestValue";
$this->assertFalse($this->session->exists($key));
$this->session->set($key, $value);
$this->session->delete($key);
$this->assertFalse($this->session->exists($key));
}

public function testCaseSensitivity() {
$key = "TestKey";
$keyCi = strtolower($key);
$value = "TestValue";

$cfgCS = new \Gt\Core\ConfigObj([
"case_sensitive" => true,
"separator" => ".",
"base_namespace" => "TestApp",
]);

$this->session->set($key, $value);
$this->assertEquals($this->session->get($keyCi), $value);

$this->session->setConfig($cfgCS);
$this->assertFalse($this->session->exists($keyCi));
}

public function testNamespace() {
$namespace = "Shop.Basket.items";
$itemArray = ["beer", "wine", "cheese"];

$this->session->set($namespace, $itemArray);
$this->assertEquals(
$this->session->get($namespace),
$itemArray
);

$this->assertInstanceOf("\Gt\Session\Store",
$this->session->get("Shop.Basket"));
}

public function testStoringNullValue() {
$namespace = "A.Test.Namespace.thing";
$this->session->set($namespace, null);
$this->assertNull($this->session->get($namespace));
}

/**
* @expectedException \Gt\Session\SessionStoreNotFoundException
*/
public function testInvalidGet() {
$this->session->get("This.Namespace.Does.Not.Exist");
}

}#

0 comments on commit caf11ad

Please sign in to comment.