merged branch drak/session_detect (PR #7571)
This PR was squashed before being merged into the master branch (closes #7571).
Discussion
----------
[2.3] Handle PHP sessions started outside of Symfony
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets |
| License | MIT
| Doc PR | symfony/symfony-docs#2474
This PR brings a way to allow Symfony2 to manage a session started outside of Symfony in such a way that quite explicit. It also introduces more robust detection of previously started sessions under PHP 5.3 and supports real session status detection under PHP 5.4
Commits
-------
df99902
[2.3] Handle PHP sessions started outside of Symfony
This commit is contained in:
commit
7bf8933662
@ -318,6 +318,7 @@ class FrameworkExtension extends Extension
|
|||||||
if (null == $config['handler_id']) {
|
if (null == $config['handler_id']) {
|
||||||
// Set the handler class to be null
|
// Set the handler class to be null
|
||||||
$container->getDefinition('session.storage.native')->replaceArgument(1, null);
|
$container->getDefinition('session.storage.native')->replaceArgument(1, null);
|
||||||
|
$container->getDefinition('session.storage.php_bridge')->replaceArgument(1, null);
|
||||||
} else {
|
} else {
|
||||||
$container->setAlias('session.handler', $config['handler_id']);
|
$container->setAlias('session.handler', $config['handler_id']);
|
||||||
}
|
}
|
||||||
@ -327,6 +328,7 @@ class FrameworkExtension extends Extension
|
|||||||
$this->addClassesToCompile(array(
|
$this->addClassesToCompile(array(
|
||||||
'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
|
'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
|
||||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
|
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
|
||||||
|
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage',
|
||||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler',
|
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler',
|
||||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
|
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
|
||||||
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy',
|
'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy',
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<parameter key="session.flashbag.class">Symfony\Component\HttpFoundation\Session\Flash\FlashBag</parameter>
|
<parameter key="session.flashbag.class">Symfony\Component\HttpFoundation\Session\Flash\FlashBag</parameter>
|
||||||
<parameter key="session.attribute_bag.class">Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag</parameter>
|
<parameter key="session.attribute_bag.class">Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag</parameter>
|
||||||
<parameter key="session.storage.native.class">Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage</parameter>
|
<parameter key="session.storage.native.class">Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage</parameter>
|
||||||
|
<parameter key="session.storage.php_bridge.class">Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage</parameter>
|
||||||
<parameter key="session.storage.mock_file.class">Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage</parameter>
|
<parameter key="session.storage.mock_file.class">Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage</parameter>
|
||||||
<parameter key="session.handler.native_file.class">Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler</parameter>
|
<parameter key="session.handler.native_file.class">Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler</parameter>
|
||||||
<parameter key="session_listener.class">Symfony\Bundle\FrameworkBundle\EventListener\SessionListener</parameter>
|
<parameter key="session_listener.class">Symfony\Bundle\FrameworkBundle\EventListener\SessionListener</parameter>
|
||||||
@ -26,6 +27,10 @@
|
|||||||
<argument type="service" id="session.handler" />
|
<argument type="service" id="session.handler" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="session.storage.php_bridge" class="%session.storage.php_bridge.class%">
|
||||||
|
<argument type="service" id="session.handler" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="session.flash_bag" class="%session.flashbag.class%" public="false" />
|
<service id="session.flash_bag" class="%session.flashbag.class%" public="false" />
|
||||||
|
|
||||||
<service id="session.attribute_bag" class="%session.attribute_bag.class%" public="false" />
|
<service id="session.attribute_bag" class="%session.attribute_bag.class%" public="false" />
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
|
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||||
@ -92,7 +93,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
|
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
|
||||||
*
|
*
|
||||||
* @param array $options Session configuration options.
|
* @param array $options Session configuration options.
|
||||||
* @param object $handler SessionHandlerInterface.
|
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
|
||||||
* @param MetadataBag $metaBag MetadataBag.
|
* @param MetadataBag $metaBag MetadataBag.
|
||||||
*/
|
*/
|
||||||
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
|
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
|
||||||
@ -130,27 +131,28 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch condition where session was started automatically by PHP
|
if (version_compare(phpversion(), '5.4.0', '>=') && \PHP_SESSION_ACTIVE === session_status()) {
|
||||||
if (!$this->started && !$this->closed && $this->saveHandler->isActive()
|
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
||||||
&& $this->saveHandler->isSessionHandlerInterface()) {
|
}
|
||||||
$this->loadSession();
|
|
||||||
|
|
||||||
return true;
|
if (version_compare(phpversion(), '5.4.0', '<') && isset($_SESSION) && session_id()) {
|
||||||
|
// not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3
|
||||||
|
throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ini_get('session.use_cookies') && headers_sent()) {
|
if (ini_get('session.use_cookies') && headers_sent()) {
|
||||||
throw new \RuntimeException('Failed to start the session because headers have already been sent.');
|
throw new \RuntimeException('Failed to start the session because headers have already been sent.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the session
|
// ok to try and start the session
|
||||||
if (!session_start()) {
|
if (!session_start()) {
|
||||||
throw new \RuntimeException('Failed to start the session');
|
throw new \RuntimeException('Failed to start the session');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->loadSession();
|
$this->loadSession();
|
||||||
|
|
||||||
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||||
$this->saveHandler->setActive(false);
|
// This condition matches only PHP 5.3 with internal save handlers
|
||||||
|
$this->saveHandler->setActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -215,7 +217,8 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
{
|
{
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
|
||||||
if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
|
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||||
|
// This condition matches only PHP 5.3 with internal save handlers
|
||||||
$this->saveHandler->setActive(false);
|
$this->saveHandler->setActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +332,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers save handler as a PHP session handler.
|
* Registers session save handler as a PHP session handler.
|
||||||
*
|
*
|
||||||
* To use internal PHP session save handlers, override this method using ini_set with
|
* To use internal PHP session save handlers, override this method using ini_set with
|
||||||
* session.save_handler and session.save_path e.g.
|
* session.save_handler and session.save_path e.g.
|
||||||
@ -337,21 +340,35 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
* ini_set('session.save_handler', 'files');
|
* ini_set('session.save_handler', 'files');
|
||||||
* ini_set('session.save_path', /tmp');
|
* ini_set('session.save_path', /tmp');
|
||||||
*
|
*
|
||||||
|
* or pass in a NativeSessionHandler instance which configures session.save_handler in the
|
||||||
|
* constructor, for a template see NativeFileSessionHandler or use handlers in
|
||||||
|
* composer package drak/native-session
|
||||||
|
*
|
||||||
* @see http://php.net/session-set-save-handler
|
* @see http://php.net/session-set-save-handler
|
||||||
* @see http://php.net/sessionhandlerinterface
|
* @see http://php.net/sessionhandlerinterface
|
||||||
* @see http://php.net/sessionhandler
|
* @see http://php.net/sessionhandler
|
||||||
|
* @see http://github.com/drak/NativeSession
|
||||||
*
|
*
|
||||||
* @param object $saveHandler Default null means NativeProxy.
|
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function setSaveHandler($saveHandler = null)
|
public function setSaveHandler($saveHandler = null)
|
||||||
{
|
{
|
||||||
// Wrap $saveHandler in proxy
|
if (!$saveHandler instanceof AbstractProxy &&
|
||||||
|
!$saveHandler instanceof NativeSessionHandler &&
|
||||||
|
!$saveHandler instanceof \SessionHandlerInterface &&
|
||||||
|
null !== $saveHandler) {
|
||||||
|
throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap $saveHandler in proxy and prevent double wrapping of proxy
|
||||||
if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
|
if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
|
||||||
$saveHandler = new SessionHandlerProxy($saveHandler);
|
$saveHandler = new SessionHandlerProxy($saveHandler);
|
||||||
} elseif (!$saveHandler instanceof AbstractProxy) {
|
} elseif (!$saveHandler instanceof AbstractProxy) {
|
||||||
$saveHandler = new NativeProxy();
|
$saveHandler = version_compare(phpversion(), '5.4.0', '>=') ?
|
||||||
|
new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->saveHandler = $saveHandler;
|
$this->saveHandler = $saveHandler;
|
||||||
|
|
||||||
if ($this->saveHandler instanceof \SessionHandlerInterface) {
|
if ($this->saveHandler instanceof \SessionHandlerInterface) {
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows session to be started by PHP and managed by Symfony2
|
||||||
|
*
|
||||||
|
* @author Drak <drak@zikula.org>
|
||||||
|
*/
|
||||||
|
class PhpBridgeSessionStorage extends NativeSessionStorage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
|
||||||
|
* @param MetadataBag $metaBag MetadataBag
|
||||||
|
*/
|
||||||
|
public function __construct($handler = null, MetadataBag $metaBag = null)
|
||||||
|
{
|
||||||
|
$this->setMetadataBag($metaBag);
|
||||||
|
$this->setSaveHandler($handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
if ($this->started && !$this->closed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->loadSession();
|
||||||
|
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||||
|
// This condition matches only PHP 5.3 + internal save handlers
|
||||||
|
$this->saveHandler->setActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
// clear out the bags and nothing else that may be set
|
||||||
|
// since the purpose of this driver is to share a handler
|
||||||
|
foreach ($this->bags as $bag) {
|
||||||
|
$bag->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// reconnect the bags to the session
|
||||||
|
$this->loadSession();
|
||||||
|
}
|
||||||
|
}
|
@ -72,16 +72,31 @@ abstract class AbstractProxy
|
|||||||
*/
|
*/
|
||||||
public function isActive()
|
public function isActive()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
return $this->active = \PHP_SESSION_ACTIVE === session_status();
|
||||||
|
}
|
||||||
|
|
||||||
return $this->active;
|
return $this->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the active flag.
|
* Sets the active flag.
|
||||||
*
|
*
|
||||||
|
* Has no effect under PHP 5.4+ as status is detected
|
||||||
|
* automatically in isActive()
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
* @param Boolean $flag
|
* @param Boolean $flag
|
||||||
|
*
|
||||||
|
* @throws \LogicException
|
||||||
*/
|
*/
|
||||||
public function setActive($flag)
|
public function setActive($flag)
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
throw new \LogicException('This method is disabled in PHP 5.4.0+');
|
||||||
|
}
|
||||||
|
|
||||||
$this->active = (bool) $flag;
|
$this->active = (bool) $flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,11 +11,15 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
|
namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
|
||||||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
|
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
|
||||||
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
|
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for NativeSessionStorage.
|
* Test class for NativeSessionStorage.
|
||||||
@ -28,6 +32,28 @@ use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
|
|||||||
*/
|
*/
|
||||||
class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
|
class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
private $savePath;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
ini_set('session.save_handler', 'files');
|
||||||
|
ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
|
||||||
|
if (!is_dir($this->savePath)) {
|
||||||
|
mkdir($this->savePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
session_write_close();
|
||||||
|
array_map('unlink', glob($this->savePath.'/*'));
|
||||||
|
if (is_dir($this->savePath)) {
|
||||||
|
rmdir($this->savePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->savePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
@ -75,7 +101,6 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
|
|||||||
$storage->regenerate();
|
$storage->regenerate();
|
||||||
$this->assertNotEquals($id, $storage->getId());
|
$this->assertNotEquals($id, $storage->getId());
|
||||||
$this->assertEquals(7, $storage->getBag('attributes')->get('lucky'));
|
$this->assertEquals(7, $storage->getBag('attributes')->get('lucky'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRegenerateDestroy()
|
public function testRegenerateDestroy()
|
||||||
@ -126,32 +151,132 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals($options, $gco);
|
$this->assertEquals($options, $gco);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetSaveHandler()
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testSetSaveHandlerException()
|
||||||
{
|
{
|
||||||
$storage = $this->getStorage();
|
$storage = $this->getStorage();
|
||||||
$storage->setSaveHandler(new \StdClass());
|
$storage->setSaveHandler(new \StdClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetSaveHandler53()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_set('session.save_handler', 'files');
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
$storage->setSaveHandler();
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(null);
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new NativeSessionHandler());
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler()));
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new SessionHandler());
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new NativeProxy());
|
||||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetSaveHandlerPHP53()
|
public function testSetSaveHandler54()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_set('session.save_handler', 'files');
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
$storage->setSaveHandler();
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(null);
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new SessionHandlerProxy(new NativeSessionHandler()));
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new NativeSessionHandler());
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler()));
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
$storage->setSaveHandler(new SessionHandler());
|
||||||
|
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \RuntimeException
|
||||||
|
*/
|
||||||
|
public function testStartedOutside53()
|
||||||
{
|
{
|
||||||
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$storage = $this->getStorage();
|
$storage = $this->getStorage();
|
||||||
$storage->setSaveHandler(new NativeFileSessionHandler());
|
|
||||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler());
|
$this->assertFalse(isset($_SESSION));
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->assertTrue(isset($_SESSION));
|
||||||
|
// PHP session might have started, but the storage driver has not, so false is correct here
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
$key = $storage->getMetadataBag()->getStorageKey();
|
||||||
|
$this->assertFalse(isset($_SESSION[$key]));
|
||||||
|
$storage->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetSaveHandlerPHP54()
|
/**
|
||||||
|
* @expectedException \RuntimeException
|
||||||
|
*/
|
||||||
|
public function testCanStartOutside54()
|
||||||
{
|
{
|
||||||
if (version_compare(phpversion(), '5.4.0', '<')) {
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
$this->markTestSkipped('Test skipped, for PHP 5.4+ only.');
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$storage = $this->getStorage();
|
$storage = $this->getStorage();
|
||||||
$storage->setSaveHandler(new NullSessionHandler());
|
|
||||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
|
$this->assertFalse(isset($_SESSION));
|
||||||
|
$this->assertFalse($storage->getSaveHandler()->isActive());
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->assertTrue(isset($_SESSION));
|
||||||
|
$this->assertTrue($storage->getSaveHandler()->isActive());
|
||||||
|
// PHP session might have started, but the storage driver has not, so false is correct here
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
$key = $storage->getMetadataBag()->getStorageKey();
|
||||||
|
$this->assertFalse(isset($_SESSION[$key]));
|
||||||
|
$storage->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionHandler implements \SessionHandlerInterface
|
||||||
|
{
|
||||||
|
public function open($savePath, $sessionName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read($id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($id, $data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function gc($maxlifetime)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for PhpSessionStorage.
|
||||||
|
*
|
||||||
|
* @author Drak <drak@zikula.org>
|
||||||
|
*
|
||||||
|
* These tests require separate processes.
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcesses
|
||||||
|
*/
|
||||||
|
class PhpSessionStorageTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
private $savePath;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
ini_set('session.save_handler', 'files');
|
||||||
|
ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
|
||||||
|
if (!is_dir($this->savePath)) {
|
||||||
|
mkdir($this->savePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
session_write_close();
|
||||||
|
array_map('unlink', glob($this->savePath.'/*'));
|
||||||
|
if (is_dir($this->savePath)) {
|
||||||
|
rmdir($this->savePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->savePath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PhpBridgeSessionStorage
|
||||||
|
*/
|
||||||
|
protected function getStorage()
|
||||||
|
{
|
||||||
|
$storage = new PhpBridgeSessionStorage();
|
||||||
|
$storage->registerBag(new AttributeBag);
|
||||||
|
|
||||||
|
return $storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPhpSession53()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
|
||||||
|
$this->assertFalse(isset($_SESSION));
|
||||||
|
$this->assertFalse($storage->getSaveHandler()->isActive());
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->assertTrue(isset($_SESSION));
|
||||||
|
// in PHP 5.3 we cannot reliably tell if a session has started
|
||||||
|
$this->assertFalse($storage->getSaveHandler()->isActive());
|
||||||
|
// PHP session might have started, but the storage driver has not, so false is correct here
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
$key = $storage->getMetadataBag()->getStorageKey();
|
||||||
|
$this->assertFalse(isset($_SESSION[$key]));
|
||||||
|
$storage->start();
|
||||||
|
$this->assertTrue(isset($_SESSION[$key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPhpSession54()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
|
||||||
|
$this->assertFalse(isset($_SESSION));
|
||||||
|
$this->assertFalse($storage->getSaveHandler()->isActive());
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->assertTrue(isset($_SESSION));
|
||||||
|
// in PHP 5.4 we can reliably detect a session started
|
||||||
|
$this->assertTrue($storage->getSaveHandler()->isActive());
|
||||||
|
// PHP session might have started, but the storage driver has not, so false is correct here
|
||||||
|
$this->assertFalse($storage->isStarted());
|
||||||
|
|
||||||
|
$key = $storage->getMetadataBag()->getStorageKey();
|
||||||
|
$this->assertFalse(isset($_SESSION[$key]));
|
||||||
|
$storage->start();
|
||||||
|
$this->assertTrue(isset($_SESSION[$key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClear()
|
||||||
|
{
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
session_start();
|
||||||
|
$_SESSION['drak'] = 'loves symfony';
|
||||||
|
$storage->getBag('attributes')->set('symfony', 'greatness');
|
||||||
|
$key = $storage->getBag('attributes')->getStorageKey();
|
||||||
|
$this->assertEquals($_SESSION[$key], array('symfony' => 'greatness'));
|
||||||
|
$this->assertEquals($_SESSION['drak'], 'loves symfony');
|
||||||
|
$storage->clear();
|
||||||
|
$this->assertEquals($_SESSION[$key], array());
|
||||||
|
$this->assertEquals($_SESSION['drak'], 'loves symfony');
|
||||||
|
}
|
||||||
|
}
|
@ -86,19 +86,54 @@ class AbstractProxyTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertFalse($this->proxy->isWrapper());
|
$this->assertFalse($this->proxy->isWrapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIsActive()
|
public function testIsActivePhp53()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertFalse($this->proxy->isActive());
|
$this->assertFalse($this->proxy->isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetActive()
|
/**
|
||||||
|
* @runInSeparateProcess
|
||||||
|
*/
|
||||||
|
public function testIsActivePhp54()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertFalse($this->proxy->isActive());
|
||||||
|
session_start();
|
||||||
|
$this->assertTrue($this->proxy->isActive());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetActivePhp53()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->proxy->setActive(true);
|
$this->proxy->setActive(true);
|
||||||
$this->assertTrue($this->proxy->isActive());
|
$this->assertTrue($this->proxy->isActive());
|
||||||
$this->proxy->setActive(false);
|
$this->proxy->setActive(false);
|
||||||
$this->assertFalse($this->proxy->isActive());
|
$this->assertFalse($this->proxy->isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testSetActivePhp54()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->proxy->setActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @runInSeparateProcess
|
* @runInSeparateProcess
|
||||||
*/
|
*/
|
||||||
@ -113,12 +148,30 @@ class AbstractProxyTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @expectedException \LogicException
|
* @expectedException \LogicException
|
||||||
*/
|
*/
|
||||||
public function testNameException()
|
public function testNameExceptionPhp53()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->proxy->setActive(true);
|
$this->proxy->setActive(true);
|
||||||
$this->proxy->setName('foo');
|
$this->proxy->setName('foo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testNameExceptionPhp54()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->proxy->setName('foo');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @runInSeparateProcess
|
* @runInSeparateProcess
|
||||||
*/
|
*/
|
||||||
@ -133,9 +186,27 @@ class AbstractProxyTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @expectedException \LogicException
|
* @expectedException \LogicException
|
||||||
*/
|
*/
|
||||||
public function testIdException()
|
public function testIdExceptionPhp53()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '>=')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
|
||||||
|
}
|
||||||
|
|
||||||
$this->proxy->setActive(true);
|
$this->proxy->setActive(true);
|
||||||
$this->proxy->setId('foo');
|
$this->proxy->setId('foo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testIdExceptionPhp54()
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
|
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
|
||||||
|
}
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$this->proxy->setId('foo');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
|
|||||||
class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase
|
class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var PHPUnit_Framework_MockObject_Matcher
|
* @var \PHPUnit_Framework_MockObject_Matcher
|
||||||
*/
|
*/
|
||||||
private $mock;
|
private $mock;
|
||||||
|
|
||||||
@ -52,7 +52,11 @@ class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertFalse($this->proxy->isActive());
|
$this->assertFalse($this->proxy->isActive());
|
||||||
$this->proxy->open('name', 'id');
|
$this->proxy->open('name', 'id');
|
||||||
|
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||||
$this->assertTrue($this->proxy->isActive());
|
$this->assertTrue($this->proxy->isActive());
|
||||||
|
} else {
|
||||||
|
$this->assertFalse($this->proxy->isActive());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOpenFalse()
|
public function testOpenFalse()
|
||||||
|
Reference in New Issue
Block a user