[Session] Fixes, cleanup, docs, tests
This commit is contained in:
parent
c58814ab64
commit
a4bc626fae
@ -7,29 +7,55 @@ use Ratchet\Component\Session\Serialize\HandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
|
||||
|
||||
/**
|
||||
* This component will allow access to session data from your website for each user connected
|
||||
* Symfony HttpFoundation is required for this component to work
|
||||
* Your website must also use Symfony HttpFoundation Sessions to read your sites session data
|
||||
* If your are not using at least PHP 5.4 you must include a SessionHandlerInterface stub (is included in Symfony HttpFoundation, loaded w/ composer)
|
||||
*/
|
||||
class SessionComponent implements MessageComponentInterface {
|
||||
/**
|
||||
* @var Ratchet\Component\MessageComponentInterface
|
||||
*/
|
||||
protected $_app;
|
||||
|
||||
protected $_options;
|
||||
/**
|
||||
* Selected handler storage assigned by the developer
|
||||
* @var SessionHandlerInterface
|
||||
*/
|
||||
protected $_handler;
|
||||
|
||||
/**
|
||||
* Null storage handler if no previous session was found
|
||||
* @var SessionHandlerInterface
|
||||
*/
|
||||
protected $_null;
|
||||
|
||||
/**
|
||||
* @var Ratchet\Component\Session\Serialize\HandlerInterface
|
||||
*/
|
||||
protected $_serializer;
|
||||
|
||||
/**
|
||||
* @param Ratchet\Component\MessageComponentInterface
|
||||
* @param SessionHandlerInterface
|
||||
* @param array
|
||||
* @param Ratchet\Component\Session\Serialize\HandlerInterface
|
||||
* @throws RuntimeException If unable to match serialization methods
|
||||
*/
|
||||
public function __construct(MessageComponentInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) {
|
||||
$this->_app = $app;
|
||||
$this->_handler = $handler;
|
||||
$this->_options = array();
|
||||
$this->_null = new NullSessionHandler;
|
||||
|
||||
ini_set('session.auto_start', 0);
|
||||
ini_set('session.cache_limiter', '');
|
||||
ini_set('session.use_cookies', 0);
|
||||
|
||||
$options = $this->setOptions($options);
|
||||
$this->setOptions($options);
|
||||
|
||||
if (null === $serializer) {
|
||||
$serialClass = __NAMESPACE__ . '\\Serialize\\' . str_replace(' ', '', ucwords(str_replace('_', ' ', ini_get('session.serialize_handler')))) . 'Handler'; // awesome/terrible hack, eh?
|
||||
$serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh?
|
||||
if (!class_exists($serialClass)) {
|
||||
throw new \RuntimeExcpetion('Unable to parse session serialize handler');
|
||||
}
|
||||
@ -44,7 +70,7 @@ class SessionComponent implements MessageComponentInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onOpen(ConnectionInterface $conn) {
|
||||
if (null === ($id = $conn->WebSocket->headers->getCookie($this->_options['name']))) {
|
||||
if (null === ($id = $conn->WebSocket->headers->getCookie(ini_get('session.name')))) {
|
||||
$saveHandler = $this->_null;
|
||||
$id = '';
|
||||
} else {
|
||||
@ -53,6 +79,10 @@ class SessionComponent implements MessageComponentInterface {
|
||||
|
||||
$conn->Session = new Session(new VirtualSessionStorage($saveHandler, $id, $this->_serializer));
|
||||
|
||||
if (ini_get('session.auto_start')) {
|
||||
$conn->Session->start();
|
||||
}
|
||||
|
||||
return $this->_app->onOpen($conn);
|
||||
}
|
||||
|
||||
@ -79,6 +109,12 @@ class SessionComponent implements MessageComponentInterface {
|
||||
return $this->_app->onError($conn, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all the php session. ini options
|
||||
* © Symfony
|
||||
* @param array
|
||||
* @return array
|
||||
*/
|
||||
protected function setOptions(array $options) {
|
||||
$all = array(
|
||||
'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
|
||||
@ -102,4 +138,12 @@ class SessionComponent implements MessageComponentInterface {
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string Input to convert
|
||||
* @return string
|
||||
*/
|
||||
protected function toClassCase($langDef) {
|
||||
return str_replace(' ', '', ucwords(str_replace('_', ' ', $langDef)));
|
||||
}
|
||||
}
|
@ -11,7 +11,9 @@ class VirtualSessionStorage extends NativeSessionStorage {
|
||||
protected $_serializer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @param SessionHandlerInterface
|
||||
* @param string The ID of the session to retreive
|
||||
* @param Ratchet\Component\Session\Serialize\HandlerInterface
|
||||
*/
|
||||
public function __construct(\SessionHandlerInterface $handler, $sessionId, HandlerInterface $serializer) {
|
||||
$this->setSaveHandler($handler);
|
||||
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Component\Session\Serialize;
|
||||
use Ratchet\Component\Session\Serialize\PhpHandler;
|
||||
|
||||
/**
|
||||
* @covers Ratchet\Component\Session\Serialize\PhpHandler
|
||||
*/
|
||||
class PhpHandlerTest extends \PHPUnit_Framework_TestCase {
|
||||
protected $_handler;
|
||||
|
||||
public function setUp() {
|
||||
$this->_handler = new PhpHandler;
|
||||
}
|
||||
|
||||
public function serializedProvider() {
|
||||
return array(
|
||||
array(
|
||||
'_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}'
|
||||
, array(
|
||||
'_sf2_attributes' => array(
|
||||
'hello' => 'world'
|
||||
, 'last' => 1332872102
|
||||
)
|
||||
, '_sf2_flashes' => array()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider serializedProvider
|
||||
*/
|
||||
public function testUnserialize($in, $expected) {
|
||||
$this->assertEquals($expected, $this->_handler->unserialize($in));
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Component\Session;
|
||||
use Ratchet\Component\Session\SessionComponent;
|
||||
use Ratchet\Tests\Mock\NullMessageComponent;
|
||||
use Ratchet\Tests\Mock\MemorySessionHandler;
|
||||
|
||||
/**
|
||||
* @covers Ratchet\Component\Session\SessionComponent
|
||||
*/
|
||||
class SessionComponentTest extends \PHPUnit_Framework_TestCase {
|
||||
protected $_app;
|
||||
|
||||
public function setUp() {
|
||||
// $this->app = new SessionComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkSymfonyPresent() {
|
||||
return class_exists('Symfony\\Component\\HttpFoundation\\Session\\Session');
|
||||
}
|
||||
|
||||
public function classCaseProvider() {
|
||||
return array(
|
||||
array('php', 'Php')
|
||||
, array('php_binary', 'PhpBinary')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider classCaseProvider
|
||||
*/
|
||||
public function testToClassCase($in, $out) {
|
||||
if (!interface_exists('SessionHandlerInterface')) {
|
||||
return $this->markTestSkipped('SessionHandlerInterface not defined. Requires PHP 5.4 or Symfony HttpFoundation');
|
||||
}
|
||||
|
||||
$ref = new \ReflectionClass('\\Ratchet\\Component\\Session\\SessionComponent');
|
||||
$method = $ref->getMethod('toClassCase');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$component = new SessionComponent(new NullMessageComponent, new MemorySessionHandler);
|
||||
$this->assertEquals($out, $method->invokeArgs($component, array($in)));
|
||||
}
|
||||
|
||||
/* Put this in test methods that require Symfony
|
||||
if (false === $this->checkSymfonyPresent()) {
|
||||
return $this->markTestSkipped('Symfony HttpFoundation not loaded');
|
||||
}
|
||||
*/
|
||||
}
|
39
tests/Ratchet/Tests/Mock/MemorySessionHandler.php
Normal file
39
tests/Ratchet/Tests/Mock/MemorySessionHandler.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Mock;
|
||||
|
||||
class MemorySessionHandler implements \SessionHandlerInterface {
|
||||
protected $_sessions = array();
|
||||
|
||||
public function close() {
|
||||
}
|
||||
|
||||
public function destroy($session_id) {
|
||||
if (isset($this->_sessions[$session_id])) {
|
||||
unset($this->_sessions[$session_id]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function gc($maxlifetime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function open($save_path, $session_id) {
|
||||
if (!isset($this->_sessions[$session_id])) {
|
||||
$this->_sessions[$session_id] = '';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function read($session_id) {
|
||||
return $this->_sessions[$session_id];
|
||||
}
|
||||
|
||||
public function write($session_id, $session_data) {
|
||||
$this->_sessions[$session_id] = $session_data;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
55
tests/Ratchet/Tests/Mock/NullMessageComponent.php
Normal file
55
tests/Ratchet/Tests/Mock/NullMessageComponent.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Mock;
|
||||
use Ratchet\Component\MessageComponentInterface;
|
||||
use Ratchet\Resource\ConnectionInterface;
|
||||
|
||||
class NullMessageComponent implements MessageComponentInterface {
|
||||
/**
|
||||
* @var SplObjectStorage
|
||||
*/
|
||||
public $connections;
|
||||
|
||||
/**
|
||||
* @var SplQueue
|
||||
*/
|
||||
public $messageHistory;
|
||||
|
||||
/**
|
||||
* @var SplQueue
|
||||
*/
|
||||
public $errorHistory;
|
||||
|
||||
public function __construct() {
|
||||
$this->connections = new \SplObjectStorage;
|
||||
$this->messageHistory = new \SplQueue;
|
||||
$this->errorHistory = new \SplQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onOpen(ConnectionInterface $conn) {
|
||||
$this->connections->attach($conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onMessage(ConnectionInterface $from, $msg) {
|
||||
$this->messageHistory->enqueue(array('from' => $from, 'msg' => $msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onClose(ConnectionInterface $conn) {
|
||||
$this->connections->detach($conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function onError(ConnectionInterface $conn, \Exception $e) {
|
||||
$this->errorHistory->enqueue(array('conn' => $conn, 'exception' => $e));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user