From 059f59a106634ba9e408c70c8dea557a9bd6c658 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 13 Nov 2017 20:26:33 +0100 Subject: [PATCH 01/36] Fix ambiguous pattern --- src/Symfony/Component/Validator/Constraints/UrlValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 56857de63c49a..4498bd167ca79 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -25,7 +25,7 @@ class UrlValidator extends ConstraintValidator (%s):// # protocol (([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth ( - ([\pL\pN\pS-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name + ([\pL\pN\pS\-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address | # or From 278088931b4a7171bb616a1eec08cfb98c632afa Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 14 Nov 2017 19:49:30 +0100 Subject: [PATCH 02/36] Replace array|\Traversable by iterable --- src/Symfony/Component/Console/Application.php | 4 +-- .../Component/Console/Question/Question.php | 4 +-- .../Component/Filesystem/Filesystem.php | 34 +++++++++---------- .../Form/ChoiceList/ArrayChoiceList.php | 10 +++--- .../Factory/ChoiceListFactoryInterface.php | 6 ++-- .../Factory/PropertyAccessDecorator.php | 2 +- .../Data/Bundle/Writer/TextBundleWriter.php | 10 +++--- .../PropertyAccess/PropertyAccessor.php | 10 +++--- .../RecursiveContextualValidator.php | 2 +- 9 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 8964f10789bec..a6e7c35d148fe 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -1015,8 +1015,8 @@ public function extractNamespace($name, $limit = null) * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * - * @param string $name The string - * @param array|\Traversable $collection The collection + * @param string $name The string + * @param iterable $collection The collection * * @return string[] A sorted array of similar string */ diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index bece3e59752ad..d94836b85b785 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -114,7 +114,7 @@ public function setHiddenFallback($fallback) /** * Gets values for the autocompleter. * - * @return null|array|\Traversable + * @return null|iterable */ public function getAutocompleterValues() { @@ -124,7 +124,7 @@ public function getAutocompleterValues() /** * Sets values for the autocompleter. * - * @param null|array|\Traversable $values + * @param null|iterable $values * * @return $this * diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 1c10366cee414..40371d9307cd2 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -83,8 +83,8 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) /** * Creates a directory recursively. * - * @param string|array|\Traversable $dirs The directory path - * @param int $mode The directory mode + * @param string|iterable $dirs The directory path + * @param int $mode The directory mode * * @throws IOException On any directory creation failure */ @@ -111,7 +111,7 @@ public function mkdir($dirs, $mode = 0777) /** * Checks the existence of files or directories. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to check * * @return bool true if the file exists, false otherwise */ @@ -135,9 +135,9 @@ public function exists($files) /** * Sets access and modification time of file. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create - * @param int $time The touch time as a Unix timestamp - * @param int $atime The access time as a Unix timestamp + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create + * @param int $time The touch time as a Unix timestamp + * @param int $atime The access time as a Unix timestamp * * @throws IOException When touch fails */ @@ -154,7 +154,7 @@ public function touch($files, $time = null, $atime = null) /** * Removes files or directories. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to remove * * @throws IOException When removal fails */ @@ -190,10 +190,10 @@ public function remove($files) /** * Change mode for an array of files or directories. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode - * @param int $mode The new mode (octal) - * @param int $umask The mode mask (octal) - * @param bool $recursive Whether change the mod recursively or not + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change mode + * @param int $mode The new mode (octal) + * @param int $umask The mode mask (octal) + * @param bool $recursive Whether change the mod recursively or not * * @throws IOException When the change fail */ @@ -212,9 +212,9 @@ public function chmod($files, $mode, $umask = 0000, $recursive = false) /** * Change the owner of an array of files or directories. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner - * @param string $user The new owner user name - * @param bool $recursive Whether change the owner recursively or not + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner + * @param string $user The new owner user name + * @param bool $recursive Whether change the owner recursively or not * * @throws IOException When the change fail */ @@ -239,9 +239,9 @@ public function chown($files, $user, $recursive = false) /** * Change the group of an array of files or directories. * - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group - * @param string $group The group name - * @param bool $recursive Whether change the group recursively or not + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group + * @param string $group The group name + * @param bool $recursive Whether change the group recursively or not * * @throws IOException When the change fail */ diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index 676987e641216..418aa3200cc17 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -58,11 +58,11 @@ class ArrayChoiceList implements ChoiceListInterface * * The given choice array must have the same array keys as the value array. * - * @param array|\Traversable $choices The selectable choices - * @param callable|null $value The callable for creating the value - * for a choice. If `null` is passed, - * incrementing integers are used as - * values + * @param iterable $choices The selectable choices + * @param callable|null $value The callable for creating the value + * for a choice. If `null` is passed, + * incrementing integers are used as + * values */ public function __construct($choices, $value = null) { diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php index 7933dd91d48d7..c66ce0f028d37 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php @@ -31,9 +31,9 @@ interface ChoiceListFactoryInterface * The callable receives the choice as first and the array key as the second * argument. * - * @param array|\Traversable $choices The choices - * @param null|callable $value The callable generating the choice - * values + * @param iterable $choices The choices + * @param null|callable $value The callable generating the choice + * values * * @return ChoiceListInterface The choice list */ diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php index 82b2082f33e1f..42f7b916f6ed6 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php @@ -63,7 +63,7 @@ public function getDecoratedFactory() /** * {@inheritdoc} * - * @param array|\Traversable $choices The choices + * @param iterable $choices The choices * @param null|callable|string|PropertyPath $value The callable or path for * generating the choice values * diff --git a/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php b/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php index 3a444fd350edb..20fad5347aed2 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php @@ -195,11 +195,11 @@ private function writeArray($file, array $value, $indentation) /** * Writes a "table" node. * - * @param resource $file The file handle to write to - * @param array|\Traversable $value The value of the node - * @param int $indentation The number of levels to indent - * @param bool $fallback Whether the table should be merged - * with the fallback locale + * @param resource $file The file handle to write to + * @param iterable $value The value of the node + * @param int $indentation The number of levels to indent + * @param bool $fallback Whether the table should be merged + * with the fallback locale * * @throws UnexpectedTypeException when $value is not an array and not a * \Traversable instance diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 4ce814a538479..233a6fe2f3fe7 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -611,11 +611,11 @@ private function writeProperty($zval, $property, $value) /** * Adjusts a collection-valued property by calling add*() and remove*() methods. * - * @param array $zval The array containing the object to write to - * @param string $property The property to write - * @param array|\Traversable $collection The collection to write - * @param string $addMethod The add*() method - * @param string $removeMethod The remove*() method + * @param array $zval The array containing the object to write to + * @param string $property The property to write + * @param iterable $collection The collection to write + * @param string $addMethod The add*() method + * @param string $removeMethod The remove*() method */ private function writeCollection($zval, $property, $collection, $addMethod, $removeMethod) { diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index acb43283967ca..00c1c4d6e480a 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -378,7 +378,7 @@ private function validateObject($object, $propertyPath, array $groups, $traversa * objects are iterated as well. Nested arrays are always iterated, * regardless of the value of $recursive. * - * @param array|\Traversable $collection The collection + * @param iterable $collection The collection * @param string $propertyPath The current property path * @param string[] $groups The validated groups * @param bool $stopRecursion Whether to disable From ddffd6163f76b840b95deb155302617900888354 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 16 Nov 2017 17:24:08 +0100 Subject: [PATCH 03/36] updated CHANGELOG for 2.7.38 --- CHANGELOG-2.7.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 371e8c464e7a1..7ac65a77371f6 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,13 @@ 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.38 (2017-11-16) + + * security #24995 Validate redirect targets using the session cookie domain (nicolas-grekas) + * security #24994 Prevent bundle readers from breaking out of paths (xabbuh) + * security #24993 Ensure that submitted data are uploaded files (xabbuh) + * security #24992 Namespace generated CSRF tokens depending of the current scheme (dunglas) + * 2.7.37 (2017-11-13) * bug #24952 [HttpFoundation] Fix session-related BC break (nicolas-grekas, sroze) From 330c5e5577c1b727d0c3175377184c17dc791510 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 16 Nov 2017 17:24:22 +0100 Subject: [PATCH 04/36] updated VERSION for 2.7.38 --- 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 f78633744e12f..b1ba60fd65ed1 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.38-DEV'; + const VERSION = '2.7.38'; const VERSION_ID = 20738; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 38; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From c963178206515c40968c01dcccdbd9ddbc250fe1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 17 Nov 2017 07:26:23 +0100 Subject: [PATCH 05/36] bumped Symfony version to 2.7.39 --- 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 b1ba60fd65ed1..466e01b172ecb 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.38'; - const VERSION_ID = 20738; + const VERSION = '2.7.39-DEV'; + const VERSION_ID = 20739; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 38; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 39; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 58352f2f0291df9c2f63a4bfd82a0056dbe85f0b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 17 Nov 2017 07:34:32 +0100 Subject: [PATCH 06/36] bumped Symfony version to 2.8.32 --- 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 3e0993a126f05..0bfec287a98b3 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.31'; - const VERSION_ID = 20831; + const VERSION = '2.8.32-DEV'; + const VERSION_ID = 20832; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 31; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 32; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 3822c07f65c33295d40cac129d4b0d213463bb37 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 17 Nov 2017 13:59:02 +0100 Subject: [PATCH 07/36] [Console] Remove remaining dead code --- src/Symfony/Component/Console/Application.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 8964f10789bec..84f2cca7c34fc 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -113,11 +113,10 @@ public function run(InputInterface $input = null, OutputInterface $output = null $e = null; $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { - } catch (\Throwable $e) { } if (null !== $e) { - if (!$this->catchExceptions || !$e instanceof \Exception) { + if (!$this->catchExceptions) { throw $e; } From 20f9b758574718d52106014a519a1832ebcb6304 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 17 Nov 2017 15:26:00 +0100 Subject: [PATCH 08/36] [SecurityBundle] Fix syntax error in test --- .../Compiler/AddSessionDomainConstraintPassTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php index f476b5ef7313e..7d49ad3dd4ec6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php @@ -124,7 +124,8 @@ private function createContainer($sessionStorageOptions) $ext = new SecurityExtension(); $ext->load($config, $container); - (new AddSessionDomainConstraintPass())->process($container); + $pass = new AddSessionDomainConstraintPass(); + $pass->process($container); return $container; } From 1f8db731a0dd6ba464f04c0cde2752a8f4be4102 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Wed, 15 Nov 2017 16:25:33 +0100 Subject: [PATCH 09/36] [Console] Fix global console flag when used in chain --- src/Symfony/Component/Console/Input/ArgvInput.php | 8 ++++++++ .../Component/Console/Tests/Input/ArgvInputTest.php | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index c2f533eb36798..4493a5bafc3b9 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -282,6 +282,14 @@ public function hasParameterOption($values) if ($token === $value || 0 === strpos($token, $value.'=')) { return true; } + + if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) { + $searchableToken = str_replace('-', '', $token); + $searchableValue = str_replace('-', '', $value); + if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) { + return true; + } + } } } diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 1fe21d0f6c1a8..85fb533715b62 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -296,6 +296,9 @@ public function testHasParameterOption() $input = new ArgvInput(array('cli.php', '-f', 'foo')); $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '-fh')); + $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '--foo', 'foo')); $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input'); From a5122174312fb9e3ea6c5fc6c20667d55e5a0516 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 19 Nov 2017 20:49:57 +0200 Subject: [PATCH 10/36] Remove function_exists(__phpunit_run_isolated_test) checks --- src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php | 4 +--- .../Component/Routing/Tests/Fixtures/validresource.php | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php index d338ca9d5752b..21e0aba17d358 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php @@ -1,5 +1,3 @@ import('validpattern.php'); From 675a3fe7f616ceda079f90c96c8da692bf698fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Strzelecki?= Date: Thu, 24 Jul 2014 10:48:45 +0200 Subject: [PATCH 11/36] added ability for substitute aliases when mapping in YAML is on single line --- src/Symfony/Component/Yaml/Parser.php | 55 ++++++++++++++++++- .../Yaml/Tests/Fixtures/sfMergeKey.yml | 8 ++- .../Component/Yaml/Tests/ParserTest.php | 12 ++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 8ffa8ccf64940..93b2fca4d71b9 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -491,6 +491,59 @@ private function moveToPreviousLine() return true; } + /** + * Substitute from alias where is used a << + * + * @param mixed $values Parsed YAML in which aliases are not substituted + * + * @return mixed YAML with substituted aliases + * + * @throws Exception\ParseException When indentation problem are detected + */ + private function substituteAliases($values) + { + if (is_array($values)) { + $keys = array(); + foreach ($values as $key => $value) { + if ($key ==='<<' && preg_grep('/^\*.+/', (array) $value) === array_values((array) $value)) { + $values[$key] = array(); + foreach ((array) $value as $ref) { + $refName = substr($ref, 1); + if (!array_key_exists($refName, $this->refs)) { + throw new ParseException( + sprintf('Reference "%s" does not exist.', $refName), + $this->getRealCurrentLineNb() + 1, + $this->currentLine + ); + } + + $keys = array_merge( + $keys, + array_diff(array_keys($this->refs[$refName]), $keys) + ); + $values[$key] = array_replace($this->refs[$refName], $values[$key]); + } + } elseif (!isset($result[$key]) || is_array($result[$key])) { + $keys[] = $key; + $values[$key] = $this->substituteAliases($value); + } + } + + if (isset($values['<<'])) { + $values = array_replace($values['<<'], $values); + unset($values['<<']); + uksort( + $values, + function ($a, $b) use ($keys) { + return array_search($a, $keys, true) - array_search($b, $keys, true); + } + ); + } + } + + return $values; + } + /** * Parses a YAML value. * @@ -526,7 +579,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob } try { - return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); + return $this->substituteAliases(Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs)); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml index 59f612514170a..a37eca2e3cd73 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml @@ -22,6 +22,7 @@ yaml: | foo: bar foo: ignore bar: foo + bar_inline: {a: before, d: other, <<: *foo, b: new, x: Oren, c: { foo: bar, foo: ignore, bar: foo}} duplicate: foo: bar foo: ignore @@ -46,15 +47,20 @@ yaml: | p: 12345 z: <<: *nestedref + head_inline: &head_inline { <<: [ *foo , *dong , *foo2 ] } + recursive_inline: { <<: *head_inline, c: { <<: *foo2 } } php: | array( 'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'), 'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), + 'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), 'duplicate' => array('foo' => 'bar'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), 'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)), - 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)) + 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)), + 'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'), + 'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'fi', 'fei', 'fo', 'fam') ) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 9be278f67ec92..97ce0cac0f770 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1207,6 +1207,18 @@ public function testParseReferencesOnMergeKeys() $this->assertSame($expected, $this->parser->parse($yaml)); } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Reference "foo" does not exist + */ + public function testEvalRefException() + { + $yaml = <<parser->parse($yaml); + } } class B From dd26c80aa95c32af0ddbf195b2bab1cd29c74b7b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 20 Nov 2017 08:47:12 +0100 Subject: [PATCH 12/36] substitute aliases in inline mappings --- src/Symfony/Component/Yaml/Inline.php | 22 +++++++- src/Symfony/Component/Yaml/Parser.php | 55 +------------------ .../Yaml/Tests/Fixtures/sfMergeKey.yml | 6 +- 3 files changed, 23 insertions(+), 60 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 9ff9b89c1c123..31a0514fd4972 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -365,6 +365,7 @@ private static function parseMapping($mapping, &$i = 0, $references = array()) $output = array(); $len = strlen($mapping); ++$i; + $allowOverwrite = false; // {foo: bar, bar:foo, ...} while ($i < $len) { @@ -384,6 +385,10 @@ private static function parseMapping($mapping, &$i = 0, $references = array()) // key $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); + if ('<<' === $key) { + $allowOverwrite = true; + } + // value $done = false; @@ -395,7 +400,12 @@ private static function parseMapping($mapping, &$i = 0, $references = array()) // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. - if (!isset($output[$key])) { + // But overwriting is allowed when a merge node is used in current block. + if ('<<' === $key) { + foreach ($value as $parsedValue) { + $output += $parsedValue; + } + } elseif ($allowOverwrite || !isset($output[$key])) { $output[$key] = $value; } $done = true; @@ -406,7 +416,10 @@ private static function parseMapping($mapping, &$i = 0, $references = array()) // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. - if (!isset($output[$key])) { + // But overwriting is allowed when a merge node is used in current block. + if ('<<' === $key) { + $output += $value; + } elseif ($allowOverwrite || !isset($output[$key])) { $output[$key] = $value; } $done = true; @@ -419,7 +432,10 @@ private static function parseMapping($mapping, &$i = 0, $references = array()) // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. - if (!isset($output[$key])) { + // But overwriting is allowed when a merge node is used in current block. + if ('<<' === $key) { + $output += $value; + } elseif ($allowOverwrite || !isset($output[$key])) { $output[$key] = $value; } $done = true; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 93b2fca4d71b9..8ffa8ccf64940 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -491,59 +491,6 @@ private function moveToPreviousLine() return true; } - /** - * Substitute from alias where is used a << - * - * @param mixed $values Parsed YAML in which aliases are not substituted - * - * @return mixed YAML with substituted aliases - * - * @throws Exception\ParseException When indentation problem are detected - */ - private function substituteAliases($values) - { - if (is_array($values)) { - $keys = array(); - foreach ($values as $key => $value) { - if ($key ==='<<' && preg_grep('/^\*.+/', (array) $value) === array_values((array) $value)) { - $values[$key] = array(); - foreach ((array) $value as $ref) { - $refName = substr($ref, 1); - if (!array_key_exists($refName, $this->refs)) { - throw new ParseException( - sprintf('Reference "%s" does not exist.', $refName), - $this->getRealCurrentLineNb() + 1, - $this->currentLine - ); - } - - $keys = array_merge( - $keys, - array_diff(array_keys($this->refs[$refName]), $keys) - ); - $values[$key] = array_replace($this->refs[$refName], $values[$key]); - } - } elseif (!isset($result[$key]) || is_array($result[$key])) { - $keys[] = $key; - $values[$key] = $this->substituteAliases($value); - } - } - - if (isset($values['<<'])) { - $values = array_replace($values['<<'], $values); - unset($values['<<']); - uksort( - $values, - function ($a, $b) use ($keys) { - return array_search($a, $keys, true) - array_search($b, $keys, true); - } - ); - } - } - - return $values; - } - /** * Parses a YAML value. * @@ -579,7 +526,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob } try { - return $this->substituteAliases(Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs)); + return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml index a37eca2e3cd73..499446c10cb76 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml @@ -53,7 +53,7 @@ php: | array( 'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'), 'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), - 'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), + 'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'e' => 'notnull', 'x' => 'Oren'), 'duplicate' => array('foo' => 'bar'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), @@ -61,6 +61,6 @@ php: | 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), 'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)), 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)), - 'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'), - 'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'fi', 'fei', 'fo', 'fam') + 'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), + 'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), ) From faf5470fd5498b9ae4d1faf83bd0266ba7ccfcdb Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Mon, 20 Nov 2017 13:43:41 +0900 Subject: [PATCH 13/36] [Form] Add phpdoc to `RequestHandlerInterface::isFileUpload()` method --- .../Extension/HttpFoundation/HttpFoundationRequestHandler.php | 3 +++ src/Symfony/Component/Form/NativeRequestHandler.php | 3 +++ src/Symfony/Component/Form/RequestHandlerInterface.php | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php index 368a5a80a1481..571db0eb41dfc 100644 --- a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -108,6 +108,9 @@ public function handleRequest(FormInterface $form, $request = null) $form->submit($data, 'PATCH' !== $method); } + /** + * {@inheritdoc} + */ public function isFileUpload($data) { return $data instanceof File; diff --git a/src/Symfony/Component/Form/NativeRequestHandler.php b/src/Symfony/Component/Form/NativeRequestHandler.php index f68efe25cfe54..37e1c99a74505 100644 --- a/src/Symfony/Component/Form/NativeRequestHandler.php +++ b/src/Symfony/Component/Form/NativeRequestHandler.php @@ -118,6 +118,9 @@ public function handleRequest(FormInterface $form, $request = null) $form->submit($data, 'PATCH' !== $method); } + /** + * {@inheritdoc} + */ public function isFileUpload($data) { // POST data will always be strings or arrays of strings. Thus, we can be sure diff --git a/src/Symfony/Component/Form/RequestHandlerInterface.php b/src/Symfony/Component/Form/RequestHandlerInterface.php index e6360e449889f..3d7b45d5064af 100644 --- a/src/Symfony/Component/Form/RequestHandlerInterface.php +++ b/src/Symfony/Component/Form/RequestHandlerInterface.php @@ -27,7 +27,9 @@ interface RequestHandlerInterface public function handleRequest(FormInterface $form, $request = null); /** - * @param mixed $data + * Returns true if the given data is a file upload. + * + * @param mixed $data The form field data * * @return bool */ From 381f5d1bc57c0c51110082e63f255b1bf9607d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 27 Oct 2017 17:09:21 +0200 Subject: [PATCH 14/36] Add a "link" script to ease debugging Flex apps --- link | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 link diff --git a/link b/link new file mode 100755 index 0000000000000..f4070998e72b5 --- /dev/null +++ b/link @@ -0,0 +1,59 @@ +#!/usr/bin/env php + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +require __DIR__.'/src/Symfony/Component/Filesystem/Exception/ExceptionInterface.php'; +require __DIR__.'/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php'; +require __DIR__.'/src/Symfony/Component/Filesystem/Exception/IOException.php'; +require __DIR__.'/src/Symfony/Component/Filesystem/Filesystem.php'; + +use Symfony\Component\Filesystem\Filesystem; + +/** + * Links dependencies to components to a local clone of the main symfony/symfony GitHub repository. + * + * @author Kévin Dunglas + */ + +if (2 !== $argc) { + echo 'Link dependencies to components to a local clone of the main symfony/symfony GitHub repository.'.PHP_EOL.PHP_EOL; + echo "Usage: $argv[0] /path/to/the/project".PHP_EOL; + exit(1); +} + +if (!is_dir("$argv[1]/vendor/symfony")) { + echo "The directory \"$argv[1]\" does not exist or the dependencies are not installed, did you forget to run \"composer install\" in your project?".PHP_EOL; + exit(1); +} + +$sfPackages = array('symfony/symfony' => __DIR__); +foreach (glob(__DIR__.'/src/Symfony/{Bundle,Bridge,Component,Component/Security}/*', GLOB_BRACE | GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { + $sfPackages[json_decode(file_get_contents("$dir/composer.json"))->name] = $dir; +} + +$filesystem = new Filesystem(); +foreach (glob("$argv[1]/vendor/symfony/*", GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { + $package = 'symfony/'.basename($dir); + if (is_link($dir)) { + echo "\"$package\" is already a symlink, skipping.".PHP_EOL; + continue; + } + + if (!isset($sfPackages[$package])) { + continue; + } + + $sfDir = '\\' === DIRECTORY_SEPARATOR ? $sfPackages[$package] : $filesystem->makePathRelative($sfPackages[$package], dirname(realpath($dir))); + + $filesystem->remove($dir); + $filesystem->symlink($sfDir, $dir); + echo "\"$package\" has been linked to \"$sfPackages[$package]\".".PHP_EOL; +} From a35d4f88b34fca0883fc904838f85447c0ff788a Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Mon, 20 Nov 2017 15:44:43 +0900 Subject: [PATCH 15/36] [Form] Rename `FormConfigBuilder::$nativeRequestProcessor` private variable to `::$nativeRequestHandler` --- src/Symfony/Component/Form/FormConfigBuilder.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index f51881a092c97..243ef89f312cf 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -32,7 +32,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface * * @var NativeRequestHandler */ - private static $nativeRequestProcessor; + private static $nativeRequestHandler; /** * The accepted request methods. @@ -511,10 +511,10 @@ public function getMethod() public function getRequestHandler() { if (null === $this->requestHandler) { - if (null === self::$nativeRequestProcessor) { - self::$nativeRequestProcessor = new NativeRequestHandler(); + if (null === self::$nativeRequestHandler) { + self::$nativeRequestHandler = new NativeRequestHandler(); } - $this->requestHandler = self::$nativeRequestProcessor; + $this->requestHandler = self::$nativeRequestHandler; } return $this->requestHandler; From 5ddb121723daa61766da38598d1b407753355f8a Mon Sep 17 00:00:00 2001 From: Guillaume Aveline <917449+joky@users.noreply.github.com> Date: Tue, 21 Nov 2017 09:21:36 +0100 Subject: [PATCH 16/36] [Bridge/PhpUnit] Remove trailing "\n" from ClockMock::microtime(false) --- src/Symfony/Bridge/PhpUnit/ClockMock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/ClockMock.php b/src/Symfony/Bridge/PhpUnit/ClockMock.php index fe5cd851258d2..8bfb9a6211186 100644 --- a/src/Symfony/Bridge/PhpUnit/ClockMock.php +++ b/src/Symfony/Bridge/PhpUnit/ClockMock.php @@ -66,7 +66,7 @@ public static function microtime($asFloat = false) return self::$now; } - return sprintf("%0.6f %d\n", self::$now - (int) self::$now, (int) self::$now); + return sprintf('%0.6f %d', self::$now - (int) self::$now, (int) self::$now); } public static function register($class) From 1c1a540d2f18ed173789df4f659ddbf419163774 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 20 Nov 2017 20:31:57 +0100 Subject: [PATCH 17/36] Bump phpunit-bridge requirement to 3.4|4.0 --- composer.json | 2 +- phpunit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index f067b4bbe20b2..f263c15d45324 100644 --- a/composer.json +++ b/composer.json @@ -80,7 +80,7 @@ "monolog/monolog": "~1.11", "ircmaxell/password-compat": "~1.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0", - "symfony/phpunit-bridge": "~3.2", + "symfony/phpunit-bridge": "~3.4|~4.0", "egulias/email-validator": "~1.2,>=1.2.1", "sensio/framework-extra-bundle": "^3.0.2" }, diff --git a/phpunit b/phpunit index 53e1a8dc31dbf..86f4cdd5ae0a2 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Tue, 21 Nov 2017 10:41:52 +0100 Subject: [PATCH 18/36] [HttpFoundation] Fix bad merge in NativeSessionStorage --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 6f60a5c762f7d..f03cdf343024d 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -108,7 +108,11 @@ public function __construct(array $options = array(), $handler = null, MetadataB 'use_cookies' => 1, ); - session_register_shutdown(); + if (\PHP_VERSION_ID >= 50400) { + session_register_shutdown(); + } else { + register_shutdown_function('session_write_close'); + } $this->setMetadataBag($metaBag); $this->setOptions($options); From 4f63b3ac28d9d4f20c9eba9d042ac872ff241ebf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 21 Nov 2017 18:42:30 +0100 Subject: [PATCH 19/36] Update github PR template --- .github/PULL_REQUEST_TEMPLATE.md | 3 +-- phpunit | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3af6c2a83bc18..e51cf88761451 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | master / 2.7, 2.8, 3.3, or 3.4 +| Branch? | master for features / 2.7 up to 4.0 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | BC breaks? | yes/no @@ -14,6 +14,5 @@ - Bug fixes must be submitted against the lowest branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against the master branch. -- Please fill in this template according to the PR you're about to submit. - Replace this comment by a description of what your PR is solving. --> diff --git a/phpunit b/phpunit index 86f4cdd5ae0a2..b6783d0ba5d41 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Wed, 22 Nov 2017 09:54:48 +0100 Subject: [PATCH 20/36] Force phpunit-bridge update --- phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit b/phpunit index b6783d0ba5d41..cb572db266937 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Wed, 22 Nov 2017 10:25:38 +0100 Subject: [PATCH 21/36] Force phpunit-bridge update (bis) --- phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit b/phpunit index cb572db266937..c0ffe8ddef9e9 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Thu, 23 Nov 2017 09:59:26 +0100 Subject: [PATCH 22/36] [DI] Fix handling of inlined definitions by ContainerBuilder --- .../DependencyInjection/ContainerBuilder.php | 50 ++++++++++++------- .../Tests/ContainerBuilderTest.php | 22 ++++++++ .../Tests/Fixtures/includes/classes.php | 2 +- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 65ea1c842c04f..59f8cc7d0dcb9 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -441,7 +441,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV $this->loading[$id] = true; try { - $service = $this->createService($definition, $id); + $service = $this->createService($definition, new \SplObjectStorage(), $id); } catch (\Exception $e) { unset($this->loading[$id]); @@ -827,8 +827,12 @@ public function findDefinition($id) * * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code */ - public function createService(Definition $definition, $id, $tryProxy = true) + public function createService(Definition $definition, \SplObjectStorage $inlinedDefinitions, $id = null, $tryProxy = true) { + if (null === $id && isset($inlinedDefinitions[$definition])) { + return $inlinedDefinitions[$definition]; + } + if ($definition instanceof DefinitionDecorator) { throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id)); } @@ -845,11 +849,11 @@ public function createService(Definition $definition, $id, $tryProxy = true) ->instantiateProxy( $container, $definition, - $id, function () use ($definition, $id, $container) { - return $container->createService($definition, $id, false); + $id, function () use ($definition, $inlinedDefinitions, $id, $container) { + return $container->createService($definition, $inlinedDefinitions, $id, false); } ); - $this->shareService($definition, $proxy, $id); + $this->shareService($definition, $proxy, $id, $inlinedDefinitions); return $proxy; } @@ -860,11 +864,11 @@ public function createService(Definition $definition, $id, $tryProxy = true) require_once $parameterBag->resolveValue($definition->getFile()); } - $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments()))); + $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlinedDefinitions); if (null !== $factory = $definition->getFactory()) { if (is_array($factory)) { - $factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]); + $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlinedDefinitions), $factory[1]); } elseif (!is_string($factory)) { throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id)); } @@ -888,16 +892,16 @@ public function createService(Definition $definition, $id, $tryProxy = true) if ($tryProxy || !$definition->isLazy()) { // share only if proxying failed, or if not a proxy - $this->shareService($definition, $service, $id); + $this->shareService($definition, $service, $id, $inlinedDefinitions); } - $properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties()))); + $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlinedDefinitions); foreach ($properties as $name => $value) { $service->$name = $value; } foreach ($definition->getMethodCalls() as $call) { - $this->callMethod($service, $call); + $this->callMethod($service, $call, $inlinedDefinitions); } if ($callable = $definition->getConfigurator()) { @@ -907,7 +911,7 @@ public function createService(Definition $definition, $id, $tryProxy = true) if ($callable[0] instanceof Reference) { $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior()); } elseif ($callable[0] instanceof Definition) { - $callable[0] = $this->createService($callable[0], null); + $callable[0] = $this->createService($callable[0], $inlinedDefinitions); } } @@ -930,15 +934,20 @@ public function createService(Definition $definition, $id, $tryProxy = true) * the real service instances and all expressions evaluated */ public function resolveServices($value) + { + return $this->doResolveServices($value, new \SplObjectStorage()); + } + + private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions) { if (is_array($value)) { foreach ($value as $k => $v) { - $value[$k] = $this->resolveServices($v); + $value[$k] = $this->doResolveServices($v, $inlinedDefinitions); } } elseif ($value instanceof Reference) { $value = $this->get((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { - $value = $this->createService($value, null); + $value = $this->createService($value, $inlinedDefinitions); } elseif ($value instanceof Expression) { $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); } @@ -1065,14 +1074,14 @@ private function synchronize($id) foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { - $this->callMethod($this->get($definitionId), $call); + $this->callMethod($this->get($definitionId), $call, new \SplObjectStorage()); } } } } } - private function callMethod($service, $call) + private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitions) { $services = self::getServiceConditionals($call[1]); @@ -1082,7 +1091,7 @@ private function callMethod($service, $call) } } - call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])))); + call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlinedDefinitions)); } /** @@ -1094,9 +1103,14 @@ private function callMethod($service, $call) * * @throws InactiveScopeException */ - private function shareService(Definition $definition, $service, $id) + private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions) { - if (null !== $id && self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + if (self::SCOPE_PROTOTYPE === $scope = $definition->getScope()) { + return; + } + if (null === $id) { + $inlinedDefinitions[$definition] = $service; + } else { if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { throw new InactiveScopeException($id, $scope); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index f4274b80a4443..32e1b99adb255 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -827,6 +827,28 @@ public function testLazyLoadedService() $this->assertTrue($classInList); } + public function testInlinedDefinitions() + { + $container = new ContainerBuilder(); + + $definition = new Definition('BarClass'); + + $container->register('bar_user', 'BarUserClass') + ->addArgument($definition) + ->setProperty('foo', $definition); + + $container->register('bar', 'BarClass') + ->setProperty('foo', $definition) + ->addMethodCall('setBaz', array($definition)); + + $barUser = $container->get('bar_user'); + $bar = $container->get('bar'); + + $this->assertSame($barUser->foo, $barUser->bar); + $this->assertSame($bar->foo, $bar->getBaz()); + $this->assertNotSame($bar->foo, $barUser->foo); + } + public function testInitializePropertiesBeforeMethodCalls() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index 0ecdea3fbfb89..92db8f3c5ebfb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -8,7 +8,7 @@ function sc_configure($instance) $instance->configure(); } -class BarClass +class BarClass extends BazClass { protected $baz; public $foo = 'foo'; From 1b408e692ddc6d353c89e9684afd96f51ce6d417 Mon Sep 17 00:00:00 2001 From: chihiro-adachi Date: Wed, 22 Nov 2017 19:00:37 +0900 Subject: [PATCH 23/36] [Form] Fixed ContextErrorException in FileType --- .../Form/Extension/Core/Type/FileType.php | 7 ++++++- .../Tests/Extension/Core/Type/FileTypeTest.php | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index fc5b1aae68329..cff7adf1bb2c8 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -34,8 +34,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ($options['multiple']) { $data = array(); + $files = $event->getData(); - foreach ($event->getData() as $file) { + if (!is_array($files)) { + $files = array(null); + } + + foreach ($files as $file) { if ($requestHandler->isFileUpload($file)) { $data[] = $file; } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php index 5d6fe1e20d668..646470ff5abf9 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -158,6 +158,24 @@ public function testMultipleSubmittedFilePathsAreDropped(RequestHandlerInterface $this->assertCount(1, $form->getData()); } + /** + * @dataProvider requestHandlerProvider + */ + public function testSubmitNonArrayValueWhenMultiple(RequestHandlerInterface $requestHandler) + { + $form = $this->factory + ->createBuilder(static::TESTED_TYPE, null, array( + 'multiple' => true, + )) + ->setRequestHandler($requestHandler) + ->getForm(); + $form->submit(null); + + $this->assertSame(array(), $form->getData()); + $this->assertSame(array(), $form->getNormData()); + $this->assertSame(array(), $form->getViewData()); + } + public function requestHandlerProvider() { return array( From 37baa1de512da4390a953bfcc0d59f36e73ddc0e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 23 Nov 2017 12:13:33 +0100 Subject: [PATCH 24/36] Fix merge --- src/Symfony/Component/DependencyInjection/ContainerBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 84863a2fb8245..15da037be7869 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1151,7 +1151,7 @@ private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitio */ private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions) { - if (!$definition->isShared() || self::SCOPE_PROTOTYPE === $scope = $definition->getScope()) { + if (!$definition->isShared() || self::SCOPE_PROTOTYPE === $scope = $definition->getScope(false)) { return; } if (null === $id) { From a264238e8a398029266350ef14d9b1c088cd4161 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Sat, 25 Nov 2017 00:42:53 +0900 Subject: [PATCH 25/36] [Form] Don't rely on if http-foundation isn't in FileType --- .../Component/Form/Extension/Core/Type/FileType.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index ddd5cae0bc3c3..7d84512d9b3c7 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -92,9 +92,12 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function configureOptions(OptionsResolver $resolver) { - $dataClass = function (Options $options) { - return $options['multiple'] ? null : 'Symfony\Component\HttpFoundation\File\File'; - }; + $dataClass = null; + if (class_exists('Symfony\Component\HttpFoundation\File\File')) { + $dataClass = function (Options $options) { + return $options['multiple'] ? null : 'Symfony\Component\HttpFoundation\File\File'; + }; + } $emptyData = function (Options $options) { return $options['multiple'] ? array() : null; From 7fe3fe824547101a9c0d66a558ff1d4873dfe5f0 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Tue, 28 Nov 2017 06:31:17 +0100 Subject: [PATCH 26/36] [HttpFoundation] AutExpireFlashBag should not clear new flashes --- .../HttpFoundation/Session/Flash/AutoExpireFlashBag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php index 59ba309005b38..0ed6600974371 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php @@ -106,7 +106,7 @@ public function get($type, array $default = array()) public function all() { $return = $this->flashes['display']; - $this->flashes = array('new' => array(), 'display' => array()); + $this->flashes['display'] = array(); return $return; } From 706201efe46580e89d3f24d6fa097e065c43a2c8 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Tue, 28 Nov 2017 08:49:55 +0000 Subject: [PATCH 27/36] Test that it do not remove the new flashes when displaying the existing ones --- .../Tests/Session/Flash/AutoExpireFlashBagTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php index 18b71a5021fbb..0e0724a3249a4 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php @@ -150,4 +150,12 @@ public function testClear() { $this->assertEquals(array('notice' => array('A previous flash message')), $this->bag->clear()); } + + public function testDoNotRemoveTheNewFlashesWhenDisplayingTheExistingOnes() + { + $this->bag->add('success', 'Something'); + $this->bag->all(); + + $this->assertEquals(array('new' => array('success' => array('Something')), 'display' => array()), $this->array); + } } From 85058949883eee0b0deafbf5b090704adad28750 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 30 Nov 2017 23:22:28 -0500 Subject: [PATCH 28/36] Fix collision between view properties and form fields --- .../Bridge/Twig/Extension/FormExtension.php | 7 +++++++ .../views/Form/bootstrap_3_layout.html.twig | 4 ++-- .../views/Form/form_div_layout.html.twig | 4 ++-- .../views/Form/form_table_layout.html.twig | 2 +- .../Extension/FormExtensionDivLayoutTest.php | 16 ++++++++++++++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 053b1d4a6b336..aaed8221c1fc8 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -14,6 +14,7 @@ use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Form\TwigRendererInterface; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\FormView; use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\Extension\InitRuntimeInterface; @@ -97,6 +98,7 @@ public function getTests() { return array( new TwigTest('selectedchoice', array($this, 'isSelectedChoice')), + new TwigTest('rootform', array($this, 'isRootForm')), ); } @@ -156,6 +158,11 @@ public function isSelectedChoice(ChoiceView $choice, $selectedValue) return $choice->value === $selectedValue; } + public function isRootForm(FormView $formView) + { + return null === $formView->parent; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index 2efc0c4d4a213..e3c76349648e5 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -238,12 +238,12 @@ {% block form_errors -%} {% if errors|length > 0 -%} - {% if form.parent %}{% else %}
{% endif %} + {% if form is not rootform %}{% else %}
{% endif %}
    {%- for error in errors -%}
  • {{ error.message }}
  • {%- endfor -%}
