From 908a7a35be2b6e2e361c666a4e53f4ceb47f9943 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 2 Aug 2011 19:29:35 +0200 Subject: [PATCH 01/16] [HttpFoundation] Fix bug in clearCookie/removeCookie not clearing cookies set with a default '/' path, unless it was explicitly specified --- src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index 86976cee41..26017f1cfa 100644 --- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -139,7 +139,7 @@ class ResponseHeaderBag extends HeaderBag * * @api */ - public function removeCookie($name, $path = null, $domain = null) + public function removeCookie($name, $path = '/', $domain = null) { unset($this->cookies[$domain][$path][$name]); @@ -195,7 +195,7 @@ class ResponseHeaderBag extends HeaderBag * * @api */ - public function clearCookie($name, $path = null, $domain = null) + public function clearCookie($name, $path = '/', $domain = null) { $this->setCookie(new Cookie($name, null, 1, $path, $domain)); } From 85ed5c67dcde0c6d0dd00f383cb78e1aa3785496 Mon Sep 17 00:00:00 2001 From: Josef Cech Date: Sun, 25 Sep 2011 13:13:28 +0200 Subject: [PATCH 02/16] [ClassLoader] Fixed state when trait_exists doesn't exists --- .../Component/ClassLoader/ClassCollectionLoader.php | 2 +- .../Component/ClassLoader/DebugUniversalClassLoader.php | 2 +- .../Component/ClassLoader/ClassCollectionLoaderTest.php | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php index 5bcd6d67ca..da777f2991 100644 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -84,7 +84,7 @@ class ClassCollectionLoader $files = array(); $content = ''; foreach ($classes as $class) { - if (!class_exists($class) && !interface_exists($class) && function_exists('trait_exists') && !trait_exists($class)) { + if (!class_exists($class) && !interface_exists($class) && (!function_exists('trait_exists') || !trait_exists($class))) { throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class)); } diff --git a/src/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php b/src/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php index 7d0cb54069..19952909ee 100644 --- a/src/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php +++ b/src/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php @@ -54,7 +54,7 @@ class DebugUniversalClassLoader extends UniversalClassLoader if ($file = $this->findFile($class)) { require $file; - if (!class_exists($class, false) && !interface_exists($class, false) && function_exists('trait_exists') && !trait_exists($class)) { + if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class))) { throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } } diff --git a/tests/Symfony/Tests/Component/ClassLoader/ClassCollectionLoaderTest.php b/tests/Symfony/Tests/Component/ClassLoader/ClassCollectionLoaderTest.php index 3fee2ed324..ed0b7b96fa 100644 --- a/tests/Symfony/Tests/Component/ClassLoader/ClassCollectionLoaderTest.php +++ b/tests/Symfony/Tests/Component/ClassLoader/ClassCollectionLoaderTest.php @@ -63,4 +63,12 @@ EOF; $this->assertEquals($expected, ClassCollectionLoader::fixNamespaceDeclarations($source)); } + + /** + * @expectedException InvalidArgumentException + */ + public function testUnableToLoadClassException() + { + ClassCollectionLoader::load(array('SomeNotExistingClass'), '', 'foo', false); + } } From decfe9eb5cfb4c70f3875aaeac3857f31c12aeba Mon Sep 17 00:00:00 2001 From: Dan Patrick Date: Sun, 25 Sep 2011 18:50:30 -0500 Subject: [PATCH 03/16] Corrected grammar in FilterControllerEvent comments --- .../Component/HttpKernel/Event/FilterControllerEvent.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Event/FilterControllerEvent.php b/src/Symfony/Component/HttpKernel/Event/FilterControllerEvent.php index f5c1d82b87..fbac347fae 100644 --- a/src/Symfony/Component/HttpKernel/Event/FilterControllerEvent.php +++ b/src/Symfony/Component/HttpKernel/Event/FilterControllerEvent.php @@ -15,11 +15,11 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** - * Allows to filter a controller callable + * Allows filtering of a controller callable * * You can call getController() to retrieve the current controller. With - * setController() you can set a new controller that is used in for processing - * a request. + * setController() you can set a new controller that is used in the processing + * of the request. * * Controllers should be callables. * From ed02aa9974a85c87eb2885a01af1df89312e0ade Mon Sep 17 00:00:00 2001 From: Marcin Chylek Date: Mon, 26 Sep 2011 01:05:02 +0200 Subject: [PATCH 04/16] Fix console: list 'namespace' command display all available commands --- src/Symfony/Component/Console/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 75c17351e5..5167bfea85 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -581,7 +581,7 @@ class Application $commands = array(); foreach ($this->commands as $name => $command) { - if ($namespace === $this->extractNamespace($name)) { + if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { $commands[$name] = $command; } } From 72e82eb595113652e6c963b46932635d634930e3 Mon Sep 17 00:00:00 2001 From: Laurent Bachelier Date: Mon, 26 Sep 2011 16:30:32 +0200 Subject: [PATCH 05/16] Replace deprecated key_exists alias From the PHP manual of array_key_exists: For backward compatibility, the following deprecated alias may be used: key_exists(). --- src/Symfony/Component/Serializer/Encoder/XmlEncoder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index 146be81317..701c071dd4 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -198,7 +198,7 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec $data[] = $tmp; $data[] = $value; } - } elseif (key_exists($key, $data)) { + } elseif (array_key_exists($key, $data)) { if ((false === is_array($data[$key])) || (false === isset($data[$key][0]))) { $data[$key] = array($data[$key]); } From d6b915a1746624e6fddc6e052bd8241456349a2b Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Mon, 19 Sep 2011 15:45:18 -0400 Subject: [PATCH 06/16] [FrameworkBundle] Assets templating helper does not need request scope No other helpers have request scope and the assets helper's parameters don't appear to depend on the request in any way, so this appears to be unnecessary. As-is, request scope here prevents use of the assets helper from a console command that may need to internally render a template. --- .../Bundle/FrameworkBundle/Resources/config/templating_php.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml index 0c164ca129..ae87c44be1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml @@ -34,7 +34,7 @@ - + From 369f1810051895bf86502ffea34a3d2354ee0e16 Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Mon, 26 Sep 2011 13:19:08 -0400 Subject: [PATCH 07/16] [FrameworkBundle] Add request scope to assets helper only if needed Builds upon aead4a9836180cabae4d47fe27c634dcd79ac8f2, which prematurely removed request scoping from the assets templating helper in all cases. The helper need only be request-scoped if one or more request-scoped packages (e.g. PathPackages) are injected into it. This change makes it possible to utilize the assets helper outside of a request (e.g. during a console script). To ensure that the assets helper is not assigned a request scope, all asset base URL's must be defined for all packages (default and any named) and both protocols: HTTP and SSL. The included test config fixtures concisely accomplish this by specifying a single HTTPS URL as the base URL for our default and named package, since FrameworkExtension's Configuration conveniently registers this URL for both protocols. --- .../FrameworkExtension.php | 14 ++++++++++++++ .../Fixtures/php/templating_url_package.php | 14 ++++++++++++++ .../Fixtures/xml/templating_url_package.xml | 19 +++++++++++++++++++ .../Fixtures/yml/templating_url_package.yml | 8 ++++++++ .../FrameworkExtensionTest.php | 9 +++++++++ 5 files changed, 64 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_url_package.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_url_package.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_url_package.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 769371e3a2..b0a911577c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Parameter; @@ -342,6 +343,19 @@ class FrameworkExtension extends Extension $namedPackages, )); + // Apply request scope to assets helper if one or more packages are request-scoped + $requireRequestScope = array_reduce( + $namedPackages, + function($v, Reference $ref) use ($container) { + return $v || 'request' === $container->getDefinition($ref)->getScope(); + }, + 'request' === $defaultPackage->getScope() + ); + + if ($requireRequestScope) { + $container->getDefinition('templating.helper.assets')->setScope('request'); + } + if (!empty($config['loaders'])) { $loaders = array_map(function($loader) { return new Reference($loader); }, $config['loaders']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_url_package.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_url_package.php new file mode 100644 index 0000000000..a5dda77dad --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_url_package.php @@ -0,0 +1,14 @@ +loadFromExtension('framework', array( + 'secret' => 's3cr3t', + 'templating' => array( + 'assets_base_urls' => 'https://cdn.example.com', + 'engines' => array('php', 'twig'), + 'packages' => array( + 'images' => array( + 'base_urls' => 'https://images.example.com', + ), + ), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_url_package.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_url_package.xml new file mode 100644 index 0000000000..0fd2039b07 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_url_package.xml @@ -0,0 +1,19 @@ + + + + + + + php + twig + https://cdn.example.com + + https://images.example.com + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_url_package.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_url_package.yml new file mode 100644 index 0000000000..bfec7a19cc --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_url_package.yml @@ -0,0 +1,8 @@ +framework: + secret: s3cr3t + templating: + assets_base_urls: https://cdn.example.com + engines: [php, twig] + packages: + images: + base_urls: https://images.example.com diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 93667842d4..b25372d7e2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -96,6 +96,8 @@ abstract class FrameworkExtensionTest extends TestCase $this->assertTrue($container->hasDefinition('templating.name_parser'), '->registerTemplatingConfiguration() loads templating.xml'); + $this->assertEquals('request', $container->getDefinition('templating.helper.assets')->getScope(), '->registerTemplatingConfiguration() sets request scope on assets helper if one or more packages are request-scopes'); + // default package should have one http base url and path package ssl url $this->assertTrue($container->hasDefinition('templating.asset.default_package.http')); $package = $container->getDefinition('templating.asset.default_package.http'); @@ -125,6 +127,13 @@ abstract class FrameworkExtensionTest extends TestCase $this->assertEquals(array('FrameworkBundle:Form', 'theme1', 'theme2'), $container->getParameter('templating.helper.form.resources'), '->registerTemplatingConfiguration() registers the theme and adds the base theme'); } + public function testTemplatingAssetsHelperScopeDependsOnPackageArgumentScopes() + { + $container = $this->createContainerFromFile('templating_url_package'); + + $this->assertNotEquals('request', $container->getDefinition('templating.helper.assets')->getScope(), '->registerTemplatingConfiguration() does not set request scope on assets helper if no packages are request-scopes'); + } + public function testTranslator() { $container = $this->createContainerFromFile('full'); From 6555e28d578ffd9087b60adc35064a5d736be8cb Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Mon, 26 Sep 2011 14:40:56 -0400 Subject: [PATCH 08/16] Remove unnecessary use statement --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b0a911577c..0abb828551 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -13,7 +13,6 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Parameter; From d375b6d00e7fc2810f587ee35c89747a7f3a685d Mon Sep 17 00:00:00 2001 From: Drak Date: Tue, 27 Sep 2011 13:34:25 +0545 Subject: [PATCH 09/16] Corrected docblock, quoted types were incorrect. --- src/Symfony/Component/HttpFoundation/Request.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index a1fea5a8bb..cce039f9cb 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -44,14 +44,14 @@ class Request public $query; /** - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var \Symfony\Component\HttpFoundation\ServerBag * * @api */ public $server; /** - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var \Symfony\Component\HttpFoundation\FileBag * * @api */ From c13b4e2b55d88f5d93d2120b90a5155855d03daf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 27 Sep 2011 17:17:34 +0200 Subject: [PATCH 10/16] fixed fallback catalogue mechanism in Framework bundle --- .../Tests/Translation/TranslatorTest.php | 126 ++++++++++++++++++ .../Translation/Translator.php | 30 ++++- .../Component/Translation/Translator.php | 22 +-- 3 files changed, 164 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php new file mode 100644 index 0000000000..15c7c3c636 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Translation; + +use Symfony\Bundle\FrameworkBundle\Translation\Translator; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\HttpKernel\Util\Filesystem; + +class TranslatorTest extends \PHPUnit_Framework_TestCase +{ + protected $tmpDir; + + public function setUp() + { + $this->tmpDir = sys_get_temp_dir().'/sf2_translation'; + $this->deleteTmpDir(); + } + + public function tearDown() + { + $this->deleteTmpDir(); + } + + protected function deleteTmpDir() + { + if (!file_exists($dir = $this->tmpDir)) { + return; + } + + $fs = new Filesystem(); + $fs->remove($dir); + } + + public function testTransWithoutCaching() + { + $translator = $this->getTranslator($this->getLoader()); + $translator->setLocale('fr'); + $translator->setFallbackLocale('en'); + + $this->assertEquals('foo (FR)', $translator->trans('foo')); + $this->assertEquals('bar (EN)', $translator->trans('bar')); + } + + public function testTransWithCaching() + { + // prime the cache + $translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir)); + $translator->setLocale('fr'); + $translator->setFallbackLocale('en'); + + $this->assertEquals('foo (FR)', $translator->trans('foo')); + $this->assertEquals('bar (EN)', $translator->trans('bar')); + + // do it another time as the cache is primed now + $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface'); + $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir)); + $translator->setLocale('fr'); + $translator->setFallbackLocale('en'); + + $this->assertEquals('foo (FR)', $translator->trans('foo')); + $this->assertEquals('bar (EN)', $translator->trans('bar')); + } + + protected function getCatalogue($locale, $messages) + { + $catalogue = new MessageCatalogue($locale); + foreach ($messages as $key => $translation) { + $catalogue->set($key, $translation); + } + + return $catalogue; + } + + protected function getLoader() + { + $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface'); + $loader + ->expects($this->at(0)) + ->method('load') + ->will($this->returnValue($this->getCatalogue('fr', array('foo' => 'foo (FR)')))) + ; + $loader + ->expects($this->at(1)) + ->method('load') + ->will($this->returnValue($this->getCatalogue('en', array('foo' => 'foo (EN)', 'bar' => 'bar (EN)')))) + ; + + return $loader; + } + + protected function getContainer($loader) + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container + ->expects($this->any()) + ->method('get') + ->will($this->returnValue($loader)) + ; + + return $container; + } + + public function getTranslator($loader, $options = array()) + { + $translator = new Translator( + $this->getContainer($loader), + $this->getMock('Symfony\Component\Translation\MessageSelector'), + array('loader' => 'loader'), + $options + ); + + $translator->addResource('loader', 'foo', 'fr'); + $translator->addResource('loader', 'foo', 'en'); + + return $translator; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 7bbe983c26..991b607bba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -98,10 +98,34 @@ class Translator extends BaseTranslator parent::loadCatalogue($locale); - $content = sprintf( - "computeFallbackLocale($locale); + if ($fallback && $fallback != $locale) { + $fallbackContent = sprintf(<<addFallbackCatalogue(new MessageCatalogue('%s', %s)); +EOF + , + $fallback, + var_export($this->catalogues[$fallback]->all(), true) + ); + } + + $content = sprintf(<<catalogues[$locale]->all(), true) + var_export($this->catalogues[$locale]->all(), true), + $fallbackContent ); $cache->write($content, $this->catalogues[$locale]->getResources()); diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index e26ee47f5f..e42dcb1d6f 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -167,10 +167,19 @@ class Translator implements TranslatorInterface } } - $this->optimizeCatalogue($locale); + $this->addFallbackCatalogue($locale); } - private function optimizeCatalogue($locale) + protected function computeFallbackLocale($locale) + { + if (strlen($locale) > 3) { + return substr($locale, 0, -strlen(strrchr($locale, '_'))); + } else { + return $this->fallbackLocale; + } + } + + private function addFallbackCatalogue($locale) { if (!$fallback = $this->computeFallbackLocale($locale)) { return; @@ -184,13 +193,4 @@ class Translator implements TranslatorInterface $this->catalogues[$locale]->addFallbackCatalogue($this->catalogues[$fallback]); } } - - private function computeFallbackLocale($locale) - { - if (strlen($locale) > 3) { - return substr($locale, 0, -strlen(strrchr($locale, '_'))); - } else { - return $this->fallbackLocale; - } - } } From 2db24c264f186b50c7f3eddc923dd9f8fd4f452d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 28 Sep 2011 08:30:05 +0200 Subject: [PATCH 11/16] removed time limit for the vendors script (closes #2282) --- vendors.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendors.php b/vendors.php index afcf33b46e..8f44e491d4 100755 --- a/vendors.php +++ b/vendors.php @@ -19,6 +19,8 @@ http://symfony.com/download */ +set_time_limit(0); + if (!is_dir($vendorDir = dirname(__FILE__).'/vendor')) { mkdir($vendorDir, 0777, true); } From 5c060d15e9ff165eeb8ce7d2faa25985fdce00bc Mon Sep 17 00:00:00 2001 From: Andrej Hudec Date: Wed, 28 Sep 2011 10:00:17 +0300 Subject: [PATCH 12/16] Fix for {@inheritdoc} phpDoc tag. --- src/Symfony/Bundle/FrameworkBundle/Routing/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index bf3dcbdcde..1f000f9e84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -44,7 +44,7 @@ class Router extends BaseRouter } /** - * @{inheritdoc} + * {@inheritdoc} */ public function getRouteCollection() { From 1e7e6ba305c4b7b66e49545d582325ed1ea5f9d7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 28 Sep 2011 10:34:14 +0200 Subject: [PATCH 13/16] [HttpFoundation] removed the possibility for a cookie path to set it to null (as this is equivalent to /) --- src/Symfony/Component/HttpFoundation/Cookie.php | 4 ++-- src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 9dab8e6df4..339e78d406 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -90,7 +90,7 @@ class Cookie } } - if (null !== $this->getPath()) { + if ('/' !== $this->getPath()) { $str .= '; path='.$this->getPath(); } @@ -166,7 +166,7 @@ class Cookie */ public function getPath() { - return $this->path; + return null === $this->path ? '/' : $this->path; } /** diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index 26017f1cfa..f243dcc9f6 100644 --- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -141,6 +141,10 @@ class ResponseHeaderBag extends HeaderBag */ public function removeCookie($name, $path = '/', $domain = null) { + if (null === $path) { + $path = '/'; + } + unset($this->cookies[$domain][$path][$name]); if (empty($this->cookies[$domain][$path])) { From 128468193f5d23c8ac878f973c49ed191dd82a2a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 28 Sep 2011 10:49:26 +0200 Subject: [PATCH 14/16] [BrowserKit] standardized cookie paths (an empty path is equivalent to /) --- src/Symfony/Component/BrowserKit/Cookie.php | 10 +++++----- .../Symfony/Tests/Component/BrowserKit/CookieTest.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index 5f9a213016..166f720f90 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -67,7 +67,7 @@ class Cookie } $this->name = $name; $this->expires = null === $expires ? null : (integer) $expires; - $this->path = empty($path) ? null : $path; + $this->path = empty($path) ? '/' : $path; $this->domain = $domain; $this->secure = (Boolean) $secure; $this->httponly = (Boolean) $httponly; @@ -92,7 +92,7 @@ class Cookie $cookie .= '; domain='.$this->domain; } - if (null !== $this->path) { + if ('/' !== $this->path) { $cookie .= '; path='.$this->path; } @@ -130,8 +130,8 @@ class Cookie $values = array( 'name' => trim($name), 'value' => trim($value), - 'expires' => null, - 'path' => null, + 'expires' => null, + 'path' => '/', 'domain' => '', 'secure' => false, 'httponly' => false, @@ -262,7 +262,7 @@ class Cookie */ public function getPath() { - return null !== $this->path ? $this->path : '/'; + return $this->path; } /** diff --git a/tests/Symfony/Tests/Component/BrowserKit/CookieTest.php b/tests/Symfony/Tests/Component/BrowserKit/CookieTest.php index e309b6ccdd..89b11061dc 100644 --- a/tests/Symfony/Tests/Component/BrowserKit/CookieTest.php +++ b/tests/Symfony/Tests/Component/BrowserKit/CookieTest.php @@ -65,7 +65,7 @@ class CookieTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('foo=bar; domain=www.example.com', (string) Cookie::FromString('foo=bar', 'http://www.example.com/')); $this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar')); - $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar')); + $this->assertEquals('foo=bar; domain=www.example.com', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar')); $this->assertEquals('foo=bar; domain=www.myotherexample.com', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/')); } From b4028350d26e5e47e620c3574e51daa471ec8c1c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 28 Sep 2011 10:49:50 +0200 Subject: [PATCH 15/16] [HttpFoundation] standardized cookie paths (an empty path is equivalent to /) --- src/Symfony/Component/HttpFoundation/Cookie.php | 8 ++++---- .../Symfony/Tests/Component/HttpFoundation/CookieTest.php | 6 +++--- .../Component/HttpFoundation/ResponseHeaderBagTest.php | 4 ++-- .../Http/Logout/CookieClearingLogoutHandlerTest.php | 4 ++-- .../PersistentTokenBasedRememberMeServicesTest.php | 2 +- .../Http/RememberMe/TokenBasedRememberMeServicesTest.php | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 339e78d406..8392812ebe 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -71,7 +71,7 @@ class Cookie $this->value = $value; $this->domain = $domain; $this->expire = $expire; - $this->path = $path; + $this->path = empty($path) ? '/' : $path; $this->secure = (Boolean) $secure; $this->httpOnly = (Boolean) $httpOnly; } @@ -90,8 +90,8 @@ class Cookie } } - if ('/' !== $this->getPath()) { - $str .= '; path='.$this->getPath(); + if ('/' !== $this->path) { + $str .= '; path='.$this->path; } if (null !== $this->getDomain()) { @@ -166,7 +166,7 @@ class Cookie */ public function getPath() { - return null === $this->path ? '/' : $this->path; + return $this->path; } /** diff --git a/tests/Symfony/Tests/Component/HttpFoundation/CookieTest.php b/tests/Symfony/Tests/Component/HttpFoundation/CookieTest.php index 114d3ad2cb..35c06de482 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/CookieTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/CookieTest.php @@ -142,10 +142,10 @@ class CookieTest extends \PHPUnit_Framework_TestCase { $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); - $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie'); + $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie'); - $cookie = new Cookie('foo', null, 1, '/', '.myfoodomain.com'); + $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); - $this->assertEquals('foo=deleted; expires=' . gmdate("D, d-M-Y H:i:s T", time()-31536001) . '; path=/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL'); + $this->assertEquals('foo=deleted; expires=' . gmdate("D, d-M-Y H:i:s T", time()-31536001) . '; path=/admin/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL'); } } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/ResponseHeaderBagTest.php b/tests/Symfony/Tests/Component/HttpFoundation/ResponseHeaderBagTest.php index a69c966a9a..329c3f9361 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/ResponseHeaderBagTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/ResponseHeaderBagTest.php @@ -69,7 +69,7 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase $bag = new ResponseHeaderBag(array()); $bag->setCookie(new Cookie('foo', 'bar')); - $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", explode("\r\n", $bag->__toString())); + $this->assertContains("Set-Cookie: foo=bar; httponly", explode("\r\n", $bag->__toString())); $bag->clearCookie('foo'); @@ -90,7 +90,7 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); $this->assertContains("Set-Cookie: foo=bar; path=/path/bar; domain=bar.foo; httponly", $headers); - $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", $headers); + $this->assertContains("Set-Cookie: foo=bar; httponly", $headers); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertTrue(isset($cookies['foo.bar']['/path/foo']['foo'])); diff --git a/tests/Symfony/Tests/Component/Security/Http/Logout/CookieClearingLogoutHandlerTest.php b/tests/Symfony/Tests/Component/Security/Http/Logout/CookieClearingLogoutHandlerTest.php index 9d77f82990..4a55f7949b 100644 --- a/tests/Symfony/Tests/Component/Security/Http/Logout/CookieClearingLogoutHandlerTest.php +++ b/tests/Symfony/Tests/Component/Security/Http/Logout/CookieClearingLogoutHandlerTest.php @@ -40,9 +40,9 @@ class CookieClearingLogoutHandlerTest extends \PHPUnit_Framework_TestCase $this->assertEquals('foo.foo', $cookie->getDomain()); $this->assertTrue($cookie->isCleared()); - $cookie = $cookies['']['']['foo2']; + $cookie = $cookies['']['/']['foo2']; $this->assertStringStartsWith('foo2', $cookie->getName()); - $this->assertNull($cookie->getPath()); + $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); $this->assertTrue($cookie->isCleared()); } diff --git a/tests/Symfony/Tests/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php b/tests/Symfony/Tests/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php index daa3263717..bf50b33265 100644 --- a/tests/Symfony/Tests/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php +++ b/tests/Symfony/Tests/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServicesTest.php @@ -222,7 +222,7 @@ class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_Test $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); - $this->assertNull($cookie->getPath()); + $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); } diff --git a/tests/Symfony/Tests/Component/Security/Http/RememberMe/TokenBasedRememberMeServicesTest.php b/tests/Symfony/Tests/Component/Security/Http/RememberMe/TokenBasedRememberMeServicesTest.php index 4a587dd7fb..c3dec185b6 100644 --- a/tests/Symfony/Tests/Component/Security/Http/RememberMe/TokenBasedRememberMeServicesTest.php +++ b/tests/Symfony/Tests/Component/Security/Http/RememberMe/TokenBasedRememberMeServicesTest.php @@ -155,7 +155,7 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); - $this->assertNull($cookie->getPath()); + $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); } From b12ce94c38b66d7bcd18e87d063f94e60b9d2f46 Mon Sep 17 00:00:00 2001 From: stealth35 Date: Wed, 28 Sep 2011 13:18:44 +0200 Subject: [PATCH 16/16] [HttpFoundation] fix #2142 PathInfo parsing/checking Bug fix: yes Feature addition: no Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: #2142 --- .../Component/HttpFoundation/Request.php | 2 +- .../Component/HttpFoundation/RequestTest.php | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index cce039f9cb..e66abb7484 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1188,7 +1188,7 @@ class Request $requestUri = substr($requestUri, 0, $pos); } - if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) { + if ((null !== $baseUrl) && (false === ($pathInfo = substr(urldecode($requestUri), strlen(urldecode($baseUrl)))))) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } elseif (null === $baseUrl) { diff --git a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php index 17abc6d807..c3292152a5 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php @@ -689,6 +689,31 @@ class RequestTest extends \PHPUnit_Framework_TestCase $this->assertEquals('', $request->getBasePath()); } + public function testGetPathInfo() + { + $request = new Request(); + $this->assertEquals('/', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '/path/info'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/path/info', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '/path test/info'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/path test/info', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '/path%20test/info'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/path test/info', $request->getPathInfo()); + + } + public function testGetPreferredLanguage() { $request = new Request();