Add Session Listener to enforce save of session at kernel response

This commit is contained in:
Benoît Burnichon
2015-03-26 00:03:33 +01:00
parent 10cf918ff2
commit 8d7fe65430
3 changed files with 171 additions and 65 deletions

View File

@@ -14,6 +14,9 @@ namespace Alchemy\Phrasea\Core\Provider;
use Alchemy\Phrasea\Core\Configuration\SessionHandlerFactory;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
class SessionHandlerServiceProvider implements ServiceProviderInterface
{
@@ -27,10 +30,24 @@ class SessionHandlerServiceProvider implements ServiceProviderInterface
});
}
public function onKernelResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$session = $event->getRequest()->getSession();
if ($session && $session->isStarted()) {
$session->save();
}
}
/**
* {@inheritdoc}
*/
public function boot(Application $app)
{
// Priority should be lower than test session mock listener
$app['dispatcher']->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'), -129);
}
}

View File

@@ -23,10 +23,12 @@
<filter>
<blacklist>
<directory>lib/vendor</directory>
<directory>tests</directory>
<directory>vendor</directory>
</blacklist>
<whitelist>
<directory suffix=".php">lib</directory>
</whitelist>
</filter>
<!--<listeners>-->

View File

@@ -5,17 +5,31 @@ namespace Alchemy\Tests\Phrasea\Core\Provider;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Core\Provider\SessionHandlerServiceProvider;
use Alchemy\Tests\Phrasea\MockArrayConf;
use Silex\Application as SilexApp;
use Silex\Application;
use Silex\Provider\SessionServiceProvider;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
class SessionHandlerServiceProviderTest extends \PhraseanetTestCase
class SessionHandlerServiceProviderTest extends \PHPUnit_Framework_TestCase
{
/** @var SessionHandlerServiceProvider */
private $sut;
protected function setUp()
{
$this->sut = new SessionHandlerServiceProvider();
}
/**
* @dataProvider provideVariousConfs
* @dataProvider provideVariousConfigurations
*/
public function testWithVariousConf($sessionConf, $expectedInstance, $method = null, $options = null, $mock = null)
public function testWithVariousConfigurations($sessionConf, $expectedInstance, $method = null, $options = null, $mock = null)
{
$app = new SilexApp();
$app = new Application();
$app['root.path'] = __DIR__ . '/../../../../../..';
$app->register(new SessionServiceProvider());
$app->register(new SessionHandlerServiceProvider());
@@ -35,60 +49,9 @@ class SessionHandlerServiceProviderTest extends \PhraseanetTestCase
$this->assertInstanceOf($expectedInstance, $handler);
}
public function provideVariousConfs()
public function provideVariousConfigurations()
{
$memcache = $this->getMockBuilder('Memcache')
->disableOriginalConstructor()
->getMock();
@$memcached = $this->getMockBuilder('Memcached')
->disableOriginalConstructor()
->getMock();
$redis = $this->getMockBuilder('Redis')
->disableOriginalConstructor()
->getMock();
return [
[
[
'type' => 'memcache',
'options' => [
'host' => 'localhost',
'port' => '11211',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getMemcacheConnection',
['host' => 'localhost', 'port' => 11211],
$memcache
],
[
[
'type' => 'memcached',
'options' => [
'host' => 'localhost',
'port' => '11211',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getMemcachedConnection',
['host' => 'localhost', 'port' => 11211],
$memcached
],
[
[
'type' => 'redis',
'options' => [
'host' => '127.0.0.1',
'port' => '6379',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getRedisConnection',
['host' => '127.0.0.1', 'port' => 6379],
$redis
],
$configurations = [
[
[
'main' => [
@@ -100,5 +63,129 @@ class SessionHandlerServiceProviderTest extends \PhraseanetTestCase
'Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler'
]
];
if (class_exists('Memcache')) {
$memcache = $this->getMockBuilder('Memcache')
->disableOriginalConstructor()
->getMock();
$configurations[] = [
[
'type' => 'memcache',
'options' => [
'host' => 'localhost',
'port' => '11211',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getMemcacheConnection',
['host' => 'localhost', 'port' => 11211],
$memcache
];
}
if (class_exists('Memcached')) {
// Error suppressor due to Memcached having now obsolete by reference declarations
@$memcached = $this->getMockBuilder('Memcached')
->disableOriginalConstructor()
->getMock();
$configurations[] = [
[
'type' => 'memcached',
'options' => [
'host' => 'localhost',
'port' => '11211',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getMemcachedConnection',
['host' => 'localhost', 'port' => 11211],
$memcached
];
}
if (class_exists('Redis')) {
$redis = $this->getMockBuilder('Redis')
->disableOriginalConstructor()
->getMock();
$configurations[] = [
[
'type' => 'redis',
'options' => [
'host' => '127.0.0.1',
'port' => '6379',
]
],
'Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler',
'getRedisConnection',
['host' => '127.0.0.1', 'port' => 6379],
$redis
];
}
return $configurations;
}
public function testItIgnoresSubRequests()
{
$event = $this->getMockBuilder(FilterResponseEvent::class)
->disableOriginalConstructor()
->getMock();
$event->expects($this->once())
->method('getRequestType')
->willReturn(HttpKernelInterface::SUB_REQUEST)
;
$this->sut->onKernelResponse($event);
}
public function testItSavesSessionAtKernelResponseEvent()
{
$session = $this->getMock(SessionInterface::class);
$session
->expects($this->once())
->method('isStarted')
->willReturn(true)
;
$session
->expects($this->once())
->method('save')
;
$request = new Request();
$request->setSession($session);
$event = $this->getMockBuilder(FilterResponseEvent::class)
->disableOriginalConstructor()
->getMock();
$event->expects($this->once())
->method('getRequestType')
->willReturn(HttpKernelInterface::MASTER_REQUEST)
;
$event
->expects($this->once())
->method('getRequest')
->willReturn($request)
;
$this->sut->onKernelResponse($event);
}
public function testItAddsFilterResponseAtBoot()
{
$dispatcher = $this->getMock(EventDispatcherInterface::class);
$dispatcher
->expects($this->once())
->method('addListener')
->with(KernelEvents::RESPONSE, [$this->sut, 'onKernelResponse'], -129);
$app = new Application();
$app['dispatcher'] = $dispatcher;
$this->sut->boot($app);
}
}