- {% if form.parent %}{% else %}
{% endif %} + {% if form is not rootform %}
{% else %}
{% endif %} {%- endif %} {%- endblock form_errors %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index a27c81dd495ae..ad00a502a0f71 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -15,7 +15,7 @@ {%- block form_widget_compound -%}
- {%- if form.parent is empty -%} + {%- if form is rootform -%} {{ form_errors(form) }} {%- endif -%} {{- block('form_rows') -}} @@ -303,7 +303,7 @@ {% endif %} {%- endfor %} - {% if not form.methodRendered and form.parent is null %} + {% if not form.methodRendered and form is rootform %} {%- do form.setMethodRendered() -%} {% set method = method|upper %} {%- if method in ["GET", "POST"] -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig index c7b3a4365b51b..39274c6c8d058 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig @@ -31,7 +31,7 @@ {%- block form_widget_compound -%} - {%- if form.parent is empty and errors|length > 0 -%} + {%- if form is rootform and errors|length > 0 -%}
{{- form_errors(form) -}} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index e2fbb48ce0339..e11daf1831349 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -146,6 +146,22 @@ public function testIsChoiceSelected($expected, $choice, $value) $this->assertSame($expected, $this->extension->isSelectedChoice($choice, $value)); } + public function isRootFormProvider() + { + return array( + array(true, new FormView()), + array(false, new FormView(new FormView())), + ); + } + + /** + * @dataProvider isRootFormProvider + */ + public function testIsRootForm($expected, FormView $formView) + { + $this->assertSame($expected, $this->extension->isRootForm($formView)); + } + protected function renderForm(FormView $view, array $vars = array()) { return (string) $this->extension->renderer->renderBlock($view, 'form', $vars); From 7dac528a8609251f7765413ca3d655a5f7a5001b Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Mon, 30 Oct 2017 06:23:08 +0100 Subject: [PATCH 29/36] [Validator] ExpressionValidator should use OBJECT_TO_STRING to allow value in message --- .../Constraints/ExpressionValidator.php | 4 +-- .../Constraints/ExpressionValidatorTest.php | 34 +++++++++++++++++++ .../Validator/Tests/Fixtures/ToString.php | 22 ++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/ToString.php diff --git a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php index 360ec5a8d9e8d..96761f51f2c2a 100644 --- a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php @@ -78,11 +78,11 @@ public function validate($value, Constraint $constraint) if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->message) - ->setParameter('{{ value }}', $this->formatValue($value)) + ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING)) ->addViolation(); } else { $this->buildViolation($constraint->message) - ->setParameter('{{ value }}', $this->formatValue($value)) + ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING)) ->addViolation(); } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php index 3b6de4d412582..be15967dcbd88 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\ExpressionValidator; use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\ToString; use Symfony\Component\Validator\Validation; class ExpressionValidatorTest extends AbstractConstraintValidatorTest @@ -90,6 +91,39 @@ public function testFailingExpressionAtObjectLevel() ->assertRaised(); } + public function testSucceedingExpressionAtObjectLevelWithToString() + { + $constraint = new Expression('this.data == 1'); + + $object = new ToString(); + $object->data = '1'; + + $this->setObject($object); + + $this->validator->validate($object, $constraint); + + $this->assertNoViolation(); + } + + public function testFailingExpressionAtObjectLevelWithToString() + { + $constraint = new Expression(array( + 'expression' => 'this.data == 1', + 'message' => 'myMessage', + )); + + $object = new ToString(); + $object->data = '2'; + + $this->setObject($object); + + $this->validator->validate($object, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', 'toString') + ->assertRaised(); + } + public function testSucceedingExpressionAtPropertyLevel() { $constraint = new Expression('value == this.data'); diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/ToString.php b/src/Symfony/Component/Validator/Tests/Fixtures/ToString.php new file mode 100644 index 0000000000000..714fdb9e98f5f --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/ToString.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +class ToString +{ + public $data; + + public function __toString() + { + return 'toString'; + } +} From 3e7780cb908b34903f2ea82b5070c532a8e71c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 1 Dec 2017 20:16:54 +0100 Subject: [PATCH 30/36] [link] Prevent warnings when running link with 2.7 --- link | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/link b/link index f4070998e72b5..3bbc97f041a20 100755 --- a/link +++ b/link @@ -35,11 +35,14 @@ if (!is_dir("$argv[1]/vendor/symfony")) { } $sfPackages = array('symfony/symfony' => __DIR__); + +$filesystem = new Filesystem(); foreach (glob(__DIR__.'/src/Symfony/{Bundle,Bridge,Component,Component/Security}/*', GLOB_BRACE | GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { - $sfPackages[json_decode(file_get_contents("$dir/composer.json"))->name] = $dir; + if ($filesystem->exists($composer = "$dir/composer.json")) { + $sfPackages[json_decode(file_get_contents($composer))->name] = $dir; + } } -$filesystem = new Filesystem(); foreach (glob("$argv[1]/vendor/symfony/*", GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { $package = 'symfony/'.basename($dir); if (is_link($dir)) { From 05c3c81a200aabf7d16875d9019f3b89a929a247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 1 Dec 2017 20:12:52 +0100 Subject: [PATCH 31/36] [link] clear the cache after linking --- link | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/link b/link index f4070998e72b5..adba4a5a1ad7e 100755 --- a/link +++ b/link @@ -57,3 +57,7 @@ foreach (glob("$argv[1]/vendor/symfony/*", GLOB_ONLYDIR | GLOB_NOSORT) as $dir) $filesystem->symlink($sfDir, $dir); echo "\"$package\" has been linked to \"$sfPackages[$package]\".".PHP_EOL; } + +foreach (glob("$argv[1]/var/cache/*") as $cacheDir) { + $filesystem->remove($cacheDir); +} From 23b575819849f523d6c86c57dc08d8034b523583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 2 Dec 2017 16:57:48 +0100 Subject: [PATCH 32/36] [FrameworkBundle] Fix visibility of a test helper --- .../FrameworkBundle/Tests/Controller/RedirectControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php index 14b6e4428e550..c4d6d837c6a7a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php @@ -290,7 +290,7 @@ private function createRedirectController($httpPort = null, $httpsPort = null) return $controller; } - public function assertRedirectUrl(Response $returnResponse, $expectedUrl) + private function assertRedirectUrl(Response $returnResponse, $expectedUrl) { $this->assertTrue($returnResponse->isRedirect($expectedUrl), "Expected: $expectedUrl\nGot: ".$returnResponse->headers->get('Location')); } From 369075a282b0f29eeed511708651d2f9f6e67d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Wer=C5=82os?= Date: Mon, 4 Dec 2017 13:08:37 +0100 Subject: [PATCH 33/36] Fix for missing whitespace control modifier in form layout --- .../Twig/Resources/views/Form/form_div_layout.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index a27c81dd495ae..eb0f6d057dcea 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -301,7 +301,7 @@ {% if not child.rendered %} {{- form_row(child) -}} {% endif %} - {%- endfor %} + {%- endfor -%} {% if not form.methodRendered and form.parent is null %} {%- do form.setMethodRendered() -%} @@ -315,7 +315,7 @@ {%- if form_method != method -%} {%- endif -%} - {% endif %} + {% endif -%} {% endblock form_rest %} {# Support #} From 0f8ff1583abffdf3b4eab026ea6e6052b30c1f11 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 4 Dec 2017 10:21:12 -0800 Subject: [PATCH 34/36] marked method as being internal --- src/Symfony/Bridge/Twig/Extension/FormExtension.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index aaed8221c1fc8..e101704efaa9d 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -158,6 +158,9 @@ public function isSelectedChoice(ChoiceView $choice, $selectedValue) return $choice->value === $selectedValue; } + /** + * @internal + */ public function isRootForm(FormView $formView) { return null === $formView->parent; From 67eb592d0e664bc72706f351a1b5b1dddbc54b49 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 4 Dec 2017 14:02:09 -0800 Subject: [PATCH 35/36] updated CHANGELOG for 2.8.32 --- CHANGELOG-2.8.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 626c310af437f..2e8fc7e47079d 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,21 @@ in 2.8 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.8.0...v2.8.1 +* 2.8.32 (2017-12-04) + + * bug #25278 Fix for missing whitespace control modifier in form layout (kubawerlos) + * bug #25236 [Form][TwigBridge] Fix collision between view properties and form fields (yceruto) + * bug #25258 [link] Prevent warnings when running link with 2.7 (dunglas) + * bug #24750 [Validator] ExpressionValidator should use OBJECT_TO_STRING (Simperfit) + * bug #25182 [HttpFoundation] AutExpireFlashBag should not clear new flashes (Simperfit, sroze) + * bug #25152 [Form] Don't rely on `Symfony\Component\HttpFoundation\File\File` if http-foundation isn't in FileType (issei-m) + * bug #24987 [Console] Fix global console flag when used in chain (Simperfit) + * bug #25043 [Yaml] added ability for substitute aliases when mapping is on single line (Michał Strzelecki, xabbuh) + * bug #25102 [Form] Fixed ContextErrorException in FileType (chihiro-adachi) + * bug #25130 [DI] Fix handling of inlined definitions by ContainerBuilder (nicolas-grekas) + * bug #25072 [Bridge/PhpUnit] Remove trailing "\n" from ClockMock::microtime(false) (joky) + * bug #24956 Fix ambiguous pattern (weltling) + * 2.8.31 (2017-11-16) * security #24995 Validate redirect targets using the session cookie domain (nicolas-grekas) From 525b5ff9765acd73fe01fb2558b64cc31c57e313 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 4 Dec 2017 14:02:14 -0800 Subject: [PATCH 36/36] updated VERSION for 2.8.32 --- 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 0bfec287a98b3..6ec30910cba15 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.32-DEV'; + const VERSION = '2.8.32'; const VERSION_ID = 20832; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 32; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019';