From 6fe8435c6fb74c55b3c6b16fcb53c1677d8309ad Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 10 Nov 2017 11:52:56 -0800 Subject: [PATCH 1/8] bumped Symfony version to 2.7.37 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 80e06235959ce..8bfd79b6c14ea 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.36'; - const VERSION_ID = 20736; + const VERSION = '2.7.37-DEV'; + const VERSION_ID = 20737; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 36; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 37; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 18f0fc594d039a7f87fed5ee28053dba348319b1 Mon Sep 17 00:00:00 2001 From: Jeremiah VALERIE Date: Thu, 9 Nov 2017 15:39:19 +0100 Subject: [PATCH 2/8] [ExpressionLanguage] Fix PhpDoc type-hints on Token value Also added tests to cover number parser BC --- .../ExpressionLanguage/Tests/ExpressionLanguageTest.php | 8 ++++++++ src/Symfony/Component/ExpressionLanguage/Token.php | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 0ef278c901496..50a0eb5e95aae 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -116,6 +116,14 @@ public function testCachingForOverriddenVariableNames() $this->assertSame('($a + $B)', $result); } + public function testStrictEquality() + { + $expressionLanguage = new ExpressionLanguage(); + $expression = '123 === a'; + $result = $expressionLanguage->compile($expression, array('a')); + $this->assertSame('(123 === $a)', $result); + } + public function testCachingWithDifferentNamesOrder() { $cacheMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); diff --git a/src/Symfony/Component/ExpressionLanguage/Token.php b/src/Symfony/Component/ExpressionLanguage/Token.php index b231bc25e73f2..4517335bbc739 100644 --- a/src/Symfony/Component/ExpressionLanguage/Token.php +++ b/src/Symfony/Component/ExpressionLanguage/Token.php @@ -30,9 +30,9 @@ class Token const PUNCTUATION_TYPE = 'punctuation'; /** - * @param string $type The type of the token (self::*_TYPE) - * @param string $value The token value - * @param int $cursor The cursor position in the source + * @param string $type The type of the token (self::*_TYPE) + * @param string|int|float|null $value The token value + * @param int $cursor The cursor position in the source */ public function __construct($type, $value, $cursor) { From 965b5b5f8da80becc9476b522e23ba0eb47b300a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 11 Nov 2017 23:09:14 +0100 Subject: [PATCH 3/8] [Console] Fix traversable autocomplete values --- .../Console/Helper/QuestionHelper.php | 6 +-- .../Component/Console/Question/Question.php | 6 +-- .../Tests/Helper/QuestionHelperTest.php | 49 +++++++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 1f3e4ff14ac38..2034ce14a4c39 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -134,7 +134,7 @@ public function doAsk(OutputInterface $output, Question $question) $ret = trim($ret); } } else { - $ret = trim($this->autocomplete($output, $question, $inputStream)); + $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false))); } $ret = strlen($ret) > 0 ? $ret : $question->getDefault(); @@ -190,12 +190,12 @@ protected function writeError(OutputInterface $output, \Exception $error) * @param OutputInterface $output * @param Question $question * @param resource $inputStream + * @param array $autocomplete * * @return string */ - private function autocomplete(OutputInterface $output, Question $question, $inputStream) + private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete) { - $autocomplete = $question->getAutocompleterValues(); $ret = ''; $i = 0; diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index 64c9205749c51..bece3e59752ad 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -137,10 +137,8 @@ public function setAutocompleterValues($values) $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); } - if (null !== $values && !is_array($values)) { - if (!$values instanceof \Traversable || !$values instanceof \Countable) { - throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.'); - } + if (null !== $values && !is_array($values) && !$values instanceof \Traversable) { + throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.'); } if ($this->hidden) { diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 69a2256efad2b..3538cbc0b7ac1 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -514,6 +514,40 @@ public function testEmptyChoices() new ChoiceQuestion('Question', array(), 'irrelevant'); } + public function testTraversableAutocomplete() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + // Acm + // AcsTest + // + // + // Test + // + // S + // 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 QuestionHelper(); + $dialog->setInputStream($inputStream); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new Question('Please select a bundle', 'FrameworkBundle'); + $question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'))); + + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + protected function getInputStream($input) { $stream = fopen('php://memory', 'r+', false); @@ -545,3 +579,18 @@ private function hasSttyAvailable() return 0 === $exitcode; } } + +class AutocompleteValues implements \IteratorAggregate +{ + private $values; + + public function __construct(array $values) + { + $this->values = $values; + } + + public function getIterator() + { + return new \ArrayIterator($this->values); + } +} From b862168cd043108fd1e5c999c953f57f0e6c4367 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 13 Nov 2017 06:34:51 +0100 Subject: [PATCH 4/8] fix method name --- src/Symfony/Component/Form/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 83f0055e0c2e0..26c6c2077ecac 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -50,7 +50,7 @@ * either as "Y-m-d" string or as timestamp. Internally we still want to * use a DateTime object for processing. To convert the data from string/integer * to DateTime you can set a normalization transformer by calling - * addNormTransformer(). The normalized data is then converted to the displayed + * addModelTransformer(). The normalized data is then converted to the displayed * data as described before. * * The conversions (1) -> (2) -> (3) use the transform methods of the transformers. From 3eaa18889c5ca3c0573c78ad523d3101f83deea5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Nov 2017 16:41:44 +0100 Subject: [PATCH 5/8] [HttpFoundation] Fix session-related BC break --- .../Session/Storage/NativeSessionStorage.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index e35af4e291a70..f03cdf343024d 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -102,12 +102,6 @@ class NativeSessionStorage implements SessionStorageInterface */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { - $this->setMetadataBag($metaBag); - - if (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) { - return; - } - $options += array( // disable by default because it's managed by HeaderBag (if used) 'cache_limiter' => '', @@ -120,6 +114,7 @@ public function __construct(array $options = array(), $handler = null, MetadataB register_shutdown_function('session_write_close'); } + $this->setMetadataBag($metaBag); $this->setOptions($options); $this->setSaveHandler($handler); } @@ -292,7 +287,7 @@ public function getBag($name) throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } - if ($this->saveHandler->isActive() && !$this->started) { + if (!$this->started && $this->saveHandler->isActive()) { $this->loadSession(); } elseif (!$this->started) { $this->start(); @@ -340,7 +335,7 @@ public function isStarted() */ public function setOptions(array $options) { - if (headers_sent()) { + if (headers_sent() || (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status())) { return; } @@ -395,10 +390,6 @@ public function setSaveHandler($saveHandler = null) throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); } - if (headers_sent($file, $line)) { - throw new \RuntimeException(sprintf('Failed to set the session handler because headers have already been sent by "%s" at line %d.', $file, $line)); - } - // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); @@ -408,6 +399,10 @@ public function setSaveHandler($saveHandler = null) } $this->saveHandler = $saveHandler; + if (headers_sent() || (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status())) { + return; + } + if ($this->saveHandler instanceof \SessionHandlerInterface) { if (\PHP_VERSION_ID >= 50400) { session_set_save_handler($this->saveHandler, false); From 38186aab2fbfffad55c05311e9a794689eb9295a Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Mon, 13 Nov 2017 13:14:59 +0000 Subject: [PATCH 6/8] [HttpFoundation] Add test --- .../Session/Storage/NativeSessionStorageTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 673cd386bf6aa..7eb7e56478ce5 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -296,4 +296,19 @@ public function testSetSessionOptionsOnceSessionStartedIsIgnored() // Assert no exception has been thrown by `getStorage()` $this->addToAssertionCount(1); } + + /** + * @requires PHP 5.4 + */ + public function testGetBagsOnceSessionStartedIsIgnored() + { + session_start(); + $bag = new AttributeBag(); + $bag->setName('flashes'); + + $storage = $this->getStorage(); + $storage->registerBag($bag); + + $this->assertEquals($storage->getBag('flashes'), $bag); + } } From 2a70d55b9f32ec90883b36c2ede6fb04cd312a94 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 13 Nov 2017 10:51:16 -0800 Subject: [PATCH 7/8] updated CHANGELOG for 2.7.37 --- CHANGELOG-2.7.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index d190ea2b7fd08..371e8c464e7a1 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,11 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.37 (2017-11-13) + + * bug #24952 [HttpFoundation] Fix session-related BC break (nicolas-grekas, sroze) + * bug #24929 [Console] Fix traversable autocomplete values (ro0NL) + * 2.7.36 (2017-11-10) * bug #24888 [FrameworkBundle] Specifically inject the debug dispatcher in the collector (ogizanagi) From 9a161068bc6fac5255a25c365210716f3a37211e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 13 Nov 2017 10:51:22 -0800 Subject: [PATCH 8/8] updated VERSION for 2.7.37 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8bfd79b6c14ea..9bfee93d6270f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.37-DEV'; + const VERSION = '2.7.37'; const VERSION_ID = 20737; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 37; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019';