From d339e74bc5552dc2662439c7cfe332066a55bf37 Mon Sep 17 00:00:00 2001 From: Drak Date: Thu, 16 Feb 2012 08:25:55 +0545 Subject: [PATCH 1/5] [ClassLoader] Add ability to incrementally register fallbacks. This is useful in the cases where you might be adding forward compat classes to several components. --- .../ClassLoader/UniversalClassLoader.php | 22 ++++++++++++++++++- .../ClassLoader/UniversalClassLoaderTest.php | 14 ++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/ClassLoader/UniversalClassLoader.php b/src/Symfony/Component/ClassLoader/UniversalClassLoader.php index f67a127e3d..60f245ad1b 100644 --- a/src/Symfony/Component/ClassLoader/UniversalClassLoader.php +++ b/src/Symfony/Component/ClassLoader/UniversalClassLoader.php @@ -141,7 +141,17 @@ class UniversalClassLoader } /** - * Registers the directory to use as a fallback for class prefixes. + * Registers a directory to use as a fallback for namespaces. + * + * @param string $dir A directory + */ + public function registerNamespaceFallback($dir) + { + $this->namespaceFallbacks[] = $dir; + } + + /** + * Registers directories to use as a fallback for class prefixes. * * @param array $dirs An array of directories * @@ -152,6 +162,16 @@ class UniversalClassLoader $this->prefixFallbacks = $dirs; } + /** + * Registers a directory to use as a fallback for class prefixes. + * + * @param string $dir A directory + */ + public function registerPrefixFallback($dir) + { + $this->prefixFallbacks[] = $dir; + } + /** * Registers an array of namespaces * diff --git a/tests/Symfony/Tests/Component/ClassLoader/UniversalClassLoaderTest.php b/tests/Symfony/Tests/Component/ClassLoader/UniversalClassLoaderTest.php index 92a4eeda06..a1fbfa5031 100644 --- a/tests/Symfony/Tests/Component/ClassLoader/UniversalClassLoaderTest.php +++ b/tests/Symfony/Tests/Component/ClassLoader/UniversalClassLoaderTest.php @@ -80,6 +80,20 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase ); } + public function testRegisterPrefixFallback() + { + $loader = new UniversalClassLoader(); + $loader->registerPrefixFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'); + $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'), $loader->getPrefixFallbacks()); + } + + public function testRegisterNamespaceFallback() + { + $loader = new UniversalClassLoader(); + $loader->registerNamespaceFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'); + $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'), $loader->getNamespaceFallbacks()); + } + /** * @dataProvider getLoadClassNamespaceCollisionTests */ From e585ca783d5dfdee9f70662c02421cb0a88be337 Mon Sep 17 00:00:00 2001 From: Drak Date: Thu, 16 Feb 2012 08:27:50 +0545 Subject: [PATCH 2/5] [HttpFoundation] Added forward compatibility for \SessionHandlerInterface --- autoload.php.dist | 5 +- .../stubs/SessionHandlerInterface.php | 155 ++++++++++++++++ .../Storage/AbstractSessionStorage.php | 7 +- .../Storage/MemcacheSessionStorage.php | 2 +- .../Storage/MemcachedSessionStorage.php | 2 +- .../Session/Storage/NullSessionStorage.php | 2 +- .../Session/Storage/PdoSessionStorage.php | 2 +- .../Storage/SessionHandlerInterface.php | 167 ------------------ .../Storage/AbstractSessionStorageTest.php | 3 +- 9 files changed, 165 insertions(+), 180 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/SessionHandlerInterface.php diff --git a/autoload.php.dist b/autoload.php.dist index a69f5f1925..54278e28dd 100644 --- a/autoload.php.dist +++ b/autoload.php.dist @@ -20,7 +20,10 @@ $loader->registerPrefixes(array( if (!function_exists('intl_get_error_code')) { require_once __DIR__.'/src/Symfony/Component/Locale/Resources/stubs/functions.php'; - $loader->registerPrefixFallbacks(array(__DIR__.'/src/Symfony/Component/Locale/Resources/stubs')); + $loader->registerPrefixFallback(__DIR__.'/src/Symfony/Component/Locale/Resources/stubs'); +} +if (!interface_exists('SessionHandlerInterface', false)) { + $loader->registerPrefixFallback(__DIR__.'/src/Symfony/Component/HttpFoundation/Resources/stubs'); } $loader->register(); diff --git a/src/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php b/src/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php new file mode 100644 index 0000000000..24b9648cb7 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Session Savehandler Interface. + * + * This interface is for implementing methods required for the + * session_set_save_handler() function. + * + * @see http://php.net/session_set_save_handler + * + * These are methods called by PHP when the session is started + * and closed and for various house-keeping tasks required + * by session management. + * + * PHP requires session save handlers. There are some defaults set + * automatically when PHP starts, but these can be overriden using + * this command if you need anything other than PHP's default handling. + * + * When the session starts, PHP will call the read() handler + * which should return a string extactly as stored (which will have + * been encoded by PHP using a special session serializer session_decode() + * which is different to the serialize() function. PHP will then populate + * these into $_SESSION. + * + * When PHP shuts down, the write() handler is called and will pass + * the $_SESSION contents already serialized (using session_encode()) to + * be stored. + * + * When a session is specifically destroyed, PHP will call the + * destroy() handler with the session ID. This happens when the + * session is regenerated for example and th handler MUST delete the + * session by ID from the persistent storage immediately. + * + * PHP will call gc() from time to time to expire any session + * records according to the set max lifetime of a session. This routine + * should delete all records from persistent storage which were last + * accessed longer than the $lifetime. + * + * PHP open() and close() are pretty much redundant and + * can return true. + * + * @author Drak + */ +interface SessionHandlerInterface +{ + /** + * Open session. + * + * This method is for internal use by PHP and must not be called manually. + * + * @param string $savePath Save path. + * @param string $sessionName Session Name. + * + * @throws \RuntimeException If something goes wrong starting the session. + * + * @return boolean + */ + function open($savePath, $sessionName); + + /** + * Close session. + * + * This method is for internal use by PHP and must not be called manually. + * + * @return boolean + */ + function close(); + + /** + * Read session. + * + * This method is for internal use by PHP and must not be called manually. + * + * This method is called by PHP itself when the session is started. + * This method should retrieve the session data from storage by the + * ID provided by PHP. Return the string directly as is from storage. + * If the record was not found you must return an empty string. + * + * The returned data will be unserialized automatically by PHP using a + * special unserializer method session_decode() and the result will be used + * to populate the $_SESSION superglobal. This is done automatically and + * is not configurable. + * + * @param string $sessionId Session ID. + * + * @throws \RuntimeException On fatal error but not "record not found". + * + * @return string String as stored in persistent storage or empty string in all other cases. + */ + function read($sessionId); + + /** + * Commit session to storage. + * + * This method is for internal use by PHP and must not be called manually. + * + * PHP will call this method when the session is closed. It sends + * the session ID and the contents of $_SESSION to be saved in a lightweight + * serialized format (which PHP does automatically using session_encode() + * which should be stored exactly as is given in $data. + * + * Note this method is normally called by PHP after the output buffers + * have been closed. + * + * @param string $sessionId Session ID. + * @param string $data Session serialized data to save. + * + * @throws \RuntimeException On fatal error. + * + * @return boolean + */ + function write($sessionId, $data); + + /** + * Destroys this session. + * + * This method is for internal use by PHP and must not be called manually. + * + * PHP will call this method when the session data associated + * with the session ID provided needs to be immediately + * deleted from the permanent storage. + * + * @param string $sessionId Session ID. + * + * @throws \RuntimeException On fatal error. + * + * @return boolean + */ + function destroy($sessionId); + + /** + * Garbage collection for storage. + * + * This method is for internal use by PHP and must not be called manually. + * + * This method is called by PHP periodically and passes the maximum + * time a session can exist for before being deleted from permanent storage. + * + * @param integer $lifetime Max lifetime in seconds to keep sessions stored. + * + * @throws \RuntimeException On fatal error. + * + * @return boolean + */ + function gc($lifetime); +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php index 968a15c1a6..9fcabab593 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php @@ -13,11 +13,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -// force load forward compatability for PHP 5.4's SessionHandlerInterface if necessary. -if (version_compare(phpversion(), '5.4.0', '<')) { - interface_exists('Symfony\Component\HttpFoundation\Session\Storage\SessionHandlerInterface'); -} - /** * This provides a base class for session attribute storage. * @@ -283,7 +278,7 @@ abstract class AbstractSessionStorage implements SessionStorageInterface { // 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 || $this instanceof SessionHandlerInterface) { + if ($this instanceof \SessionHandlerInterface) { session_set_save_handler( array($this, 'open'), array($this, 'close'), diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php index 70be3e913c..c9b0ca5dad 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MemcacheSessionStorage.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * * @author Drak */ -class MemcacheSessionStorage extends AbstractSessionStorage implements SessionHandlerInterface +class MemcacheSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface { /** * Memcache driver. diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php index 340d0db808..00e5242510 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MemcachedSessionStorage.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * * @author Drak */ -class MemcachedSessionStorage extends AbstractSessionStorage implements SessionHandlerInterface +class MemcachedSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface { /** * Memcached driver. diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php index 531775327e..8f45a6eff2 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NullSessionStorage.php @@ -20,7 +20,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * * @api */ -class NullSessionStorage extends AbstractSessionStorage implements SessionHandlerInterface +class NullSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface { /** * {@inheritdoc} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php index 4d01604a33..da76694597 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php @@ -17,7 +17,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * @author Fabien Potencier * @author Michael Williams */ -class PdoSessionStorage extends AbstractSessionStorage implements SessionHandlerInterface +class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface { /** * PDO instance. diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionHandlerInterface.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionHandlerInterface.php deleted file mode 100644 index 1d2dbc20f8..0000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionHandlerInterface.php +++ /dev/null @@ -1,167 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace -{ - if (!interface_exists('SessionHandlerInterface', false)) { - /** - * Session Savehandler Interface. - * - * This interface is for implementing methods required for the - * session_set_save_handler() function. - * - * @see http://php.net/session_set_save_handler - * - * These are methods called by PHP when the session is started - * and closed and for various house-keeping tasks required - * by session management. - * - * PHP requires session save handlers. There are some defaults set - * automatically when PHP starts, but these can be overriden using - * this command if you need anything other than PHP's default handling. - * - * When the session starts, PHP will call the read() handler - * which should return a string extactly as stored (which will have - * been encoded by PHP using a special session serializer session_decode() - * which is different to the serialize() function. PHP will then populate - * these into $_SESSION. - * - * When PHP shuts down, the write() handler is called and will pass - * the $_SESSION contents already serialized (using session_encode()) to - * be stored. - * - * When a session is specifically destroyed, PHP will call the - * destroy() handler with the session ID. This happens when the - * session is regenerated for example and th handler MUST delete the - * session by ID from the persistent storage immediately. - * - * PHP will call gc() from time to time to expire any session - * records according to the set max lifetime of a session. This routine - * should delete all records from persistent storage which were last - * accessed longer than the $lifetime. - * - * PHP open() and close() are pretty much redundant and - * can return true. - * - * @author Drak - */ - interface SessionHandlerInterface - { - /** - * Open session. - * - * This method is for internal use by PHP and must not be called manually. - * - * @param string $savePath Save path. - * @param string $sessionName Session Name. - * - * @throws \RuntimeException If something goes wrong starting the session. - * - * @return boolean - */ - function open($savePath, $sessionName); - - /** - * Close session. - * - * This method is for internal use by PHP and must not be called manually. - * - * @return boolean - */ - function close(); - - /** - * Read session. - * - * This method is for internal use by PHP and must not be called manually. - * - * This method is called by PHP itself when the session is started. - * This method should retrieve the session data from storage by the - * ID provided by PHP. Return the string directly as is from storage. - * If the record was not found you must return an empty string. - * - * The returned data will be unserialized automatically by PHP using a - * special unserializer method session_decode() and the result will be used - * to populate the $_SESSION superglobal. This is done automatically and - * is not configurable. - * - * @param string $sessionId Session ID. - * - * @throws \RuntimeException On fatal error but not "record not found". - * - * @return string String as stored in persistent storage or empty string in all other cases. - */ - function read($sessionId); - - /** - * Commit session to storage. - * - * This method is for internal use by PHP and must not be called manually. - * - * PHP will call this method when the session is closed. It sends - * the session ID and the contents of $_SESSION to be saved in a lightweight - * serialized format (which PHP does automatically using session_encode() - * which should be stored exactly as is given in $data. - * - * Note this method is normally called by PHP after the output buffers - * have been closed. - * - * @param string $sessionId Session ID. - * @param string $data Session serialized data to save. - * - * @throws \RuntimeException On fatal error. - * - * @return boolean - */ - function write($sessionId, $data); - - /** - * Destroys this session. - * - * This method is for internal use by PHP and must not be called manually. - * - * PHP will call this method when the session data associated - * with the session ID provided needs to be immediately - * deleted from the permanent storage. - * - * @param string $sessionId Session ID. - * - * @throws \RuntimeException On fatal error. - * - * @return boolean - */ - function destroy($sessionId); - - /** - * Garbage collection for storage. - * - * This method is for internal use by PHP and must not be called manually. - * - * This method is called by PHP periodically and passes the maximum - * time a session can exist for before being deleted from permanent storage. - * - * @param integer $lifetime Max lifetime in seconds to keep sessions stored. - * - * @throws \RuntimeException On fatal error. - * - * @return boolean - */ - function gc($lifetime); - } - } -} - -namespace Symfony\Component\HttpFoundation\Session\Storage -{ - interface SessionHandlerInterface extends \SessionHandlerInterface - { - } -} \ No newline at end of file diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php index 9f391ca825..d442e8a70b 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/Storage/AbstractSessionStorageTest.php @@ -5,7 +5,6 @@ namespace Symfony\Tests\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\AbstractSessionStorage; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Storage\SessionHandlerInterface; /** * Turn AbstractSessionStorage into something concrete because @@ -16,7 +15,7 @@ class ConcreteSessionStorage extends AbstractSessionStorage { } -class CustomHandlerSessionStorage extends AbstractSessionStorage implements SessionHandlerInterface +class CustomHandlerSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface { public function open($path, $id) { From dd2c4aa61f3c327a43ee4aeb669a8c0eabdd9dc4 Mon Sep 17 00:00:00 2001 From: Drak Date: Thu, 16 Feb 2012 08:34:09 +0545 Subject: [PATCH 3/5] [HttpFoundation] Documentation. --- src/Symfony/Component/HttpFoundation/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/README.md b/src/Symfony/Component/HttpFoundation/README.md index 67823e7f70..88adfed759 100644 --- a/src/Symfony/Component/HttpFoundation/README.md +++ b/src/Symfony/Component/HttpFoundation/README.md @@ -28,6 +28,17 @@ And here is how to create and send a Response: The Request and the Response classes have many other methods that implement the HTTP specification. +Loading +------- + +If you are using PHP 5.3.x you must add the following to your autoloader: + + // SessionHandlerInterface + if (!interface_exists('SessionHandlerInterface')) { + $loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs'); + } + + Resources --------- From ff8d740753788da5f077a155c4850a11c9c0b49f Mon Sep 17 00:00:00 2001 From: Drak Date: Thu, 16 Feb 2012 08:34:29 +0545 Subject: [PATCH 4/5] [Locale] Update documentation for autoloader. --- src/Symfony/Component/Locale/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Locale/README.md b/src/Symfony/Component/Locale/README.md index 4fece8b38a..a0d7a87d5e 100644 --- a/src/Symfony/Component/Locale/README.md +++ b/src/Symfony/Component/Locale/README.md @@ -11,7 +11,7 @@ requires adding the following lines to your autoloader: if (!function_exists('intl_get_error_code')) { require __DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php'; - $loader->registerPrefixFallbacks(array(__DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs')); + $loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs'); } Resources From 2871ea062e62e2f5f9007bec91fd74be545e1377 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 17 Feb 2012 13:55:48 +0545 Subject: [PATCH 5/5] Update composer for HttpFoundation's PHP 5.4 forward compatibility. --- autoload.php.dist | 2 +- composer.json | 5 ++++- src/Symfony/Component/HttpFoundation/composer.json | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/autoload.php.dist b/autoload.php.dist index 54278e28dd..8b51fa8ea3 100644 --- a/autoload.php.dist +++ b/autoload.php.dist @@ -23,7 +23,7 @@ if (!function_exists('intl_get_error_code')) { $loader->registerPrefixFallback(__DIR__.'/src/Symfony/Component/Locale/Resources/stubs'); } if (!interface_exists('SessionHandlerInterface', false)) { - $loader->registerPrefixFallback(__DIR__.'/src/Symfony/Component/HttpFoundation/Resources/stubs'); + $loader->registerPrefix('SessionHandlerInterface', __DIR__.'/src/Symfony/Component/HttpFoundation/Resources/stubs'); } $loader->register(); diff --git a/composer.json b/composer.json index a481c4e463..99ed3df514 100644 --- a/composer.json +++ b/composer.json @@ -56,6 +56,9 @@ "doctrine/data-fixtures": "1.0.*" }, "autoload": { - "psr-0": { "Symfony": "src/" } + "psr-0": { + "Symfony": "src/", + "SessionHandlerInterface": "src/Symfony/Component/HttpFoundation/Resources/stub" + } } } diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index 09b13f505b..daf2ee0660 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -20,7 +20,10 @@ "php": ">=5.3.2" }, "autoload": { - "psr-0": { "Symfony\\Component\\HttpFoundation": "" } + "psr-0": { + "Symfony\\Component\\HttpFoundation": "", + "SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stub" + } }, "target-dir": "Symfony/Component/HttpFoundation" }