diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index 5214648ee2358..cf9c8c20a7edf 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -27,8 +27,10 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c ### DoctrineBundle * This bundle has been moved to the Doctrine organization - * added optional `group_by` property to `EntityType` that supports either a `PropertyPath` or a `\Closure` that is evaluated on the entity choices - * The `em` option for the `UniqueEntity` constraint is now optional (and should probably not be used anymore). + * added optional `group_by` property to `EntityType` that supports either a + `PropertyPath` or a `\Closure` that is evaluated on the entity choices + * The `em` option for the `UniqueEntity` constraint is now optional (and should + probably not be used anymore). ### FrameworkBundle @@ -39,13 +41,17 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c * added Controller::getUser() * [BC BREAK] assets_base_urls and base_urls merging strategy has changed * changed the default profiler storage to use the filesystem instead of SQLite - * added support for placeholders in route defaults and requirements (replaced by the value set in the service container) + * added support for placeholders in route defaults and requirements (replaced + by the value set in the service container) * added Filesystem component as a dependency * added support for hinclude (use ``standalone: 'js'`` in render tag) * session options: lifetime, path, domain, secure, httponly were deprecated. - Prefixed versions should now be used instead: cookie_lifetime, cookie_path, cookie_domain, cookie_secure, cookie_httponly - * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', 'httponly' - are now prefixed with cookie_ when dumped to the container + Prefixed versions should now be used instead: cookie_lifetime, cookie_path, + cookie_domain, cookie_secure, cookie_httponly + * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', + 'httponly' are now prefixed with cookie_ when dumped to the container + * Added `handler_id` configuration under `session` key to represent `session.handler` + service, defaults to `session.handler.native_file`. ### MonologBundle @@ -257,32 +263,47 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c * made mimetype to extension conversion configurable * [BC BREAK] Moved all session related classes and interfaces into own namespace, as `Symfony\Component\HttpFoudation\Session` and renamed classes accordingly. - * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. - This makes the implementation ESI compatible. - * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire behaviour of messages auto expiring - after one page page load. Messages must be retrived by `get()` or `all()`. - * [BC BREAK] Removed the `close()` method from the Session class + Session handlers are located in the subnamespace `Symfony\Component\HttpFoudation\Session\Handler`. + * SessionHandlers must implement `\SessionHandlerInterface` or extend from the + `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. + * Added internal storage driver proxy mechanism for forward compatibility with + PHP 5.4 `\SessionHandler` class. + * Added session handlers for PHP native Memcache, Memcached and SQLite session + save handlers. + * Added session handlers for custom Memcache, Memcached and Null session save handlers. + * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. + * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and + `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class + is a mediator for the session storage internals including the session handlers + which do the real work of participating in the internal PHP session workflow. + * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit + and functional testing without starting real PHP sessions. Removed + `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit + tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` + for functional tests. These do not interact with global session ini + configuration values, session functions or `$_SESSION` supreglobal. This means + they can be configured directly allowing multiple instances to work without + conflicting in the same PHP process. + * [BC BREAK] Removed the `close()` method from the `Session` class, as this is + now redundant. * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` - `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead which returns a `FlashBagInterface`. - * `Session->clear()` now only clears session attributes as before it cleared flash messages and - attributes. `Session->getFlashBag()->all()` clears flashes now. - * Added `Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage` base class for - session storage drivers. - * Added `SessionHandlerInterface` interface which storage drivers should implement after inheriting from - `Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage` when writing custom - session save handlers using PHP 5.3. This interface is a stub for the PHP 5.4 interface. - * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and `remove()`. Added - `getBag()`, `registerBag()`. - * Moved attribute storage to `Symfony\Component\HttpFoundation\Attribute\AttributeBagInterface`. - * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate attributes storage - behaviour from 2.0.x (default). - * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for namespace session attributes. - * Session now implements `Symfony\Component\HttpFoundation\Session\SessionInterface` making - implementation customizable and portable. - * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionStorage`. - * Added session storage drivers for PHP native Memcache, Memcached and SQLite session save handlers. - * Added session storage drivers for custom Memcache, Memcached and Null session save handlers. - * Removed `FilesystemSessionStorage`, use `MockFileSessionStorage` for functional testing instead. + `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead + which returns a `FlashBagInterface`. + * `Session->clear()` now only clears session attributes as before it cleared + flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. + * Session data is now managed by `SessionBagInterface` which to better encapsulate + session data. + * Refactored session attribute and flash messages system to their own + `SessionBagInterface` implementations. + * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This + implementation is ESI compatible. + * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire + behaviour of messages auto expiring. + after one page page load. Messages must be retrieved by `get()` or `all()`. + * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate + attributes storage behaviour from 2.0.x (default). + * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for + namespace session attributes. ### HttpKernel diff --git a/UPGRADE-2.1.md b/UPGRADE-2.1.md index db6e4c511305d..2a4927a5ec237 100644 --- a/UPGRADE-2.1.md +++ b/UPGRADE-2.1.md @@ -334,13 +334,11 @@ UPGRADE FROM 2.0 to 2.1 {% endfor %} ``` - * Session storage drivers should inherit from - `Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage` - and should no longer implement `read()`, `write()`, and `remove()`, which - were removed from `SessionStorageInterface`. + * Session handler drivers should implement `\SessionHandlerInterface` or extend from + `Symfony\Component\HttpFoudation\Session\Storage\Handler\NativeHandlerInterface` base class and renamed + to `Handler\FooSessionHandler`. E.g. `PdoSessionStorage` becomes `Handler\PdoSessionHandler`. - Any session storage driver that wants to use custom save handlers should - implement `SessionHandlerInterface`. + * Refactor code using `$session->*flash*()` methods to use `$session->getFlashBag()->*()`. ### FrameworkBundle @@ -371,3 +369,20 @@ UPGRADE FROM 2.0 to 2.1 cookie_httponly: true ``` +Added `handler_id`, defaults to `session.handler.native_file`. + + ``` + framework: + session: + storage_id: session.storage.native + handler_id: session.handler.native_file + ``` + +To use mock session storage use the following. `handler_id` is irrelevant in this context. + + ``` + framework: + session: + storage_id: session.storage.mock_file + ``` + diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorage.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php similarity index 69% rename from src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorage.php rename to src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php index a260c3a14974a..cef6cec860f4b 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorage.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php @@ -1,9 +1,17 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Doctrine\HttpFoundation; use Doctrine\DBAL\Platforms\MySqlPlatform; -use Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage; use Doctrine\DBAL\Driver\Connection; /** @@ -12,7 +20,7 @@ * @author Fabien Potencier * @author Johannes M. Schmitt */ -class DbalSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class DbalSessionHandler implements \SessionHandlerInterface { /** * @var Connection @@ -25,26 +33,19 @@ class DbalSessionStorage extends AbstractSessionStorage implements \SessionHandl private $tableName; /** + * Constructor. * - * @param Connection $con An instance of Connection. - * @param string $tableName Table name. - * @param array $options Session configuration options + * @param Connection $con An instance of Connection. + * @param string $tableName Table name. */ - public function __construct(Connection $con, $tableName = 'sessions', array $options = array()) + public function __construct(Connection $con, $tableName = 'sessions') { $this->con = $con; $this->tableName = $tableName; - - parent::__construct($options); } /** - * Opens a session. - * - * @param string $path (ignored) - * @param string $name (ignored) - * - * @return Boolean true, if the session was opened, otherwise an exception is thrown + * {@inheritdoc} */ public function open($path = null, $name = null) { @@ -52,9 +53,7 @@ public function open($path = null, $name = null) } /** - * Closes a session. - * - * @return Boolean true, if the session was closed, otherwise false + * {@inheritdoc} */ public function close() { @@ -63,13 +62,7 @@ public function close() } /** - * Destroys a session. - * - * @param string $id A session ID - * - * @return Boolean true, if the session was destroyed, otherwise an exception is thrown - * - * @throws \RuntimeException If the session cannot be destroyed + * {@inheritdoc} */ public function destroy($id) { @@ -85,13 +78,7 @@ public function destroy($id) } /** - * Cleans up old sessions. - * - * @param int $lifetime The lifetime of a session - * - * @return Boolean true, if old sessions have been cleaned, otherwise an exception is thrown - * - * @throws \RuntimeException If any old sessions cannot be cleaned + * {@inheritdoc} */ public function gc($lifetime) { @@ -107,13 +94,7 @@ public function gc($lifetime) } /** - * Reads a session. - * - * @param string $id A session ID - * - * @return string The session data if the session was read or created, otherwise an exception is thrown - * - * @throws \RuntimeException If the session cannot be read + * {@inheritdoc} */ public function read($id) { @@ -136,14 +117,7 @@ public function read($id) } /** - * Writes session data. - * - * @param string $id A session ID - * @param string $data A serialized chunk of session data - * - * @return Boolean true, if the session was written, otherwise an exception is thrown - * - * @throws \RuntimeException If the session data cannot be written + * {@inheritdoc} */ public function write($id, $data) { diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorageSchema.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php similarity index 76% rename from src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorageSchema.php rename to src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php index b33862588c9c0..b7b4b91a7a74b 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionStorageSchema.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Doctrine\HttpFoundation; use Doctrine\DBAL\Schema\Schema; @@ -9,7 +18,7 @@ * * @author Johannes M. Schmitt */ -final class DbalSessionStorageSchema extends Schema +final class DbalSessionHandlerSchema extends Schema { private $tableName; diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ca63874b0f9db..652531d613300 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -167,7 +167,8 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->canBeUnset() ->children() ->booleanNode('auto_start')->defaultFalse()->end() - ->scalarNode('storage_id')->defaultValue('session.storage.native_file')->end() + ->scalarNode('storage_id')->defaultValue('session.storage.native')->end() + ->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end() ->scalarNode('name')->end() ->scalarNode('cookie_lifetime')->end() ->scalarNode('cookie_path')->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 5a76df3b492ab..8c91c37a4e3b4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -310,10 +310,16 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c } $container->setParameter('session.storage.options', $options); + // session handler (the internal callback registered with PHP session management) + $container->setAlias('session.handler', $config['handler_id']); + $this->addClassesToCompile(array( 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener', 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\AbstractSessionStorage', + 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage', + 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\NativeSessionHandler', + 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\AbstractProxy', + 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\SessionHandlerProxy', $container->getDefinition('session')->getClass(), )); diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php index 83fdec4b7400a..ad396347d51e5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php @@ -28,7 +28,14 @@ */ class SessionListener implements EventSubscriberInterface { + /** + * @var ContainerInterface + */ private $container; + + /** + * @var boolean + */ private $autoStart; public function __construct(ContainerInterface $container, $autoStart = false) diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php index d335758b70662..8f4536de8e9b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php @@ -43,15 +43,16 @@ public function onKernelRequest(GetResponseEvent $event) } // bootstrap the session - if ($this->container->has('session')) { - $this->container->get('session'); + if (!$this->container->has('session')) { + return; } + $session = $this->container->get('session'); $cookies = $event->getRequest()->cookies; - if ($cookies->has(session_name())) { - session_id($cookies->get(session_name())); + if ($cookies->has($session->getName())) { + $session->setId($cookies->get($session->getName())); } else { - session_id(''); + $session->setId(''); } } @@ -72,7 +73,7 @@ public function onKernelResponse(FilterResponseEvent $event) $params = session_get_cookie_params(); - $event->getResponse()->headers->setCookie(new Cookie(session_name(), session_id(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); + $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 535c455b0c370..8b7c264ce218d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -74,6 +74,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 31d374aa6b22c..7392d26a1734c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -8,8 +8,9 @@ Symfony\Component\HttpFoundation\Session\Session Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag - Symfony\Component\HttpFoundation\Session\Storage\NativeFileSessionStorage + Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage + Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler Symfony\Bundle\FrameworkBundle\EventListener\SessionListener @@ -20,18 +21,21 @@ + + %session.storage.options% + + + %kernel.cache_dir%/sessions - %session.storage.options% - + %kernel.cache_dir%/sessions - %session.storage.options% @@ -40,7 +44,6 @@ - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_full.php index 219644b563ae3..5119fbdbabae6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_full.php @@ -4,7 +4,8 @@ 'secret' => 's3cr3t', 'session' => array( 'auto_start' => true, - 'storage_id' => 'session.storage.native_file', + 'storage_id' => 'session.storage.native', + 'handler_id' => 'session.handler.native_file', 'name' => '_SYMFONY', 'lifetime' => 2012, 'path' => '/sf2', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_partial.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_partial.php index deadfe4b88159..b15ea893f02ff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_partial.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/deprecated_merge_partial.php @@ -4,7 +4,8 @@ 'secret' => 's3cr3t', 'session' => array( 'auto_start' => true, - 'storage_id' => 'session.storage.native_file', + 'storage_id' => 'session.storage.native', + 'handler_id' => 'session.handler.native_file', 'name' => '_SYMFONY', 'lifetime' => 2012, 'path' => '/sf2', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index 3ab6488493024..32fa1812fa83c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -20,7 +20,8 @@ ), 'session' => array( 'auto_start' => true, - 'storage_id' => 'session.storage.native_file', + 'storage_id' => 'session.storage.native', + 'handler_id' => 'session.handler.native_file', 'name' => '_SYMFONY', 'lifetime' => 86400, 'path' => '/', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_full.xml index 283fb3190cba9..7b95b4200240c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_full.xml @@ -7,6 +7,6 @@ http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_partial.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_partial.xml index 07df1182cfd9b..701bae53bd75b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_partial.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/deprecated_merge_partial.xml @@ -7,6 +7,6 @@ http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index d91825bd20c05..5ee785070ea69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -12,7 +12,7 @@ - + loader.foo loader.bar diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_full.yml index fdc61fd93748a..e5ec05fbf6322 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_full.yml @@ -2,7 +2,8 @@ framework: secret: s3cr3t session: auto_start: true - storage_id: session.storage.native_file + storage_id: session.storage.native + handler_id: session.handler.native_file name: _SYMFONY lifetime: 2012 path: /sf2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_partial.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_partial.yml index e61808b8f2af4..67ea8bc44ba08 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_partial.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/deprecated_merge_partial.yml @@ -2,7 +2,8 @@ framework: secret: s3cr3t session: auto_start: true - storage_id: session.storage.native_file + storage_id: session.storage.native + handler_id: session.handler.native_file name: _SYMFONY lifetime: 2012 path: /sf2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 126baf2d4e90b..dd459e784fc3a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -14,7 +14,8 @@ framework: type: xml session: auto_start: true - storage_id: session.storage.native_file + storage_id: session.storage.native + handler_id: session.handler.native_file name: _SYMFONY lifetime: 86400 path: / diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index eac0395dbdb80..43ae49a016e6b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -78,7 +78,8 @@ public function testSession() $this->assertTrue($container->hasDefinition('session'), '->registerSessionConfiguration() loads session.xml'); $this->assertEquals('fr', $container->getParameter('kernel.default_locale')); $this->assertTrue($container->getDefinition('session_listener')->getArgument(1)); - $this->assertEquals('session.storage.native_file', (string) $container->getAlias('session.storage')); + $this->assertEquals('session.storage.native', (string) $container->getAlias('session.storage')); + $this->assertEquals('session.handler.native_file', (string) $container->getAlias('session.handler')); $options = $container->getParameter('session.storage.options'); $this->assertEquals('_SYMFONY', $options['name']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/TestSessionListenerTest.php index fe551ba360aa7..4c577f292f21e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/TestSessionListenerTest.php @@ -94,8 +94,13 @@ private function sessionMustBeSaved() private function getSession() { - return $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session') + $mock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session') ->disableOriginalConstructor() ->getMock(); + + // set return value for getName() + $mock->expects($this->any())->method('getName')->will($this->returnValue('MOCKSESSID')); + + return $mock; } } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index f38b1e7d0f084..eaa453e1b472e 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -496,7 +496,8 @@ public function getSession() public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->cookies->has(session_name()) && null !== $this->session; + $sessionName = $this->hasSession() ? $this->session->getName() : null; + return $this->cookies->has($sessionName) && $this->hasSession(); } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Session.php b/src/Symfony/Component/HttpFoundation/Session/Session.php index 63dda8d6bdbc6..13c6448874a3a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session/Session.php @@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * Session. @@ -35,18 +36,34 @@ class Session implements SessionInterface */ protected $storage; + /** + * @var string + */ + private $flashName; + + /** + * @var string + */ + private $attributeName; + /** * Constructor. * - * @param SessionStorageInterface $storage A SessionStorageInterface instance. + * @param SessionStorageInterface $storage A SessionStorageInterface instance. * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) */ - public function __construct(SessionStorageInterface $storage, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) + public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) { - $this->storage = $storage; - $this->registerBag($attributes ?: new AttributeBag()); - $this->registerBag($flashes ?: new FlashBag()); + $this->storage = $storage ?: new NativeSessionStorage(); + + $attributeBag = $attributes ?: new AttributeBag(); + $this->attributeName = $attributeBag->getName(); + $this->registerBag($attributeBag); + + $flashBag = $flashes ?: new FlashBag(); + $this->flashName = $flashBag->getName(); + $this->registerBag($flashBag); } /** @@ -62,7 +79,7 @@ public function start() */ public function has($name) { - return $this->storage->getBag('attributes')->has($name); + return $this->storage->getBag($this->attributeName)->has($name); } /** @@ -70,7 +87,7 @@ public function has($name) */ public function get($name, $default = null) { - return $this->storage->getBag('attributes')->get($name, $default); + return $this->storage->getBag($this->attributeName)->get($name, $default); } /** @@ -78,7 +95,7 @@ public function get($name, $default = null) */ public function set($name, $value) { - $this->storage->getBag('attributes')->set($name, $value); + $this->storage->getBag($this->attributeName)->set($name, $value); } /** @@ -86,7 +103,7 @@ public function set($name, $value) */ public function all() { - return $this->storage->getBag('attributes')->all(); + return $this->storage->getBag($this->attributeName)->all(); } /** @@ -94,7 +111,7 @@ public function all() */ public function replace(array $attributes) { - $this->storage->getBag('attributes')->replace($attributes); + $this->storage->getBag($this->attributeName)->replace($attributes); } /** @@ -102,7 +119,7 @@ public function replace(array $attributes) */ public function remove($name) { - return $this->storage->getBag('attributes')->remove($name); + return $this->storage->getBag($this->attributeName)->remove($name); } /** @@ -110,7 +127,7 @@ public function remove($name) */ public function clear() { - $this->storage->getBag('attributes')->clear(); + $this->storage->getBag($this->attributeName)->clear(); } /** @@ -140,11 +157,7 @@ public function save() } /** - * Returns the session ID - * - * @return mixed The session ID - * - * @api + * {@inheritdoc} */ public function getId() { @@ -152,7 +165,31 @@ public function getId() } /** - * Registers a SessionBagInterface with the sessio. + * {@inheritdoc} + */ + public function setId($id) + { + $this->storage->setId($id); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->storage->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->storage->setName($name); + } + + /** + * Registers a SessionBagInterface with the session. * * @param SessionBagInterface $bag */ @@ -180,7 +217,7 @@ public function getBag($name) */ public function getFlashBag() { - return $this->getBag('flashes'); + return $this->getBag($this->flashName); } // the following methods are kept for compatibility with Symfony 2.0 (they will be removed for Symfony 2.3) diff --git a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php index 741969b10ec84..4e4962de4ee39 100644 --- a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php @@ -29,6 +29,42 @@ interface SessionInterface */ function start(); + /** + * Returns the session ID. + * + * @return string The session ID. + * + * @api + */ + function getId(); + + /** + * Sets the session ID + * + * @param string $id + * + * @api + */ + function setId($id); + + /** + * Returns the session name. + * + * @return mixed The session name. + * + * @api + */ + function getName(); + + /** + * Sets the session name. + * + * @param string $name + * + * @api + */ + function setName($name); + /** * Invalidates the current session. * diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php similarity index 94% rename from src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index 68218e86b32e9..72ecac5550780 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -9,14 +9,14 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcacheSessionStorage. * * @author Drak */ -class MemcacheSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class MemcacheSessionHandler implements \SessionHandlerInterface { /** * Memcache driver. @@ -68,8 +68,6 @@ public function __construct(\Memcache $memcache, array $memcacheOptions = array( $this->prefix = isset($memcacheOptions['prefix']) ? $memcacheOptions['prefix'] : 'sf2s'; $this->memcacheOptions = $memcacheOptions; - - parent::__construct($options); } protected function addServer(array $server) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php similarity index 94% rename from src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 366d815013756..bc642cb082869 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcachedSessionStorage. @@ -21,7 +21,7 @@ * * @author Drak */ -class MemcachedSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class MemcachedSessionHandler implements \SessionHandlerInterface { /** * Memcached driver. @@ -63,8 +63,6 @@ public function __construct(\Memcached $memcached, array $memcachedOptions = arr $this->memcached->setOption(\Memcached::OPT_PREFIX_KEY, isset($memcachedOptions['prefix']) ? $memcachedOptions['prefix'] : 'sf2s'); $this->memcachedOptions = $memcachedOptions; - - parent::__construct($options); } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php new file mode 100644 index 0000000000000..202d8d0f900ee --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -0,0 +1,41 @@ + + * + * 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\Handler; + +/** + * NativeFileSessionHandler. + * + * Native session handler using PHP's built in file storage. + * + * @author Drak + */ +class NativeFileSessionHandler extends NativeSessionHandler +{ + /** + * Constructor. + * + * @param string $savePath Path of directory to save session files. Default null will leave setting as defined by PHP. + */ + public function __construct($savePath = null) + { + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } + + if ($savePath && !is_dir($savePath)) { + mkdir($savePath, 0777, true); + } + + ini_set('session.save_handler', 'files'); + ini_set('session.save_path', $savePath); + } +} \ No newline at end of file diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php similarity index 79% rename from src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php index ec34ead6d8694..beef87e965ddf 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NativeMemcacheSessionStorage. @@ -20,13 +20,8 @@ * * @author Drak */ -class NativeMemcacheSessionStorage extends AbstractSessionStorage +class NativeMemcacheSessionHandler extends NativeSessionHandler { - /** - * @var string - */ - private $savePath; - /** * Constructor. * @@ -41,17 +36,14 @@ public function __construct($savePath = 'tcp://127.0.0.1:11211?persistent=0', ar throw new \RuntimeException('PHP does not have "memcache" session module registered'); } - $this->savePath = $savePath; - parent::__construct($options); - } + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } - /** - * {@inheritdoc} - */ - protected function registerSaveHandlers() - { ini_set('session.save_handler', 'memcache'); - ini_set('session.save_path', $this->savePath); + ini_set('session.save_path', $savePath); + + $this->setOptions($options); } /** @@ -73,7 +65,5 @@ protected function setOptions(array $options) ini_set($key, $value); } } - - parent::setOptions($options); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php similarity index 79% rename from src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php index e923f34030d54..d66dc953d6d45 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NativeMemcachedSessionStorage. @@ -20,13 +20,8 @@ * * @author Drak */ -class NativeMemcachedSessionStorage extends AbstractSessionStorage +class NativeMemcachedSessionHandler extends NativeSessionHandler { - /** - * @var string - */ - private $savePath; - /** * Constructor. * @@ -41,17 +36,14 @@ public function __construct($savePath = '127.0.0.1:11211', array $options = arra throw new \RuntimeException('PHP does not have "memcached" session module registered'); } - $this->savePath = $savePath; - parent::__construct($options); - } + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } - /** - * {@inheritdoc} - */ - protected function registerSaveHandlers() - { ini_set('session.save_handler', 'memcached'); - ini_set('session.save_path', $this->savePath); + ini_set('session.save_path', $savePath); + + $this->setOptions($options); } /** @@ -72,7 +64,5 @@ protected function setOptions(array $options) ini_set($key, $value); } } - - parent::setOptions($options); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php new file mode 100644 index 0000000000000..a5338d2da2c01 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php @@ -0,0 +1,24 @@ + + * + * 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\Handler; + +/** + * Adds SessionHandler functionality if available. + * + * @see http://php.net/sessionhandler + */ + +if (version_compare(phpversion(), '5.4.0', '>=')) { + class NativeSessionHandler extends \SessionHandler {} +} else { + class NativeSessionHandler {} +} \ No newline at end of file diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandler.php similarity index 63% rename from src/Symfony/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandler.php index 4c528b0dd7459..4f383efb054d7 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NativeSqliteSessionStorage. @@ -18,38 +18,30 @@ * * @author Drak */ -class NativeSqliteSessionStorage extends AbstractSessionStorage +class NativeSqliteSessionHandler extends NativeSessionHandler { - /** - * @var string - */ - private $dbPath; - /** * Constructor. * - * @param string $dbPath Path to SQLite database file. - * @param array $options Session configuration options. + * @param string $savePath Path to SQLite database file itself. + * @param array $options Session configuration options. * * @see AbstractSessionStorage::__construct() */ - public function __construct($dbPath, array $options = array()) + public function __construct($savePath, array $options = array()) { if (!extension_loaded('sqlite')) { throw new \RuntimeException('PHP does not have "sqlite" session module registered'); } - $this->dbPath = $dbPath; - parent::__construct($options); - } + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } - /** - * {@inheritdoc} - */ - protected function registerSaveHandlers() - { ini_set('session.save_handler', 'sqlite'); - ini_set('session.save_path', $this->dbPath); + ini_set('session.save_path', $savePath); + + $this->setOptions($options); } /** @@ -66,7 +58,5 @@ protected function setOptions(array $options) ini_set($key, $value); } } - - parent::setOptions($options); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php similarity index 87% rename from src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php index 8f45a6eff2779..0839622aeaa7c 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NullSessionStorage. @@ -20,7 +20,7 @@ * * @api */ -class NullSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class NullSessionHandler implements \SessionHandlerInterface { /** * {@inheritdoc} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php similarity index 97% rename from src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 6465231912e9a..8175090da0b32 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * PdoSessionStorage. @@ -17,7 +17,7 @@ * @author Fabien Potencier * @author Michael Williams */ -class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class PdoSessionHandler implements \SessionHandlerInterface { /** * PDO instance. @@ -58,8 +58,6 @@ public function __construct(\PDO $pdo, array $dbOptions = array(), array $option 'db_data_col' => 'sess_data', 'db_time_col' => 'sess_time', ), $dbOptions); - - parent::__construct($options); } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index 2447418c84393..6f1e279f41654 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + /** * MockArraySessionStorage mocks the session for unit tests. * @@ -23,21 +25,51 @@ * @author Bulat Shakirzyanov * @author Drak */ -class MockArraySessionStorage extends AbstractSessionStorage +class MockArraySessionStorage implements SessionStorageInterface { /** * @var string */ - protected $sessionId; + protected $id = ''; + + /** + * @var string + */ + protected $name; + + /** + * @var boolean + */ + protected $started = false; + + /** + * @var boolean + */ + protected $closed = false; /** * @var array */ - protected $sessionData = array(); + protected $data = array(); + /** + * Constructor. + * + * @param string $name Session name + */ + public function __construct($name = 'MOCKSESSID') + { + $this->name = $name; + } + + /** + * Sets the session data. + * + * @param array $array + */ public function setSessionData(array $array) { - $this->sessionData = $array; + $this->data = $array; } /** @@ -49,11 +81,11 @@ public function start() return true; } - $this->started = true; - $this->loadSession($this->sessionData); + if (empty($this->id)) { + $this->id = $this->generateId(); + } - $this->sessionId = $this->generateSessionId(); - session_id($this->sessionId); + $this->loadSession(); return true; } @@ -64,12 +96,11 @@ public function start() */ public function regenerate($destroy = false) { - if ($this->options['auto_start'] && !$this->started) { + if (!$this->started) { $this->start(); } - $this->sessionId = $this->generateSessionId(); - session_id($this->sessionId); + $this->id = $this->generateId(); return true; } @@ -79,11 +110,35 @@ public function regenerate($destroy = false) */ public function getId() { - if (!$this->started) { - return ''; + return $this->id; + } + + /** + * {@inheritdoc} + */ + public function setId($id) + { + if ($this->started) { + throw new \LogicException('Cannot set session ID after the session has started.'); } - return $this->sessionId; + $this->id = $id; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->name = $name; } /** @@ -106,19 +161,58 @@ public function clear() } // clear out the session - $this->sessionData = array(); + $this->data = array(); // reconnect the bags to the session - $this->loadSession($this->sessionData); + $this->loadSession(); + } + + /** + * {@inheritdoc} + */ + public function registerBag(SessionBagInterface $bag) + { + $this->bags[$bag->getName()] = $bag; + } + + /** + * {@inheritdoc} + */ + public function getBag($name) + { + if (!isset($this->bags[$name])) { + throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + } + + if (!$this->started) { + $this->start(); + } + + return $this->bags[$name]; } /** * Generates a session ID. * + * This doesn't need to be particularly cryptographically secure since this is just + * a mock. + * * @return string */ - protected function generateSessionId() + protected function generateId() { - return sha1(uniqid(mt_rand(), true)); + return sha1(uniqid(mt_rand())); + } + + protected function loadSession() + { + foreach ($this->bags as $bag) { + $key = $bag->getStorageKey(); + $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); + $bag->initialize($this->data[$key]); + } + + $this->started = true; + $this->closed = false; } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index c7c74ddd998ba..24457319f9d62 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -16,7 +16,9 @@ * functional testing when done in a single PHP process. * * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle. + * and shutdown only once per PHP execution cycle and this class does + * not pollute any session related globals, including session_*() functions + * or session.* PHP ini directives. * * @author Drak */ @@ -31,11 +33,9 @@ class MockFileSessionStorage extends MockArraySessionStorage * Constructor. * * @param string $savePath Path of directory to save session files. - * @param array $options Session options. - * - * @see AbstractSessionStorage::__construct() + * @param string $name Session name. */ - public function __construct($savePath = null, array $options = array()) + public function __construct($savePath = null, $name = 'MOCKSESSID') { if (null === $savePath) { $savePath = sys_get_temp_dir(); @@ -47,7 +47,7 @@ public function __construct($savePath = null, array $options = array()) $this->savePath = $savePath; - parent::__construct($options); + parent::__construct($name); } /** @@ -59,12 +59,10 @@ public function start() return true; } - if (!session_id()) { - session_id($this->generateSessionId()); + if (!$this->id) { + $this->id = $this->generateId(); } - $this->sessionId = session_id(); - $this->read(); $this->started = true; @@ -81,10 +79,7 @@ public function regenerate($destroy = false) $this->destroy(); } - session_id($this->generateSessionId()); - $this->sessionId = session_id(); - - $this->save(); + $this->id = $this->generateId(); return true; } @@ -92,23 +87,15 @@ public function regenerate($destroy = false) /** * {@inheritdoc} */ - public function getId() + public function save() { - if (!$this->started) { - return ''; - } - - return $this->sessionId; + file_put_contents($this->getFilePath(), serialize($this->data)); } /** - * {@inheritdoc} + * Deletes a session from persistent storage. + * Deliberately leaves session data in memory intact. */ - public function save() - { - file_put_contents($this->getFilePath(), serialize($this->sessionData)); - } - private function destroy() { if (is_file($this->getFilePath())) { @@ -121,16 +108,19 @@ private function destroy() * * @return string File path */ - public function getFilePath() + private function getFilePath() { - return $this->savePath.'/'.$this->sessionId.'.sess'; + return $this->savePath.'/'.$this->id.'.mocksess'; } + /** + * Reads session from storage and loads session. + */ private function read() { $filePath = $this->getFilePath(); - $this->sessionData = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); + $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); - $this->loadSession($this->sessionData); + $this->loadSession(); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeFileSessionStorage.php deleted file mode 100644 index eca342ec372ee..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeFileSessionStorage.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * 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; - -/** - * NativeFileSessionStorage. - * - * Native session handler using PHP's built in file storage. - * - * @author Drak - */ -class NativeFileSessionStorage extends AbstractSessionStorage -{ - /** - * @var string - */ - private $savePath; - - /** - * Constructor. - * - * @param string $savePath Path of directory to save session files. - * @param array $options Session configuration options. - * - * @see AbstractSessionStorage::__construct() - */ - public function __construct($savePath = null, array $options = array()) - { - if (null === $savePath) { - $savePath = sys_get_temp_dir(); - } - - if (!is_dir($savePath)) { - mkdir($savePath, 0777, true); - } - - $this->savePath = $savePath; - - parent::__construct($options); - } - - /** - * {@inheritdoc} - */ - protected function registerSaveHandlers() - { - ini_set('session.save_handler', 'files'); - ini_set('session.save_path', $this->savePath); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php similarity index 60% rename from src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 4f8fde308f630..be6904ed66acb 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -12,20 +12,16 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * This provides a base class for session attribute storage. * - * This can be used to implement internal PHP session handlers - * provided by PHP extensions or custom session save handlers - * implementing the \SessionHandlerInterface - * - * @see http://php.net/session.customhandler - * @see http://php.net/sessionhandlerinterface - * * @author Drak */ -abstract class AbstractSessionStorage implements SessionStorageInterface +class NativeSessionStorage implements SessionStorageInterface { /** * Array of SessionBagInterface @@ -34,11 +30,6 @@ abstract class AbstractSessionStorage implements SessionStorageInterface */ protected $bags; - /** - * @var array - */ - protected $options = array(); - /** * @var boolean */ @@ -49,6 +40,11 @@ abstract class AbstractSessionStorage implements SessionStorageInterface */ protected $closed = false; + /** + * @var AbstractProxy + */ + protected $saveHandler; + /** * Constructor. * @@ -75,7 +71,6 @@ abstract class AbstractSessionStorage implements SessionStorageInterface * hash_function, "0" * name, "PHPSESSID" * referer_check, "" - * save_path, "" * serialize_handler, "php" * use_cookies, "1" * use_only_cookies, "1" @@ -88,13 +83,34 @@ abstract class AbstractSessionStorage implements SessionStorageInterface * upload_progress.min-freq, "1" * 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. */ - public function __construct(array $options = array()) + public function __construct(array $options = array(), $handler = null) { + // sensible defaults + ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class. + ini_set('session.cache_limiter', ''); // disable by default because it's managed by HeaderBag (if used) + ini_set('session.use_cookies', 1); + + if (version_compare(phpversion(), '5.4.0', '>=')) { + session_register_shutdown(); + } else { + register_shutdown_function('session_write_close'); + } + $this->setOptions($options); - $this->registerSaveHandlers(); - $this->registerShutdownFunction(); + $this->setSaveHandler($handler); + } + + /** + * Gets the save handler instance. + * + * @return AbstractProxy + */ + public function getSaveHandler() + { + return $this->saveHandler; } /** @@ -106,8 +122,16 @@ public function start() return true; } - if ($this->options['use_cookies'] && headers_sent()) { - throw new \RuntimeException('Failed to start the session because header have already been sent.'); + // catch condition where session was started automatically by PHP + if (!$this->started && !$this->closed && $this->saveHandler->isActive() + && $this->saveHandler->isSessionHandlerInterface()) { + $this->loadSession(); + + return true; + } + + if (ini_get('session.use_cookies') && headers_sent()) { + throw new \RuntimeException('Failed to start the session because headers have already been sent.'); } // start the session @@ -117,8 +141,9 @@ public function start() $this->loadSession(); - $this->started = true; - $this->closed = false; + if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { + $this->saveHandler->setActive(false); + } return true; } @@ -132,7 +157,31 @@ public function getId() return ''; // returning empty is consistent with session_id() behaviour } - return session_id(); + return $this->saveHandler->getId(); + } + + /** + * {@inheritdoc} + */ + public function setId($id) + { + return $this->saveHandler->setId($id); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->saveHandler->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->saveHandler->setName($name); } /** @@ -149,6 +198,11 @@ public function regenerate($destroy = false) public function save() { session_write_close(); + + if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) { + $this->saveHandler->setActive(false); + } + $this->closed = true; } @@ -186,8 +240,10 @@ public function getBag($name) throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } - if ($this->options['auto_start'] && !$this->started) { + if (ini_get('session.auto_start') && !$this->started) { $this->start(); + } else if ($this->saveHandler->isActive() && !$this->started) { + $this->loadSession(); } return $this->bags[$name]; @@ -199,38 +255,20 @@ public function getBag($name) * For convenience we omit 'session.' from the beginning of the keys. * Explicitly ignores other ini keys. * - * session_get_cookie_params() overrides values. - * - * @param array $options + * @param array $options Session ini directives array(key => value). * * @see http://php.net/session.configuration */ - protected function setOptions(array $options) + public function setOptions(array $options) { - $this->options = $options; - - // set defaults for certain values - $defaults = array( - 'cache_limiter' => '', // disable by default because it's managed by HeaderBag (if used) - 'auto_start' => false, - 'use_cookies' => true, - 'cookie_httponly' => true, - ); - - foreach ($defaults as $key => $value) { - if (!isset($this->options[$key])) { - $this->options[$key] = $value; - } - } - - foreach ($this->options as $key => $value) { + foreach ($options as $key => $value) { if (in_array($key, array( 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'name', 'referer_check', - 'save_path', 'serialize_handler', 'use_cookies', + 'serialize_handler', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) { @@ -240,7 +278,7 @@ protected function setOptions(array $options) } /** - * Registers this storage device as a PHP session handler. + * Registers save handler as a PHP session handler. * * To use internal PHP session save handlers, override this method using ini_set with * session.save_handlers and session.save_path e.g. @@ -250,34 +288,35 @@ protected function setOptions(array $options) * * @see http://php.net/session-set-save-handler * @see http://php.net/sessionhandlerinterface + * @see http://php.net/sessionhandler + * + * @param object $saveHandler Default null means NativeProxy. */ - protected function registerSaveHandlers() + public function setSaveHandler($saveHandler = null) { - // note this can be reset to PHP's control using ini_set('session.save_handler', 'files'); - // so long as ini_set() is called before the session is started. - if ($this instanceof \SessionHandlerInterface) { - session_set_save_handler( - array($this, 'open'), - array($this, 'close'), - array($this, 'read'), - array($this, 'write'), - array($this, 'destroy'), - array($this, 'gc') - ); + // Wrap $saveHandler in proxy + if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { + $saveHandler = new SessionHandlerProxy($saveHandler); + } elseif (!$saveHandler instanceof AbstractProxy) { + $saveHandler = new NativeProxy($saveHandler); } - } - /** - * Registers PHP shutdown function. - * - * This method is required to avoid strange issues when using PHP objects as - * session save handlers. - * - * @see http://php.net/register-shutdown-function - */ - protected function registerShutdownFunction() - { - register_shutdown_function('session_write_close'); + $this->saveHandler = $saveHandler; + + if ($this->saveHandler instanceof \SessionHandlerInterface) { + if (version_compare(phpversion(), '5.4.0', '>=')) { + session_set_save_handler($this->saveHandler, false); + } else { + session_set_save_handler( + array($this->saveHandler, 'open'), + array($this->saveHandler, 'close'), + array($this->saveHandler, 'read'), + array($this->saveHandler, 'write'), + array($this->saveHandler, 'destroy'), + array($this->saveHandler, 'gc') + ); + } + } } /** @@ -301,5 +340,8 @@ protected function loadSession(array &$session = null) $session[$key] = isset($session[$key]) ? $session[$key] : array(); $bag->initialize($session[$key]); } + + $this->started = true; + $this->closed = false; } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php new file mode 100644 index 0000000000000..09f9efa091dc7 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -0,0 +1,135 @@ + + * + * 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\Proxy; + +/** + * AbstractProxy. + * + * @author Drak + */ +abstract class AbstractProxy +{ + /** + * Flag if handler wraps an internal PHP session handler (using \SessionHandler). + * + * @var boolean + */ + protected $wrapper = false; + + /** + * @var boolean + */ + protected $active = false; + + /** + * @var string + */ + protected $saveHandlerName; + + /** + * Gets the session.save_handler name. + * + * @return string + */ + public function getSaveHandlerName() + { + return $this->saveHandlerName; + } + + /** + * Is this proxy handler and instance of \SessionHandlerInterface. + * + * @return boolean + */ + public function isSessionHandlerInterface() + { + return ($this instanceof \SessionHandlerInterface); + } + + /** + * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. + * + * @return bool + */ + public function isWrapper() + { + return $this->wrapper; + } + + /** + * Has a session started? + * + * @return bool + */ + public function isActive() + { + return $this->active; + } + + /** + * Sets the active flag. + * + * @param bool $flag + */ + public function setActive($flag) + { + $this->active = (bool) $flag; + } + + /** + * Gets the session ID. + * + * @return string + */ + public function getId() + { + return session_id(); + } + + /** + * Sets the session ID. + * + * @param string $id + */ + public function setId($id) + { + if ($this->isActive()) { + throw new \LogicException('Cannot change the ID of an active session'); + } + + session_id($id); + } + + /** + * Gets the session name. + * + * @return string + */ + public function getName() + { + return session_name(); + } + + /** + * Sets the session name. + * + * @param string $name + */ + public function setName($name) + { + if ($this->isActive()) { + throw new \LogicException('Cannot change the name of an active session'); + } + + session_name($name); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php new file mode 100644 index 0000000000000..5bb2c712e32ae --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php @@ -0,0 +1,41 @@ + + * + * 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\Proxy; + +/** + * NativeProxy. + * + * This proxy is built-in session handlers in PHP 5.3.x + * + * @author Drak + */ +class NativeProxy extends AbstractProxy +{ + /** + * Constructor. + */ + public function __construct() + { + // this makes an educated guess as to what the handler is since it should already be set. + $this->saveHandlerName = ini_get('session.save_handler'); + } + + /** + * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. + * + * @return bool False. + */ + public function isWrapper() + { + return false; + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php new file mode 100644 index 0000000000000..e925d628df4a7 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -0,0 +1,95 @@ + + * + * 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\Proxy; + +/** + * SessionHandler proxy. + * + * @author Drak + */ +class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface +{ + /** + * @var \SessionHandlerInterface + */ + protected $handler; + + /** + * Constructor. + * + * @param \SessionHandlerInterface $handler + */ + public function __construct(\SessionHandlerInterface $handler) + { + $this->handler = $handler; + $this->wrapper = ($handler instanceof \SessionHandler); + $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; + } + + // \SessionHandlerInterface + + /** + * {@inheritdoc} + */ + public function open($savePath, $sessionName) + { + $return = (bool)$this->handler->open($savePath, $sessionName); + + if (true === $return) { + $this->active = true; + } + + return $return; + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->active = false; + + return (bool) $this->handler->close(); + } + + /** + * {@inheritdoc} + */ + public function read($id) + { + return (string) $this->handler->read($id); + } + + /** + * {@inheritdoc} + */ + public function write($id, $data) + { + return (bool) $this->handler->write($id, $data); + } + + /** + * {@inheritdoc} + */ + public function destroy($id) + { + return (bool) $this->handler->destroy($id); + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime) + { + return (bool) $this->handler->gc($maxlifetime); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php index 6065a550dc8c3..8bf2e5d32ad02 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php @@ -37,12 +37,39 @@ function start(); /** * Returns the session ID * - * @return mixed The session ID or false if the session has not started. + * @return string The session ID or empty. * * @api */ function getId(); + /** + * Sets the session ID + * + * @param string $id + * + * @api + */ + function setId($id); + + /** + * Returns the session name + * + * @return mixed The session name. + * + * @api + */ + function getName(); + + /** + * Sets the session name + * + * @param string $name + * + * @api + */ + function setName($name); + /** * Regenerates id that represents this storage. * @@ -51,6 +78,9 @@ function getId(); * or functional testing where a real PHP session would interfere * with testing. * + * Note regenerate+destroy should not clear the session data in memory + * only delete the session data from persistent storage. + * * @param Boolean $destroy Destroy session when regenerating? * * @return Boolean True if session regenerated, false if error diff --git a/tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionStorageTest.php b/tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerTest.php similarity index 80% rename from tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionStorageTest.php rename to tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerTest.php index 428f065c1a2c5..eda2dac30d196 100644 --- a/tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionStorageTest.php +++ b/tests/Symfony/Tests/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerTest.php @@ -11,19 +11,19 @@ namespace Symfony\Bridge\Doctrine\HttpFoundation; -use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionStorage; +use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler; /** * Test class for DbalSessionStorage. * * @author Drak */ -class DbalSessionStorageTest extends \PHPUnit_Framework_TestCase +class DbalSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function test__Construct() { $this->connection = $this->getMock('Doctrine\DBAL\Driver\Connection'); - $mock = $this->getMockBuilder('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionStorage'); + $mock = $this->getMockBuilder('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler'); $mock->setConstructorArgs(array($this->connection)); $this->driver = $mock->getMock(); } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php index 3e672da273dde..136b8fc95be65 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php @@ -866,7 +866,7 @@ public function testForwardedSecure() public function testHasSession() { - $request = new Request; + $request = new Request(); $this->assertFalse($request->hasSession()); $request->setSession(new Session(new MockArraySessionStorage())); @@ -875,10 +875,10 @@ public function testHasSession() public function testHasPreviousSession() { - $request = new Request; + $request = new Request(); $this->assertFalse($request->hasPreviousSession()); - $request->cookies->set(session_name(), 'foo'); + $request->cookies->set('MOCKSESSID', 'foo'); $this->assertFalse($request->hasPreviousSession()); $request->setSession(new Session(new MockArraySessionStorage())); $this->assertTrue($request->hasPreviousSession()); diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcacheSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandlerTest.php similarity index 91% rename from tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcacheSessionStorageTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandlerTest.php index 1cdbe2a3a9a16..3d4adfab47f64 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcacheSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -1,10 +1,10 @@ memcache = $this->getMock('Memcache'); - $this->storage = new MemcacheSessionStorage($this->memcache); + $this->storage = new MemcacheSessionHandler($this->memcache); } protected function tearDown() @@ -42,7 +42,7 @@ public function testConstructingWithServerPool() { $mock = $this->getMock('Memcache'); - $storage = new MemcacheSessionStorage($mock, array( + $storage = new MemcacheSessionHandler($mock, array( 'serverpool' => array( array('host' => '127.0.0.2'), array('host' => '127.0.0.3', diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcachedSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandlerTest.php similarity index 86% rename from tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcachedSessionStorageTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandlerTest.php index cc8d0bee3554b..1fca44445e1a0 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MemcachedSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -1,13 +1,13 @@ memcached = $this->getMock('Memcached'); - $this->storage = new MemcachedSessionStorage($this->memcached); + $this->storage = new MemcachedSessionHandler($this->memcached); } protected function tearDown() diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandlerTest.php new file mode 100644 index 0000000000000..c6a4495225d3b --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -0,0 +1,40 @@ + + * + * @runTestsInSeparateProcesses + */ +class NativeFileSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testConstruct() + { + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('files', ini_get('session.save_handler')); + } else { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } + + public function testConstructDefault() + { + $path = ini_get('session.save_path'); + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler()); + + $this->assertEquals($path, ini_get('session.save_path')); + } +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php new file mode 100644 index 0000000000000..3dbcb4f7f81ba --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcacheSessionHandlerTest.php @@ -0,0 +1,36 @@ + + * + * @runTestsInSeparateProcesses + */ +class NativeMemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('memcache')) { + $this->markTestSkipped('Skipped tests SQLite extension is not present'); + } + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeMemcacheSessionHandler('tcp://127.0.0.1:11211?persistent=0')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('memcache', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('memcache', ini_get('session.save_handler')); + } else { + $this->assertEquals('memcache', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals('tcp://127.0.0.1:11211?persistent=0', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php new file mode 100644 index 0000000000000..a85fbdd056f4c --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeMemcachedSessionHandlerTest.php @@ -0,0 +1,40 @@ + + * + * @runTestsInSeparateProcesses + */ +class NativeMemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('memcached')) { + $this->markTestSkipped('Skipped tests SQLite extension is not present'); + } + + // test takes too long if memcached server is not running + ini_set('memcached.sess_locking', '0'); + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeMemcachedSessionHandler('127.0.0.1:11211')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('memcached', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('memcached', ini_get('session.save_handler')); + } else { + $this->assertEquals('memcached', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals('127.0.0.1:11211', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} + diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php new file mode 100644 index 0000000000000..9867e49590edd --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NativeSqliteSessionHandlerTest.php @@ -0,0 +1,38 @@ + + * + * @runTestsInSeparateProcesses + */ +class NativeSqliteSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testSaveHandlers() + { + if (!extension_loaded('sqlite')) { + $this->markTestSkipped('Skipped tests SQLite extension is not present'); + } + + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeSqliteSessionHandler(sys_get_temp_dir().'/sqlite.db')); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('sqlite', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('sqlite', ini_get('session.save_handler')); + } else { + $this->assertEquals('sqlite', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + + $this->assertEquals(sys_get_temp_dir().'/sqlite.db', ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } +} + diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NullSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandlerTest.php similarity index 68% rename from tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NullSessionStorageTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandlerTest.php index 66599f68b3cef..e0c883e7c3f40 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NullSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandlerTest.php @@ -1,11 +1,12 @@ * @@ -15,14 +16,14 @@ class NullSessionStorageTest extends \PHPUnit_Framework_TestCase { public function testSaveHandlers() { - $storage = new NullSessionStorage(); + $storage = $this->getStorage(); $this->assertEquals('user', ini_get('session.save_handler')); } public function testSession() { session_id('nullsessionstorage'); - $storage = new NullSessionStorage(); + $storage = $this->getStorage(); $session = new Session($storage); $this->assertNull($session->get('something')); $session->set('something', 'unique'); @@ -32,11 +33,16 @@ public function testSession() public function testNothingIsPersisted() { session_id('nullsessionstorage'); - $storage = new NullSessionStorage(); + $storage = $this->getStorage(); $session = new Session($storage); $session->start(); $this->assertEquals('nullsessionstorage', $session->getId()); $this->assertNull($session->get('something')); } + + public function getStorage() + { + return new NativeSessionStorage(array(), new NullSessionHandler()); + } } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/PdoSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandlerTest.php similarity index 79% rename from tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/PdoSessionStorageTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandlerTest.php index 6a6fd6760a8ed..8f921334ae52c 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/PdoSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -9,11 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Tests\Component\HttpFoundation\Session\Storage; +namespace Symfony\Tests\Component\HttpFoundation\Session\Storage\Handler; -use Symfony\Component\HttpFoundation\Session\Storage\PdoSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; -class PdoSessionStorageTest extends \PHPUnit_Framework_TestCase +class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase { private $pdo; @@ -26,16 +26,16 @@ protected function setUp() public function testMultipleInstances() { - $storage1 = new PdoSessionStorage($this->pdo, array('db_table' => 'sessions'), array()); + $storage1 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage1->write('foo', 'bar'); - $storage2 = new PdoSessionStorage($this->pdo, array('db_table' => 'sessions'), array()); + $storage2 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $this->assertEquals('bar', $storage2->read('foo'), 'values persist between instances'); } public function testSessionDestroy() { - $storage = new PdoSessionStorage($this->pdo, array('db_table' => 'sessions'), array()); + $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage->write('foo', 'bar'); $this->assertEquals(1, count($this->pdo->query('SELECT * FROM sessions')->fetchAll())); @@ -46,7 +46,7 @@ public function testSessionDestroy() public function testSessionGC() { - $storage = new PdoSessionStorage($this->pdo, array('db_table' => 'sessions'), array()); + $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage->write('foo', 'bar'); $storage->write('baz', 'bar'); diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MockFileSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MockFileSessionStorageTest.php index 770bcda8f00ec..c0453df9779c4 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MockFileSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/MockFileSessionStorageTest.php @@ -69,6 +69,7 @@ public function testGetId() public function testSave() { $this->storage->start(); + $id = $this->storage->getId(); $this->assertNotEquals('108', $this->storage->getBag('attributes')->get('new')); $this->assertFalse($this->storage->getBag('flashes')->has('newkey')); $this->storage->getBag('attributes')->set('new', '108'); @@ -76,6 +77,7 @@ public function testSave() $this->storage->save(); $storage = $this->getStorage(); + $storage->setId($id); $storage->start(); $this->assertEquals('108', $storage->getBag('attributes')->get('new')); $this->assertTrue($storage->getBag('flashes')->has('newkey')); @@ -90,13 +92,14 @@ public function testMultipleInstances() $storage1->save(); $storage2 = $this->getStorage(); + $storage2->setId($storage1->getId()); $storage2->start(); $this->assertEquals('bar', $storage2->getBag('attributes')->get('foo'), 'values persist between instances'); } - private function getStorage(array $options = array()) + private function getStorage() { - $storage = new MockFileSessionStorage($this->sessionDir, $options); + $storage = new MockFileSessionStorage($this->sessionDir); $storage->registerBag(new FlashBag); $storage->registerBag(new AttributeBag); diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeFileSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeFileSessionStorageTest.php deleted file mode 100644 index df3ef95cbf799..0000000000000 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeFileSessionStorageTest.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @runTestsInSeparateProcesses - */ -class NativeFileSessionStorageTest extends \PHPUnit_Framework_TestCase -{ - public function testSaveHandlers() - { - $storage = new NativeFileSessionStorage(sys_get_temp_dir(), array('name' => 'TESTING')); - $this->assertEquals('files', ini_get('session.save_handler')); - $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); - $this->assertEquals('TESTING', ini_get('session.name')); - } -} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorageTest.php deleted file mode 100644 index 4274ed5bd1496..0000000000000 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcacheSessionStorageTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * @runTestsInSeparateProcesses - */ -class NativeMemcacheSessionStorageTest extends \PHPUnit_Framework_TestCase -{ - public function testSaveHandlers() - { - if (!extension_loaded('memcache')) { - $this->markTestSkipped('Skipped tests SQLite extension is not present'); - } - - $storage = new NativeMemcacheSessionStorage('tcp://127.0.0.1:11211?persistent=0', array('name' => 'TESTING')); - $this->assertEquals('memcache', ini_get('session.save_handler')); - $this->assertEquals('tcp://127.0.0.1:11211?persistent=0', ini_get('session.save_path')); - $this->assertEquals('TESTING', ini_get('session.name')); - } -} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorageTest.php deleted file mode 100644 index c0a12aa2b4d15..0000000000000 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeMemcachedSessionStorageTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * @runTestsInSeparateProcesses - */ -class NativeMemcachedSessionStorageTest extends \PHPUnit_Framework_TestCase -{ - public function testSaveHandlers() - { - if (!extension_loaded('memcached')) { - $this->markTestSkipped('Skipped tests SQLite extension is not present'); - } - - // test takes too long if memcached server is not running - ini_set('memcached.sess_locking', '0'); - - $storage = new NativeMemcachedSessionStorage('127.0.0.1:11211', array('name' => 'TESTING')); - - $this->assertEquals('memcached', ini_get('session.save_handler')); - $this->assertEquals('127.0.0.1:11211', ini_get('session.save_path')); - $this->assertEquals('TESTING', ini_get('session.name')); - } -} - diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSessionStorageTest.php similarity index 62% rename from tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSessionStorageTest.php index 8d53002c8d0fb..26f6113448011 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSessionStorageTest.php @@ -2,46 +2,12 @@ namespace Symfony\Tests\Component\HttpFoundation\Session\Storage; -use Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -/** - * Turn AbstractSessionStorage into something concrete because - * certain mocking features are broken in PHPUnit-Mock-Objects < 1.1.2 - * @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/73 - */ -class ConcreteSessionStorage extends AbstractSessionStorage -{ -} - -class CustomHandlerSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface -{ - public function open($path, $id) - { - } - - public function close() - { - } - - public function read($id) - { - } - - public function write($id, $data) - { - } - - public function destroy($id) - { - } - - public function gc($lifetime) - { - } -} - /** * Test class for AbstractSessionStorage. * @@ -51,14 +17,14 @@ public function gc($lifetime) * * @runTestsInSeparateProcesses */ -class AbstractSessionStorageTest extends \PHPUnit_Framework_TestCase +class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase { /** - * @return AbstractSessionStorage + * @return NativeSessionStorage */ - protected function getStorage($options = array()) + protected function getStorage(array $options = array()) { - $storage = new CustomHandlerSessionStorage($options); + $storage = new NativeSessionStorage($options); $storage->registerBag(new AttributeBag); return $storage; @@ -112,23 +78,11 @@ public function testRegenerateDestroy() $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); } - public function testCustomSaveHandlers() - { - $storage = new CustomHandlerSessionStorage(); - $this->assertEquals('user', ini_get('session.save_handler')); - } - - public function testNativeSaveHandlers() - { - $storage = new ConcreteSessionStorage(); - $this->assertNotEquals('user', ini_get('session.save_handler')); - } - public function testDefaultSessionCacheLimiter() { ini_set('session.cache_limiter', 'nocache'); - $storage = new ConcreteSessionStorage(); + $storage = new NativeSessionStorage(); $this->assertEquals('', ini_get('session.cache_limiter')); } @@ -136,7 +90,7 @@ public function testExplicitSessionCacheLimiter() { ini_set('session.cache_limiter', 'nocache'); - $storage = new ConcreteSessionStorage(array('cache_limiter' => 'public')); + $storage = new NativeSessionStorage(array('cache_limiter' => 'public')); $this->assertEquals('public', ini_get('session.cache_limiter')); } @@ -160,4 +114,33 @@ public function testCookieOptions() $this->assertEquals($options, $gco); } + + public function testSetSaveHandler() + { + $storage = $this->getStorage(); + $storage->setSaveHandler(new \StdClass()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); + } + + public function testSetSaveHandlerPHP53() + { + if (version_compare(phpversion(), '5.4.0', '>=')) { + $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); + } + + $storage = $this->getStorage(); + $storage->setSaveHandler(new NativeFileSessionHandler()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); + } + + public function testSetSaveHandlerPHP54() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->markTestSkipped('Test skipped, for PHP 5.4+ only.'); + } + + $storage = $this->getStorage(); + $storage->setSaveHandler(new NullSessionHandler()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); + } } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorageTest.php deleted file mode 100644 index b1700326b1d8a..0000000000000 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/NativeSqliteSessionStorageTest.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * @runTestsInSeparateProcesses - */ -class NativeSqliteSessionStorageTest extends \PHPUnit_Framework_TestCase -{ - public function testSaveHandlers() - { - if (!extension_loaded('sqlite')) { - $this->markTestSkipped('Skipped tests SQLite extension is not present'); - } - - $storage = new NativeSqliteSessionStorage(sys_get_temp_dir().'/sqlite.db', array('name' => 'TESTING')); - $this->assertEquals('sqlite', ini_get('session.save_handler')); - $this->assertEquals(sys_get_temp_dir().'/sqlite.db', ini_get('session.save_path')); - $this->assertEquals('TESTING', ini_get('session.name')); - } -} - diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxyTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxyTest.php new file mode 100644 index 0000000000000..6850f5b81ef94 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxyTest.php @@ -0,0 +1,132 @@ + + */ +class AbstractProxyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AbstractProxy + */ + protected $proxy; + + protected function setUp() + { + $this->proxy = new ConcreteProxy(); + } + + protected function tearDown() + { + $this->proxy = null; + } + + public function testGetSaveHandlerName() + { + $this->assertNull($this->proxy->getSaveHandlerName()); + } + + public function testIsSessionHandlerInterface() + { + $this->assertFalse($this->proxy->isSessionHandlerInterface()); + $sh = new ConcreteSessionHandlerInterfaceProxy(); + $this->assertTrue($sh->isSessionHandlerInterface()); + } + + public function testIsWrapper() + { + $this->assertFalse($this->proxy->isWrapper()); + } + + public function testIsActive() + { + $this->assertFalse($this->proxy->isActive()); + } + + public function testSetActive() + { + $this->proxy->setActive(true); + $this->assertTrue($this->proxy->isActive()); + $this->proxy->setActive(false); + $this->assertFalse($this->proxy->isActive()); + } + + /** + * @runInSeparateProcess + */ + public function testName() + { + $this->assertEquals(session_name(), $this->proxy->getName()); + $this->proxy->setName('foo'); + $this->assertEquals('foo', $this->proxy->getName()); + $this->assertEquals(session_name(), $this->proxy->getName()); + } + + /** + * @expectedException \LogicException + */ + public function testNameException() + { + $this->proxy->setActive(true); + $this->proxy->setName('foo'); + } + + /** + * @runInSeparateProcess + */ + public function testId() + { + $this->assertEquals(session_id(), $this->proxy->getId()); + $this->proxy->setId('foo'); + $this->assertEquals('foo', $this->proxy->getId()); + $this->assertEquals(session_id(), $this->proxy->getId()); + } + + /** + * @expectedException \LogicException + */ + public function testIdException() + { + $this->proxy->setActive(true); + $this->proxy->setId('foo'); + } +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/NativeProxyTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/NativeProxyTest.php new file mode 100644 index 0000000000000..0dc0ce92a3a56 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/NativeProxyTest.php @@ -0,0 +1,27 @@ + + */ +class NativeProxyTest extends \PHPUnit_Framework_TestCase +{ + public function testIsWrapper() + { + $proxy = new NativeProxy(); + $this->assertFalse($proxy->isWrapper()); + } + + public function testGetSaveHandlerName() + { + $name = ini_get('session.save_handler'); + $proxy = new NativeProxy(); + $this->assertEquals($name, $proxy->getSaveHandlerName()); + } +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxyTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxyTest.php new file mode 100644 index 0000000000000..61393f3102e0b --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -0,0 +1,113 @@ + + * + * @runTestsInSeparateProcesses + */ +class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var PHPUnit_Framework_MockObject_Matcher + */ + private $mock; + + /** + * @var SessionHandlerProxy + */ + private $proxy; + + protected function setUp() + { + $this->mock = $this->getMock('SessionHandlerInterface'); + $this->proxy = new SessionHandlerProxy($this->mock); + } + + protected function tearDown() + { + $this->mock = null; + $this->proxy = null; + } + + public function testOpen() + { + $this->mock->expects($this->once()) + ->method('open') + ->will($this->returnValue(true)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->open('name', 'id'); + $this->assertTrue($this->proxy->isActive()); + } + + public function testOpenFalse() + { + $this->mock->expects($this->once()) + ->method('open') + ->will($this->returnValue(false)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->open('name', 'id'); + $this->assertFalse($this->proxy->isActive()); + } + + public function testClose() + { + $this->mock->expects($this->once()) + ->method('close') + ->will($this->returnValue(true)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->close(); + $this->assertFalse($this->proxy->isActive()); + } + + public function testCloseFalse() + { + $this->mock->expects($this->once()) + ->method('close') + ->will($this->returnValue(false)); + + $this->assertFalse($this->proxy->isActive()); + $this->proxy->close(); + $this->assertFalse($this->proxy->isActive()); + } + + public function testRead() + { + $this->mock->expects($this->once()) + ->method('read'); + + $this->proxy->read('id'); + } + + public function testWrite() + { + $this->mock->expects($this->once()) + ->method('write'); + + $this->proxy->write('id', 'data'); + } + + public function testDestroy() + { + $this->mock->expects($this->once()) + ->method('destroy'); + + $this->proxy->destroy('id'); + } + + public function testGc() + { + $this->mock->expects($this->once()) + ->method('gc'); + + $this->proxy->gc(86400); + } +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/EventListener/LocaleListenerTest.php b/tests/Symfony/Tests/Component/HttpKernel/EventListener/LocaleListenerTest.php index ecce76ec5eef4..d8cac3857c896 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/EventListener/LocaleListenerTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/EventListener/LocaleListenerTest.php @@ -33,7 +33,7 @@ public function testDefaultLocaleWithSession() session_name('foo'); $request->cookies->set('foo', 'value'); - $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('get'), array(), '', false); + $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('get'), array(), '', true); $session->expects($this->once())->method('get')->will($this->returnValue('es')); $request->setSession($session); @@ -55,7 +55,7 @@ public function testLocaleFromRequestAttribute() $event = $this->getEvent($request); // also updates the session _locale value - $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('set', 'get'), array(), '', false); + $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('set', 'get'), array(), '', true); $session->expects($this->once())->method('set')->with('_locale', 'es'); $session->expects($this->once())->method('get')->with('_locale')->will($this->returnValue('es')); $request->setSession($session);