From c4da2d9892f04653798eaa42b097730aafc2d4d0 Mon Sep 17 00:00:00 2001 From: dened Date: Mon, 25 Mar 2013 11:05:20 +0400 Subject: [PATCH 01/20] [HttpFoundation] getClientIp is fixed. The getClientIp now returns ip of the earliest server in a proxy chain when all the servers in the chain are trusted proxies. Before this patch the getClientIp used to return null at such condition. Some appropriate tests are added. --- src/Symfony/Component/HttpFoundation/Request.php | 3 ++- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 6da6bc87ed..d1b22eed2d 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -677,9 +677,10 @@ class Request $clientIps[] = $ip; $trustedProxies = self::$trustProxy && !self::$trustedProxies ? array($ip) : self::$trustedProxies; + $ip = $clientIps[0]; $clientIps = array_diff($clientIps, $trustedProxies); - return array_pop($clientIps); + return $clientIps ? array_pop($clientIps) : $ip; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 38ae748da6..afb495c931 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -660,6 +660,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { return array( array('88.88.88.88', false, '88.88.88.88', null, null), + array('88.88.88.88', true, '88.88.88.88', null, null), array('127.0.0.1', false, '127.0.0.1', null, null), array('::1', false, '::1', null, null), array('127.0.0.1', false, '127.0.0.1', '88.88.88.88', null), @@ -668,6 +669,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase array('88.88.88.88', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', null), array('87.65.43.21', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), array('87.65.43.21', false, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), + array('88.88.88.88', true, '123.45.67.89', '88.88.88.88', array('123.45.67.89', '88.88.88.88')), + array('88.88.88.88', false, '123.45.67.89', '88.88.88.88', array('123.45.67.89', '88.88.88.88')), ); } From bd264195e101038a496ad6d843ef988397789dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 28 Mar 2013 18:41:24 +0100 Subject: [PATCH 02/20] [Security] Removed unused var --- src/Symfony/Component/Security/Http/Firewall.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall.php b/src/Symfony/Component/Security/Http/Firewall.php index e083fdb496..31c1da58ae 100644 --- a/src/Symfony/Component/Security/Http/Firewall.php +++ b/src/Symfony/Component/Security/Http/Firewall.php @@ -63,7 +63,7 @@ class Firewall implements EventSubscriberInterface // initiate the listener chain foreach ($listeners as $listener) { - $response = $listener->handle($event); + $listener->handle($event); if ($event->hasResponse()) { break; From 6ef92fd4e8dc3c0d7da5ca49acb3146c7b75bb55 Mon Sep 17 00:00:00 2001 From: Fran Moreno Date: Sun, 7 Apr 2013 23:48:44 +0200 Subject: [PATCH 03/20] [PropertyAccess] Add objectives to pluralMap --- src/Symfony/Component/PropertyAccess/StringUtil.php | 3 +++ src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/PropertyAccess/StringUtil.php b/src/Symfony/Component/PropertyAccess/StringUtil.php index 012ed8846b..d8704f38d2 100644 --- a/src/Symfony/Component/PropertyAccess/StringUtil.php +++ b/src/Symfony/Component/PropertyAccess/StringUtil.php @@ -69,6 +69,9 @@ class StringUtil // atlases (atlas), kisses (kiss) array('ses', 3, true, true, array('s', 'se', 'sis')), + // objectives (objective), alternative (alternatives) + array('sevit', 5, true, true, 'tive'), + // lives (life), wives (wife) array('sevi', 4, false, true, 'ife'), diff --git a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php index 3c36f91a9b..66bb6c9767 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php @@ -117,6 +117,7 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase array('bees', array('be', 'bee')), array('cheeses', array('chees', 'cheese', 'cheesis')), array('radii', 'radius'), + array('objectives', 'objective'), // test casing: if the first letter was uppercase, it should remain so array('Men', 'Man'), From df22326664bbb49b985982c7fd4b67d59f983423 Mon Sep 17 00:00:00 2001 From: janschoenherr Date: Mon, 8 Apr 2013 15:26:52 +0300 Subject: [PATCH 04/20] Update PhpEngine.php just a minor phpdoc fix --- src/Symfony/Component/Templating/PhpEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Templating/PhpEngine.php b/src/Symfony/Component/Templating/PhpEngine.php index f309b6082e..443c961c99 100644 --- a/src/Symfony/Component/Templating/PhpEngine.php +++ b/src/Symfony/Component/Templating/PhpEngine.php @@ -184,7 +184,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess * * @param string $name The helper name * - * @return mixed The helper value + * @return HelperInterface The helper value * * @throws \InvalidArgumentException if the helper is not defined * From 7fc429ffd09ffc107a927445bcd573a77579760b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Piechota?= Date: Tue, 9 Apr 2013 23:28:51 +0200 Subject: [PATCH 05/20] [Form] DateTimeToRfc3339Transformer use proper transformation exteption in reverse transformation --- .../DataTransformer/DateTimeToRfc3339Transformer.php | 6 +++++- .../DateTimeToRfc3339TransformerTest.php | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index 7131ff6519..4b8a2b76ae 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -53,7 +53,11 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer return null; } - $dateTime = new \DateTime($rfc3339); + try { + $dateTime = new \DateTime($rfc3339); + } catch (\Exception $e) { + throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); + } if ($this->outputTimezone !== $this->inputTimezone) { try { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index 8aae8e0935..4b8dfebd34 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -119,4 +119,14 @@ class DateTimeToRfc3339TransformerTest extends DateTimeTestCase $transformer->reverseTransform('2010-04-31T04:05Z'); } + + /** + * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsValidDateString() + { + $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); + + $transformer->reverseTransform('2010-2010-2010'); + } } From 0f0c29c9bf6b5976271d725b98c07e878ba46233 Mon Sep 17 00:00:00 2001 From: Maxwell Vandervelde Date: Sat, 6 Apr 2013 18:33:57 -0500 Subject: [PATCH 06/20] [HttpFoundation] Fixed bug in key searching for NamespacedAttributeBag Fixed a bug in NamespacedAttributeBag causing a result to be falsely found when the last key of the attribute matched the last of the queried name regardless of if the key did not exist in the search. Added Tests to demonstrate the issue and resolved by setting keys to null when iterating through query and returning proper responses in the case that the given array does in fact not exist. * Updated Syntax of null checks * Fixing missing else case for if statement in write context --- .../Session/Attribute/NamespacedAttributeBag.php | 16 ++++++++++------ .../Attribute/NamespacedAttributeBagTest.php | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php index 138aa36145..25dcd22869 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php @@ -46,6 +46,10 @@ class NamespacedAttributeBag extends AttributeBag $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); + if (null === $attributes) { + return false; + } + return array_key_exists($name, $attributes); } @@ -57,6 +61,10 @@ class NamespacedAttributeBag extends AttributeBag $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); + if (null === $attributes) { + return $default; + } + return array_key_exists($name, $attributes) ? $attributes[$name] : $default; } @@ -120,12 +128,8 @@ class NamespacedAttributeBag extends AttributeBag unset($parts[count($parts)-1]); foreach ($parts as $part) { - if (!array_key_exists($part, $array)) { - if (!$writeContext) { - return $array; - } - - $array[$part] = array(); + if (null !== $array && !array_key_exists($part, $array)) { + $array[$part] = $writeContext ? array() : null; } $array = & $array[$part]; diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php index 432499e945..0f9ef0fb33 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php @@ -160,8 +160,10 @@ class NamespacedAttributeBagTest extends \PHPUnit_Framework_TestCase array('csrf.token/b', '4321', true), array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), array('category/fishing', array('first' => 'cod', 'second' => 'sole'), true), + array('category/fishing/missing/first', null, false), array('category/fishing/first', 'cod', true), array('category/fishing/second', 'sole', true), + array('category/fishing/missing/second', null, false), array('user2.login', null, false), array('never', null, false), array('bye', null, false), From 383a84b807a5967ccd49d61559ec52aad22907fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9nald=20Casagraude?= Date: Thu, 11 Apr 2013 00:42:15 +0200 Subject: [PATCH 07/20] fixed handling of "0" input on ask --- src/Symfony/Component/Console/Helper/DialogHelper.php | 4 +++- .../Component/Console/Tests/Helper/DialogHelperTest.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/DialogHelper.php b/src/Symfony/Component/Console/Helper/DialogHelper.php index 170abd8886..49fc2c178f 100644 --- a/src/Symfony/Component/Console/Helper/DialogHelper.php +++ b/src/Symfony/Component/Console/Helper/DialogHelper.php @@ -102,7 +102,9 @@ class DialogHelper extends Helper $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress - while ($c = fread($inputStream, 1)) { + while (!feof($inputStream)) { + $c = fread($inputStream, 1); + // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { diff --git a/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php index 12f27005cb..e6418ad710 100644 --- a/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php @@ -69,7 +69,8 @@ class DialogHelperTest extends \PHPUnit_Framework_TestCase // Test // // S - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\n"); + // F00oo + $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); $dialog = new DialogHelper(); $dialog->setInputStream($inputStream); @@ -83,6 +84,7 @@ class DialogHelperTest extends \PHPUnit_Framework_TestCase $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); + $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); } public function testAskHiddenResponse() From b22d2ff925d25274b7c35a3a5678e1fcb696609b Mon Sep 17 00:00:00 2001 From: Andrew Udvare Date: Wed, 10 Apr 2013 22:20:58 -0700 Subject: [PATCH 08/20] The /e modifier for preg_replace() is deprecated in PHP 5.5; replace with preg_replace_callback() --- .../Compiler/RegisterKernelListenersPass.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php index 06a0d1975e..ad406eb6a3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php @@ -33,10 +33,11 @@ class RegisterKernelListenersPass implements CompilerPassInterface } if (!isset($event['method'])) { - $event['method'] = 'on'.preg_replace(array( - '/(?<=\b)[a-z]/ie', - '/[^a-z0-9]/i' - ), array('strtoupper("\\0")', ''), $event['event']); + $event['method'] = 'on'.preg_replace_callback(array( + '/(?<=\b)[a-z]/i', + '/[^a-z0-9]/i', + ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); + $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); From 302d44fb4087aa727d190741fd93ea85c595c0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9nald=20Casagraude?= Date: Thu, 11 Apr 2013 00:42:15 +0200 Subject: [PATCH 09/20] [Console] fixed handling of "0" input on ask --- src/Symfony/Component/Console/Helper/DialogHelper.php | 4 +++- .../Component/Console/Tests/Helper/DialogHelperTest.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/DialogHelper.php b/src/Symfony/Component/Console/Helper/DialogHelper.php index 170abd8886..49fc2c178f 100644 --- a/src/Symfony/Component/Console/Helper/DialogHelper.php +++ b/src/Symfony/Component/Console/Helper/DialogHelper.php @@ -102,7 +102,9 @@ class DialogHelper extends Helper $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress - while ($c = fread($inputStream, 1)) { + while (!feof($inputStream)) { + $c = fread($inputStream, 1); + // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { diff --git a/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php index 12f27005cb..e6418ad710 100644 --- a/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php @@ -69,7 +69,8 @@ class DialogHelperTest extends \PHPUnit_Framework_TestCase // Test // // S - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\n"); + // F00oo + $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); $dialog = new DialogHelper(); $dialog->setInputStream($inputStream); @@ -83,6 +84,7 @@ class DialogHelperTest extends \PHPUnit_Framework_TestCase $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); + $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); } public function testAskHiddenResponse() From 94a9cdc473e70b6aa818e9772a552e3ddec536d5 Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Thu, 11 Apr 2013 23:37:28 +0000 Subject: [PATCH 10/20] [Routing][XML Loader] Add a possibility to set a default value to null --- src/Symfony/Component/Routing/Loader/XmlFileLoader.php | 6 +++++- .../Component/Routing/Loader/schema/routing/routing-1.0.xsd | 2 +- .../Component/Routing/Tests/Fixtures/validpattern.xml | 1 + .../Component/Routing/Tests/Loader/XmlFileLoaderTest.php | 2 ++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 695494bd6e..9d4da3d096 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -141,7 +141,11 @@ class XmlFileLoader extends FileLoader switch ($node->tagName) { case 'default': - $defaults[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); + if ($node->hasAttribute('xsi:nil') && 'true' == $node->getAttribute('xsi:nil')) { + $defaults[(string) $node->getAttribute('key')] = null; + } else { + $defaults[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); + } break; case 'option': $options[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); diff --git a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index 826dfc9c36..af642d846e 100644 --- a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -16,7 +16,7 @@ - + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml b/src/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml index fdb38073a0..740224c0d2 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml +++ b/src/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml @@ -6,6 +6,7 @@ MyBundle:Blog:show + GET diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index e6f217606d..147b6e70a7 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -47,7 +47,9 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals(1, count($routes), 'One route is loaded'); $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + $route = $routes['blog_show']; + $this->assertSame(null, $route->getDefault('slug')); $this->assertEquals('RouteCompiler', $route->getOption('compiler_class')); } From 047212a439fb037bed7e032b0d49b35358c3c9a7 Mon Sep 17 00:00:00 2001 From: Pavel Volokitin Date: Fri, 12 Apr 2013 15:29:40 +0600 Subject: [PATCH 11/20] [Yaml] fixed handling an empty value --- src/Symfony/Component/Yaml/Parser.php | 6 +++--- src/Symfony/Component/Yaml/Tests/ParserTest.php | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index bafceb06c8..8dd9a23c47 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -102,7 +102,7 @@ class Parser $parser->refs =& $this->refs; $block = $values['value']; - if (!$this->isNextLineIndented()) { + if ($this->isNextLineIndented()) { $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2); } @@ -174,7 +174,7 @@ class Parser // hash } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { // if next line is less indented or equal, then it means that the current value is null - if ($this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { + if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { $data[$key] = null; } else { $c = $this->getRealCurrentLineNb() + 1; @@ -493,7 +493,7 @@ class Parser } $ret = false; - if ($this->getCurrentLineIndentation() <= $currentIndentation) { + if ($this->getCurrentLineIndentation() > $currentIndentation) { $ret = true; } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 0e977a3ba4..4eea6d5308 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -492,6 +492,15 @@ yaml: EOF ); } + + public function testEmptyValue() + { + $input = <<assertEquals(array('hash' => null), Yaml::parse($input)); + } } class B From fb686d83de23cb862f4ce129dd4918b142bf437b Mon Sep 17 00:00:00 2001 From: Pavel Volokitin Date: Fri, 12 Apr 2013 15:31:52 +0600 Subject: [PATCH 12/20] [Yaml] improved boolean naming ($notEOF -> !$EOF) --- src/Symfony/Component/Yaml/Parser.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 8dd9a23c47..1e88f85d4a 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -482,13 +482,13 @@ class Parser private function isNextLineIndented() { $currentIndentation = $this->getCurrentLineIndentation(); - $notEOF = $this->moveToNextLine(); + $EOF = !$this->moveToNextLine(); - while ($notEOF && $this->isCurrentLineEmpty()) { - $notEOF = $this->moveToNextLine(); + while (!$EOF && $this->isCurrentLineEmpty()) { + $EOF = !$this->moveToNextLine(); } - if (false === $notEOF) { + if ($EOF) { return false; } From f1632266e4494814c2986f66cde44aafbd92e1ab Mon Sep 17 00:00:00 2001 From: Pavel Volokitin Date: Fri, 12 Apr 2013 18:08:01 +0600 Subject: [PATCH 13/20] fixed output of bag values Call json_encode with flags: JSON_UNESCAPED_SLASHES and JSON_UNESCAPED_UNICODE --- .../Resources/views/Profiler/bag.html.twig | 9 +++++---- .../Resources/views/Profiler/table.html.twig | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/bag.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/bag.html.twig index d9ccadb21b..8947c9a6cb 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/bag.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/bag.html.twig @@ -7,10 +7,11 @@ {% for key in bag.keys|sort %} - - {{ key }} - {{ bag.get(key)|json_encode }} - + + {{ key }} + {# JSON_UNESCAPED_SLASHES = 64, JSON_UNESCAPED_UNICODE = 256 #} + {{ bag.get(key)|json_encode(64 b-or 256) }} + {% endfor %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/table.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/table.html.twig index 06089edaba..1c5130dfba 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/table.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/table.html.twig @@ -9,7 +9,8 @@ {% for key in data|keys|sort %} {{ key }} - {{ data[key]|json_encode }} + {# JSON_UNESCAPED_SLASHES = 64, JSON_UNESCAPED_UNICODE = 256 #} + {{ data[key]|json_encode(64 b-or 256) }} {% endfor %} From 972bde73ce28dd5699048d1beb3ff77d696f04f4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 12 Apr 2013 14:45:07 +0200 Subject: [PATCH 14/20] [HttpKernel] fixed the Kernel when the ClassLoader component is not available (closes #7406) --- src/Symfony/Component/HttpKernel/Kernel.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 6898ea8252..84135b6598 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -101,7 +101,9 @@ abstract class Kernel implements KernelInterface, TerminableInterface if ($this->debug) { error_reporting(-1); - DebugClassLoader::enable(); + if (class_exists('Symfony\Component\ClassLoader\DebugClassLoader')) { + DebugClassLoader::enable(); + } ErrorHandler::register($this->errorReportingLevel); if ('cli' !== php_sapi_name()) { ExceptionHandler::register(); From 46909faff0117ebe6b669ee95c2fa42205adb6e7 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 12 Apr 2013 15:15:07 +0200 Subject: [PATCH 15/20] [Console] Fix merging of application definition, fixes #7068, replaces #7158 --- .../Component/Console/Command/Command.php | 7 +++++- .../Console/Tests/Command/CommandTest.php | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index f475ad5363..f526b85a03 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -36,6 +36,7 @@ class Command private $description; private $ignoreValidationErrors; private $applicationDefinitionMerged; + private $applicationDefinitionMergedWithArgs; private $code; private $synopsis; private $helperSet; @@ -54,6 +55,7 @@ class Command $this->definition = new InputDefinition(); $this->ignoreValidationErrors = false; $this->applicationDefinitionMerged = false; + $this->applicationDefinitionMergedWithArgs = false; $this->aliases = array(); if (null !== $name) { @@ -277,7 +279,7 @@ class Command */ private function mergeApplicationDefinition($mergeArgs = true) { - if (null === $this->application || true === $this->applicationDefinitionMerged) { + if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { return; } @@ -290,6 +292,9 @@ class Command $this->definition->addOptions($this->application->getDefinition()->getOptions()); $this->applicationDefinitionMerged = true; + if ($mergeArgs) { + $this->applicationDefinitionMergedWithArgs = true; + } } /** diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 166ce7879e..8300f8dfe3 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -193,6 +193,29 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options'); } + public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs() + { + $application1 = new Application(); + $application1->getDefinition()->addArguments(array(new InputArgument('foo'))); + $application1->getDefinition()->addOptions(array(new InputOption('bar'))); + $command = new \TestCommand(); + $command->setApplication($application1); + $command->setDefinition($definition = new InputDefinition(array())); + + $r = new \ReflectionObject($command); + $m = $r->getMethod('mergeApplicationDefinition'); + $m->setAccessible(true); + $m->invoke($command, false); + $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the commmand options'); + $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments'); + + $m->invoke($command, true); + $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments'); + + $m->invoke($command); + $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments'); + } + public function testRun() { $command = new \TestCommand(); From 4c51ec78663ad28e1bd4bf553be4f38afd86fd8d Mon Sep 17 00:00:00 2001 From: Nicolas Le Goff Date: Fri, 12 Apr 2013 15:45:42 +0200 Subject: [PATCH 16/20] Fix download over SSL using IE < 8 and binary file response --- .../HttpFoundation/BinaryFileResponse.php | 2 + .../Component/HttpFoundation/Response.php | 24 +++--- .../Tests/BinaryFileResponseTest.php | 7 +- .../HttpFoundation/Tests/ResponseTest.php | 76 ++---------------- .../HttpFoundation/Tests/ResponseTestCase.php | 79 +++++++++++++++++++ 5 files changed, 108 insertions(+), 80 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index cb6c8a1e8a..ea46117262 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -166,6 +166,8 @@ class BinaryFileResponse extends Response $this->setProtocolVersion('1.1'); } + $this->ensureIEOverSSLCompatibility($request); + $this->offset = 0; $this->maxlen = -1; diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 7ac4e80056..248eef3089 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -253,15 +253,7 @@ class Response $this->headers->set('expires', -1); } - /** - * Check if we need to remove Cache-Control for ssl encrypted downloads when using IE < 9 - * @link http://support.microsoft.com/kb/323308 - */ - if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { - if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) { - $this->headers->remove('Cache-Control'); - } - } + $this->ensureIEOverSSLCompatibility($request); return $this; } @@ -1179,4 +1171,18 @@ class Response { return in_array($this->statusCode, array(201, 204, 304)); } + + /** + * Check if we need to remove Cache-Control for ssl encrypted downloads when using IE < 9 + * + * @link http://support.microsoft.com/kb/323308 + */ + protected function ensureIEOverSSLCompatibility(Request $request) + { + if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { + if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) { + $this->headers->remove('Cache-Control'); + } + } + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php index 4d517313f3..c3d324fa9f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php @@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; -class BinaryFileResponseTest extends \PHPUnit_Framework_TestCase +class BinaryFileResponseTest extends ResponseTestCase { public function testConstruction() { @@ -145,4 +145,9 @@ class BinaryFileResponseTest extends \PHPUnit_Framework_TestCase array('/home/foo/bar.txt', '/files/=/var/www/,/baz/=/home/foo/', '/baz/bar.txt'), ); } + + protected function provideResponse() + { + return new BinaryFileResponse('README.md'); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index 28b9d53732..3a084954c4 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -14,7 +14,7 @@ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -class ResponseTest extends \PHPUnit_Framework_TestCase +class ResponseTest extends ResponseTestCase { public function testCreate() { @@ -326,75 +326,6 @@ class ResponseTest extends \PHPUnit_Framework_TestCase $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type')); } - public function testNoCacheControlHeaderOnAttachmentUsingHTTPSAndMSIE() - { - // Check for HTTPS and IE 8 - $request = new Request(); - $request->server->set('HTTPS', true); - $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertFalse($response->headers->has('Cache-Control')); - - // Check for IE 10 and HTTPS - $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - - // Check for IE 9 and HTTPS - $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)'); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - - // Check for IE 9 and HTTP - $request->server->set('HTTPS', false); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - - // Check for IE 8 and HTTP - $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - - // Check for non-IE and HTTPS - $request->server->set('HTTPS', true); - $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17'); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - - // Check for non-IE and HTTP - $request->server->set('HTTPS', false); - - $response = new Response(); - $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); - $response->prepare($request); - - $this->assertTrue($response->headers->has('Cache-Control')); - } - public function testPrepareDoesNothingIfContentTypeIsSet() { $response = new Response('foo'); @@ -770,6 +701,11 @@ class ResponseTest extends \PHPUnit_Framework_TestCase { return new \DateTime(); } + + protected function provideResponse() + { + return new Response(); + } } class StringableObject diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php new file mode 100644 index 0000000000..2728106629 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php @@ -0,0 +1,79 @@ +server->set('HTTPS', true); + $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertFalse($response->headers->has('Cache-Control')); + + // Check for IE 10 and HTTPS + $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + + // Check for IE 9 and HTTPS + $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)'); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + + // Check for IE 9 and HTTP + $request->server->set('HTTPS', false); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + + // Check for IE 8 and HTTP + $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + + // Check for non-IE and HTTPS + $request->server->set('HTTPS', true); + $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17'); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + + // Check for non-IE and HTTP + $request->server->set('HTTPS', false); + + $response = $this->provideResponse(); + $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); + $response->prepare($request); + + $this->assertTrue($response->headers->has('Cache-Control')); + } + + abstract protected function provideResponse(); +} From d552e4c3962b79ff6115b9bb12919c2802ca7d8a Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Fri, 12 Apr 2013 17:03:10 +0200 Subject: [PATCH 17/20] [HttpFoundation] do not use server variable PATH_INFO because it is already decoded and thus symfony is fragile to double encoding of the path --- src/Symfony/Component/HttpFoundation/ApacheRequest.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/ApacheRequest.php b/src/Symfony/Component/HttpFoundation/ApacheRequest.php index ca8f8eebbf..84803ebae2 100644 --- a/src/Symfony/Component/HttpFoundation/ApacheRequest.php +++ b/src/Symfony/Component/HttpFoundation/ApacheRequest.php @@ -40,12 +40,4 @@ class ApacheRequest extends Request return $baseUrl; } - - /** - * {@inheritdoc} - */ - protected function preparePathInfo() - { - return $this->server->get('PATH_INFO') ?: substr($this->prepareRequestUri(), strlen($this->prepareBaseUrl())) ?: '/'; - } } From 60841766db90e04a40c8eba0e1d33ea91306407b Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sat, 13 Apr 2013 16:29:50 +0200 Subject: [PATCH 18/20] Disabled APC on Travis for PHP 5.5+ as it is not available --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3d3b6fa29c..26a226bd8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ matrix: - php: 5.5 before_script: - - echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + - sh -c 'if [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;' - COMPOSER_ROOT_VERSION=2.1.x-dev composer --prefer-source --dev install - php src/Symfony/Component/Locale/Resources/data/build-data.php - export USE_INTL_ICU_DATA_VERSION=1 From 1adbe3cad633ed74af8a3733e18e9670b9aa3f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Sat, 13 Apr 2013 20:14:39 +0200 Subject: [PATCH 19/20] [HttpKernel] truncate profiler token to 6 chars (see #7665) --- src/Symfony/Component/HttpKernel/Profiler/Profiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index 97fb37f63c..5b7b99a314 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -165,7 +165,7 @@ class Profiler return; } - $profile = new Profile(sha1(uniqid(mt_rand(), true))); + $profile = new Profile(substr(sha1(uniqid(mt_rand(), true)), 0, 6)); $profile->setTime(time()); $profile->setUrl($request->getUri()); $profile->setIp($request->getClientIp()); From 5abf887180e404ac227ff744d3a8a93139ecae9f Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Tue, 16 Apr 2013 18:01:36 -0400 Subject: [PATCH 20/20] Fix default value handling for multi-value options The default value for array options will be an array, so it is not suitable to use as the default when processing one of many values for a multi-value option. Using null seems appropriate here, as it indicates the absence of a value and also converts nicely to an empty string (as opposed to an empty array). Fixes #7689 --- .../Component/Console/Input/ArgvInput.php | 9 ++++++++- .../Console/Tests/Input/ArgvInputTest.php | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index 9addf1483d..0f9b62c53f 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -215,6 +215,11 @@ class ArgvInput extends Input $option = $this->definition->getOption($name); + // Convert false values (from a previous call to substr()) to null + if (false === $value) { + $value = null; + } + if (null === $value && $option->acceptValue() && count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided @@ -233,7 +238,9 @@ class ArgvInput extends Input throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); } - $value = $option->isValueOptional() ? $option->getDefault() : true; + if (!$option->isArray()) { + $value = $option->isValueOptional() ? $option->getDefault() : true; + } } if ($option->isArray()) { diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index fc7ab21834..472a91580c 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -162,7 +162,22 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz')); $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); - $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions()); + $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option=value" syntax)'); + + $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', 'baz')); + $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); + $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option value" syntax)'); + + $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=')); + $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); + $this->assertSame(array('name' => array('foo', 'bar', null)), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)'); + + $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', '--anotherOption')); + $input->bind(new InputDefinition(array( + new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY), + new InputOption('anotherOption', null, InputOption::VALUE_NONE), + ))); + $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options as null ("--option value" syntax)'); try { $input = new ArgvInput(array('cli.php', '-1'));