From b9162e8cfb625a152ff46ecbdacdb3160f30dd80 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Tue, 12 Mar 2019 12:31:54 +0100 Subject: [PATCH 01/17] [Form] Fixed some phpdocs --- .../Form/ChoiceList/ArrayChoiceList.php | 16 +++++------- .../Form/ChoiceList/ChoiceListInterface.php | 26 ++++++++++++++++++- .../Factory/ChoiceListFactoryInterface.php | 8 +++--- .../Loader/ChoiceLoaderInterface.php | 12 ++++----- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index 02685a2504..e7ebc7200b 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -15,9 +15,10 @@ namespace Symfony\Component\Form\ChoiceList; * A list of choices with arbitrary data types. * * The user of this class is responsible for assigning string values to the - * choices. Both the choices and their values are passed to the constructor. - * Each choice must have a corresponding value (with the same array key) in - * the value array. + * choices annd for their uniqueness. + * Both the choices and their values are passed to the constructor. + * Each choice must have a corresponding value (with the same key) in + * the values array. * * @author Bernhard Schussek */ @@ -43,12 +44,6 @@ class ArrayChoiceList implements ChoiceListInterface * @var int[]|string[] */ protected $originalKeys; - - /** - * The callback for creating the value for a choice. - * - * @var callable - */ protected $valueCallback; /** @@ -212,6 +207,8 @@ class ArrayChoiceList implements ChoiceListInterface /** * Checks whether the given choices can be cast to strings without * generating duplicates. + * This method is responsible for preventing conflict between scalar values + * and the empty value. * * @param array $choices The choices * @param array|null $cache The cache for previously checked entries. Internal @@ -232,6 +229,7 @@ class ArrayChoiceList implements ChoiceListInterface return false; } + // prevent having false casted to the empty string by isset() $choice = false === $choice ? '0' : (string) $choice; if (isset($cache[$choice])) { diff --git a/src/Symfony/Component/Form/ChoiceList/ChoiceListInterface.php b/src/Symfony/Component/Form/ChoiceList/ChoiceListInterface.php index c1d643ee73..9435309dd5 100644 --- a/src/Symfony/Component/Form/ChoiceList/ChoiceListInterface.php +++ b/src/Symfony/Component/Form/ChoiceList/ChoiceListInterface.php @@ -35,7 +35,25 @@ interface ChoiceListInterface /** * Returns the values for the choices. * - * The values are strings that do not contain duplicates. + * The values are strings that do not contain duplicates: + * + * $form->add('field', 'choice', [ + * 'choices' => [ + * 'Decided' => ['Yes' => true, 'No' => false], + * 'Undecided' => ['Maybe' => null], + * ], + * ]); + * + * In this example, the result of this method is: + * + * [ + * 'Yes' => '0', + * 'No' => '1', + * 'Maybe' => '2', + * ] + * + * Null and false MUST NOT conflict when being casted to string. + * For this some default incremented values SHOULD be computed. * * @return string[] The choice values */ @@ -62,6 +80,12 @@ interface ChoiceListInterface * 'Undecided' => ['Maybe' => '2'], * ] * + * Nested arrays do not make sense in a view format unless + * they are used as a convenient way of grouping. + * If the implementation does not intend to support grouped choices, + * this method SHOULD be equivalent to {@link getValues()}. + * The $groupBy callback parameter SHOULD be used instead. + * * @return string[] The choice values */ public function getStructuredValues(); diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php index dea2165ec7..41a22586cc 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php @@ -28,8 +28,8 @@ interface ChoiceListFactoryInterface * The choices should be passed in the values of the choices array. * * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. + * The callable receives the choice as only argument. + * Null may be passed when the choice list contains the empty value. * * @param iterable $choices The choices * @param callable|null $value The callable generating the choice @@ -43,8 +43,8 @@ interface ChoiceListFactoryInterface * Creates a choice list that is loaded with the given loader. * * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. + * The callable receives the choice as only argument. + * Null may be passed when the choice list contains the empty value. * * @param ChoiceLoaderInterface $loader The choice loader * @param callable|null $value The callable generating the choice diff --git a/src/Symfony/Component/Form/ChoiceList/Loader/ChoiceLoaderInterface.php b/src/Symfony/Component/Form/ChoiceList/Loader/ChoiceLoaderInterface.php index 63e5f65210..31d47d539c 100644 --- a/src/Symfony/Component/Form/ChoiceList/Loader/ChoiceLoaderInterface.php +++ b/src/Symfony/Component/Form/ChoiceList/Loader/ChoiceLoaderInterface.php @@ -28,8 +28,8 @@ interface ChoiceLoaderInterface * Loads a list of choices. * * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. + * The callable receives the choice as only argument. + * Null may be passed when the choice list contains the empty value. * * @param callable|null $value The callable which generates the values * from choices @@ -45,8 +45,8 @@ interface ChoiceLoaderInterface * corresponding values in the given array. * * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. + * The callable receives the choice as only argument. + * Null may be passed when the choice list contains the empty value. * * @param string[] $values An array of choice values. Non-existing * values in this array are ignored @@ -63,8 +63,8 @@ interface ChoiceLoaderInterface * corresponding choices in the given array. * * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. + * The callable receives the choice as only argument. + * Null may be passed when the choice list contains the empty value. * * @param array $choices An array of choices. Non-existing choices in * this array are ignored From f647b4a29d87a0c140a6f4c98c2650f8b0322007 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Mon, 4 Mar 2019 07:20:52 -0500 Subject: [PATCH 02/17] Fix DebugCommand when chain loader is involved --- .../Bridge/Twig/Command/DebugCommand.php | 94 ++++++++++++------- .../Twig/Tests/Command/DebugCommandTest.php | 16 +++- src/Symfony/Bridge/Twig/composer.json | 2 +- 3 files changed, 77 insertions(+), 35 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 5ff57e1cf4..5c22291ff0 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Finder\Finder; use Twig\Environment; +use Twig\Loader\ChainLoader; use Twig\Loader\FilesystemLoader; /** @@ -36,6 +37,7 @@ class DebugCommand extends Command private $bundlesMetadata; private $twigDefaultPath; private $rootDir; + private $filesystemLoaders; public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, string $rootDir = null) { @@ -87,7 +89,7 @@ EOF $name = $input->getArgument('name'); $filter = $input->getOption('filter'); - if (null !== $name && !$this->twig->getLoader() instanceof FilesystemLoader) { + if (null !== $name && [] === $this->getFilesystemLoaders()) { throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s"', FilesystemLoader::class)); } @@ -150,9 +152,11 @@ EOF $message = 'No template paths configured for your application'; } else { $message = sprintf('No template paths configured for "@%s" namespace', $namespace); - $namespaces = $this->twig->getLoader()->getNamespaces(); - foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) { - $alternatives[] = '@'.$namespace; + foreach ($this->getFilesystemLoaders() as $loader) { + $namespaces = $loader->getNamespaces(); + foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) { + $alternatives[] = '@'.$namespace; + } } } @@ -243,25 +247,25 @@ EOF private function getLoaderPaths(string $name = null): array { - /** @var FilesystemLoader $loader */ - $loader = $this->twig->getLoader(); $loaderPaths = []; - $namespaces = $loader->getNamespaces(); - if (null !== $name) { - $namespace = $this->parseTemplateName($name)[0]; - $namespaces = array_intersect([$namespace], $namespaces); - } - - foreach ($namespaces as $namespace) { - $paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace)); - - if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { - $namespace = '(None)'; - } else { - $namespace = '@'.$namespace; + foreach ($this->getFilesystemLoaders() as $loader) { + $namespaces = $loader->getNamespaces(); + if (null !== $name) { + $namespace = $this->parseTemplateName($name)[0]; + $namespaces = array_intersect([$namespace], $namespaces); } - $loaderPaths[$namespace] = $paths; + foreach ($namespaces as $namespace) { + $paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace)); + + if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { + $namespace = '(None)'; + } else { + $namespace = '@'.$namespace; + } + + $loaderPaths[$namespace] = $paths; + } } return $loaderPaths; @@ -437,22 +441,22 @@ EOF private function findTemplateFiles(string $name): array { - /** @var FilesystemLoader $loader */ - $loader = $this->twig->getLoader(); - $files = []; list($namespace, $shortname) = $this->parseTemplateName($name); - foreach ($loader->getPaths($namespace) as $path) { - if (!$this->isAbsolutePath($path)) { - $path = $this->projectDir.'/'.$path; - } - $filename = $path.'/'.$shortname; + $files = []; + foreach ($this->getFilesystemLoaders() as $loader) { + foreach ($loader->getPaths($namespace) as $path) { + if (!$this->isAbsolutePath($path)) { + $path = $this->projectDir.'/'.$path; + } + $filename = $path.'/'.$shortname; - if (is_file($filename)) { - if (false !== $realpath = realpath($filename)) { - $files[] = $this->getRelativePath($realpath); - } else { - $files[] = $this->getRelativePath($filename); + if (is_file($filename)) { + if (false !== $realpath = realpath($filename)) { + $files[] = $this->getRelativePath($realpath); + } else { + $files[] = $this->getRelativePath($filename); + } } } } @@ -535,4 +539,28 @@ EOF { return strspn($file, '/\\', 0, 1) || (\strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1)) || null !== parse_url($file, PHP_URL_SCHEME); } + + /** + * @return FilesystemLoader[] + */ + private function getFilesystemLoaders(): array + { + if (null !== $this->filesystemLoaders) { + return $this->filesystemLoaders; + } + $this->filesystemLoaders = []; + + $loader = $this->twig->getLoader(); + if ($loader instanceof FilesystemLoader) { + $this->filesystemLoaders[] = $loader; + } elseif ($loader instanceof ChainLoader) { + foreach ($loader->getLoaders() as $l) { + if ($l instanceof FilesystemLoader) { + $this->filesystemLoaders[] = $l; + } + } + } + + return $this->filesystemLoaders; + } } diff --git a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php index 59c8ed045c..76eb10884b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php @@ -16,6 +16,7 @@ use Symfony\Bridge\Twig\Command\DebugCommand; use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Twig\Environment; +use Twig\Loader\ChainLoader; use Twig\Loader\FilesystemLoader; class DebugCommandTest extends TestCase @@ -279,7 +280,16 @@ TXT ]; } - private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null): CommandTester + public function testDebugTemplateNameWithChainLoader() + { + $tester = $this->createCommandTester(['templates/' => null], [], null, null, true); + $ret = $tester->execute(['name' => 'base.html.twig'], ['decorated' => false]); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('[OK]', $tester->getDisplay()); + } + + private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null, bool $useChainLoader = false): CommandTester { $projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'; $loader = new FilesystemLoader([], $projectDir); @@ -291,6 +301,10 @@ TXT } } + if ($useChainLoader) { + $loader = new ChainLoader([$loader]); + } + $application = new Application(); $application->add(new DebugCommand(new Environment($loader), $projectDir, $bundleMetadata, $defaultPath, $rootDir)); $command = $application->find('debug:twig'); diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 24034230f8..9405dc2c9c 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1.3", "symfony/contracts": "^1.0.2", - "twig/twig": "^1.37.1|^2.6.2" + "twig/twig": "^1.38.1|^2.7.1" }, "require-dev": { "symfony/asset": "~3.4|~4.0", From 426b92f4a8d21107015ceec15a087fad72af027a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 16 Mar 2019 10:05:46 +0100 Subject: [PATCH 03/17] [Intl] Add compile binary --- src/Symfony/Component/Intl/Resources/bin/compile | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 src/Symfony/Component/Intl/Resources/bin/compile diff --git a/src/Symfony/Component/Intl/Resources/bin/compile b/src/Symfony/Component/Intl/Resources/bin/compile new file mode 100755 index 0000000000..8e73d641d5 --- /dev/null +++ b/src/Symfony/Component/Intl/Resources/bin/compile @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +if [[ $1 == force || ! $(docker ps -a | grep symfony-intl) ]]; then + docker rm -f symfony-intl + docker create --name symfony-intl -it -v /tmp:/tmp -v $(pwd):/app -w /app jakzal/php-intl:7.2-63.1 bash + docker start symfony-intl + docker exec symfony-intl bash -xc "apt-get update && apt-get -y install build-essential" +else + docker start symfony-intl +fi; + +docker exec -u $(id -u):$(id -g) symfony-intl php src/Symfony/Component/Intl/Resources/bin/update-data.php From 5df08d67a78048c950255061547781c99a357a04 Mon Sep 17 00:00:00 2001 From: Mehdi Mabrouk Date: Sun, 17 Mar 2019 01:11:46 +0100 Subject: [PATCH 04/17] [Validator] Add the missing translations for the Arabic (ar) locale --- .../Validator/Resources/translations/validators.ar.xlf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index eacd8d777d..12f26fdc88 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -330,6 +330,10 @@ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. رمز المعرّف نشاط تجاري (BIC) هذا لا يرتبط مع IBAN {{ iban }}. + + This value should be valid JSON. + هذه القيمة يجب أن تكون صالحة ل JSON. + From 226f522c4db551eb963dd9dff9a37769005b9db9 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Mar 2019 10:26:14 +0100 Subject: [PATCH 05/17] [Intl] Fix test --- src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php b/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php index c727e500bb..a47495f6a5 100644 --- a/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php +++ b/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php @@ -45,7 +45,7 @@ class GitRepositoryTest extends TestCase $this->setExpectedException(RuntimeException::class); } - @mkdir($this->targetDir, '0777', true); + @mkdir($this->targetDir, 0777, true); new GitRepository($this->targetDir); } From 50b52cffddd7a549253dff9d3981f3c32e3e1e78 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Mar 2019 10:32:54 +0100 Subject: [PATCH 06/17] [Intl][4.2] Fix test --- src/Symfony/Component/Intl/Resources/data/languages/ia.json | 3 --- src/Symfony/Component/Intl/Resources/data/languages/jv.json | 1 - src/Symfony/Component/Intl/Resources/data/languages/mi.json | 1 - src/Symfony/Component/Intl/Resources/data/languages/sd.json | 3 --- src/Symfony/Component/Intl/Resources/data/languages/so.json | 1 - src/Symfony/Component/Intl/Resources/data/languages/tk.json | 3 --- .../Tests/Data/Provider/AbstractLanguageDataProviderTest.php | 3 --- 7 files changed, 15 deletions(-) diff --git a/src/Symfony/Component/Intl/Resources/data/languages/ia.json b/src/Symfony/Component/Intl/Resources/data/languages/ia.json index 378b7d7f3f..364e852dec 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/ia.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/ia.json @@ -233,7 +233,6 @@ "ms": "malay", "mt": "maltese", "mua": "mundang", - "mul": "plure linguas", "mus": "creek", "mwl": "mirandese", "my": "birmano", @@ -361,7 +360,6 @@ "ug": "uighur", "uk": "ukrainiano", "umb": "umbundu", - "und": "lingua incognite", "ur": "urdu", "uz": "uzbeko", "vai": "vai", @@ -388,7 +386,6 @@ "zh_Hant": "chinese traditional", "zu": "zulu", "zun": "zuni", - "zxx": "sin contento linguistic", "zza": "zaza" } } diff --git a/src/Symfony/Component/Intl/Resources/data/languages/jv.json b/src/Symfony/Component/Intl/Resources/data/languages/jv.json index 925cd20f82..9218488236 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/jv.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/jv.json @@ -29,7 +29,6 @@ "ru": "Rusia", "th": "Thailand", "tr": "Turki", - "und": "Basa Ora Dikenali", "zh": "Tyonghwa", "zh_Hant": "Tyonghwa (Tradisional)" } diff --git a/src/Symfony/Component/Intl/Resources/data/languages/mi.json b/src/Symfony/Component/Intl/Resources/data/languages/mi.json index b31f977435..7a4424d0c1 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/mi.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/mi.json @@ -23,7 +23,6 @@ "pt_BR": "Pōtikī Parahi", "pt_PT": "Pōtikī Uropi", "ru": "Ruhiana", - "und": "Reo Tē Mōhiotia", "zh": "Hainamana", "zh_Hans": "Hainamana Māmā", "zh_Hant": "Hainamana Tukuiho" diff --git a/src/Symfony/Component/Intl/Resources/data/languages/sd.json b/src/Symfony/Component/Intl/Resources/data/languages/sd.json index 30672ca3be..70b0472a09 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/sd.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/sd.json @@ -232,7 +232,6 @@ "ms": "ملي", "mt": "مالٽي", "mua": "من دانگ", - "mul": "هڪ کان وڌيڪ ٻوليون", "mus": "ڪريڪ", "mwl": "مرانڊيز", "my": "برمي", @@ -360,7 +359,6 @@ "ug": "يوغور", "uk": "يوڪراني", "umb": "اومبنڊو", - "und": "اڻڄاتل ٻولي", "ur": "اردو", "uz": "ازبڪ", "vai": "يا", @@ -387,7 +385,6 @@ "zh_Hant": "روايتي چيني", "zu": "زولو", "zun": "زوني", - "zxx": "ڪوئي ٻولي جو مواد ڪونهي", "zza": "زازا" } } diff --git a/src/Symfony/Component/Intl/Resources/data/languages/so.json b/src/Symfony/Component/Intl/Resources/data/languages/so.json index 24b04da98d..ca7f50ab6a 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/so.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/so.json @@ -53,7 +53,6 @@ "th": "Taaylandays", "tr": "Turkish", "uk": "Yukreeniyaan", - "und": "Af aan la aqoon ama aan sax ahayn", "ur": "Urduu", "vi": "Fiitnaamays", "yo": "Yoruuba", diff --git a/src/Symfony/Component/Intl/Resources/data/languages/tk.json b/src/Symfony/Component/Intl/Resources/data/languages/tk.json index baafd1212f..f985d28bd4 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/tk.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/tk.json @@ -226,7 +226,6 @@ "ms": "malaý dili", "mt": "malta dili", "mua": "mundang dili", - "mul": "birnäçe dil", "mus": "krik dili", "mwl": "mirand dili", "my": "birma dili", @@ -353,7 +352,6 @@ "ug": "uýgur dili", "uk": "ukrain dili", "umb": "umbundu dili", - "und": "näbelli dil", "ur": "urdu", "uz": "özbek dili", "vai": "wai dili", @@ -380,7 +378,6 @@ "zh_Hant": "adaty hytaý dili", "zu": "zulu dili", "zun": "zuni dili", - "zxx": "dilçilige degişli mazmun ýok", "zza": "zazaki dili" } } diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php index 003e688d03..310fe79160 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractLanguageDataProviderTest.php @@ -392,7 +392,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest 'ms', 'mt', 'mua', - 'mul', 'mus', 'mwl', 'mwr', @@ -596,7 +595,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest 'uga', 'uk', 'umb', - 'und', 'ur', 'uz', 'vai', @@ -641,7 +639,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest 'zh_Hant', 'zu', 'zun', - 'zxx', 'zza', ]; From d8092c7b7bf46776e731961246161e864c7ed38f Mon Sep 17 00:00:00 2001 From: Matthias Althaus Date: Mon, 18 Mar 2019 11:21:32 +0100 Subject: [PATCH 07/17] Fixed usage of TranslatorInterface in form extension (fixes #30591) --- .../Component/Form/Extension/Core/CoreExtension.php | 11 +++++++++-- .../EventListener/TransformationFailureListener.php | 11 +++++++++-- .../Core/Type/TransformationFailureExtension.php | 11 +++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php index 4eb980bf9c..e578058e5c 100644 --- a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php +++ b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php @@ -19,7 +19,8 @@ use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator; use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Represents the main form extension, which loads the core functionality. @@ -32,8 +33,14 @@ class CoreExtension extends AbstractExtension private $choiceListFactory; private $translator; - public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, TranslatorInterface $translator = null) + /** + * @param TranslatorInterface|null $translator + */ + public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, $translator = null) { + if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 3 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->choiceListFactory = $choiceListFactory ?: new CachingFactoryDecorator(new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor)); $this->translator = $translator; diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/TransformationFailureListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/TransformationFailureListener.php index 835a028315..f5e73849b3 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/TransformationFailureListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/TransformationFailureListener.php @@ -15,7 +15,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @author Christian Flothmann @@ -24,8 +25,14 @@ class TransformationFailureListener implements EventSubscriberInterface { private $translator; - public function __construct(TranslatorInterface $translator = null) + /** + * @param TranslatorInterface|null $translator + */ + public function __construct($translator = null) { + if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } $this->translator = $translator; } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TransformationFailureExtension.php b/src/Symfony/Component/Form/Extension/Core/Type/TransformationFailureExtension.php index 8712fff99b..8cdca71b65 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TransformationFailureExtension.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TransformationFailureExtension.php @@ -14,7 +14,8 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\Core\EventListener\TransformationFailureListener; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @author Christian Flothmann @@ -23,8 +24,14 @@ class TransformationFailureExtension extends AbstractTypeExtension { private $translator; - public function __construct(TranslatorInterface $translator = null) + /** + * @param TranslatorInterface|null $translator + */ + public function __construct($translator = null) { + if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } $this->translator = $translator; } From 3f7bedc61f158aedc47ea451029f43ddd34130df Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Mon, 18 Mar 2019 22:39:03 +0100 Subject: [PATCH 08/17] [Tests] fixed compatbility of assertEquals(): void --- ...imeToHtml5LocalDateTimeTransformerTest.php | 13 ++------ ...teTimeToLocalizedStringTransformerTest.php | 33 ++++++++----------- .../DateTimeToRfc3339TransformerTest.php | 15 +++------ .../Traits/DateTimeEqualsTrait.php | 28 ++++++++++++++++ 4 files changed, 48 insertions(+), 41 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/Traits/DateTimeEqualsTrait.php diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php index e66331aa28..6388bf2a8d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php @@ -13,18 +13,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer; +use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait; class DateTimeToHtml5LocalDateTimeTransformerTest extends TestCase { - public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) - { - if ($expected instanceof \DateTime && $actual instanceof \DateTime) { - $expected = $expected->format('c'); - $actual = $actual->format('c'); - } - - parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); - } + use DateTimeEqualsTrait; public function transformProvider() { @@ -96,7 +89,7 @@ class DateTimeToHtml5LocalDateTimeTransformerTest extends TestCase $transformer = new DateTimeToHtml5LocalDateTimeTransformer($toTz, $fromTz); if (null !== $to) { - $this->assertEquals(new \DateTime($to), $transformer->reverseTransform($from)); + $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from)); } else { $this->assertNull($transformer->reverseTransform($from)); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index 8cf5986c13..d2feb116bf 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -13,10 +13,13 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; +use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeToLocalizedStringTransformerTest extends TestCase { + use DateTimeEqualsTrait; + protected $dateTime; protected $dateTimeWithoutSeconds; @@ -39,16 +42,6 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $this->dateTimeWithoutSeconds = null; } - public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) - { - if ($expected instanceof \DateTime && $actual instanceof \DateTime) { - $expected = $expected->format('c'); - $actual = $actual->format('c'); - } - - parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); - } - public function dataProvider() { return [ @@ -152,7 +145,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $dateTime = new \DateTime('2010-02-03 04:05'); - $this->assertEquals( + $this->assertDateTimeEquals( $dateTime->format('c'), $transformer->reverseTransform('03.02.2010, 04:05')->format('c') ); @@ -217,14 +210,14 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $output = new \DateTime($output); - $this->assertEquals($output, $transformer->reverseTransform($input)); + $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformFullTime() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); - $this->assertEquals($this->dateTime, $transformer->reverseTransform('03.02.2010, 04:05:06 GMT+00:00')); + $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010, 04:05:06 GMT+00:00')); } public function testReverseTransformFromDifferentLocale() @@ -233,7 +226,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); - $this->assertEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); + $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); } public function testReverseTransformWithDifferentTimezones() @@ -243,7 +236,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); - $this->assertEquals($dateTime, $transformer->reverseTransform('03.02.2010, 04:05')); + $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010, 04:05')); } public function testReverseTransformOnlyDateWithDifferentTimezones() @@ -252,21 +245,21 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase $dateTime = new \DateTime('2017-01-10 11:00', new \DateTimeZone('Europe/Berlin')); - $this->assertEquals($dateTime, $transformer->reverseTransform('2017-01-10')); + $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2017-01-10')); } public function testReverseTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); - $this->assertEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06')); + $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06')); } public function testReverseTransformDateOnlyWithDstIssue() { $transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'dd/MM/yyyy'); - $this->assertEquals( + $this->assertDateTimeEquals( new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')), $transformer->reverseTransform('28/05/1978') ); @@ -276,7 +269,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase { $transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, "'day': dd 'month': MM 'year': yyyy"); - $this->assertEquals( + $this->assertDateTimeEquals( new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')), $transformer->reverseTransform('day: 28 month: 05 year: 1978') ); @@ -330,7 +323,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT); - $this->assertEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); + $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); } /** 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 2352ea6cc3..773f00d713 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -13,9 +13,12 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; +use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait; class DateTimeToRfc3339TransformerTest extends TestCase { + use DateTimeEqualsTrait; + protected $dateTime; protected $dateTimeWithoutSeconds; @@ -33,16 +36,6 @@ class DateTimeToRfc3339TransformerTest extends TestCase $this->dateTimeWithoutSeconds = null; } - public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) - { - if ($expected instanceof \DateTime && $actual instanceof \DateTime) { - $expected = $expected->format('c'); - $actual = $actual->format('c'); - } - - parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); - } - public function allProvider() { return [ @@ -108,7 +101,7 @@ class DateTimeToRfc3339TransformerTest extends TestCase $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz); if (null !== $to) { - $this->assertEquals(new \DateTime($to), $transformer->reverseTransform($from)); + $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from)); } else { $this->assertNull($transformer->reverseTransform($from)); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/Traits/DateTimeEqualsTrait.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/Traits/DateTimeEqualsTrait.php new file mode 100644 index 0000000000..738c4d96b0 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/Traits/DateTimeEqualsTrait.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits; + +/** + * @internal + */ +trait DateTimeEqualsTrait +{ + public static function assertDateTimeEquals($expected, $actual) + { + if ($expected instanceof \DateTime && $actual instanceof \DateTime) { + $expected = $expected->format('c'); + $actual = $actual->format('c'); + } + + parent::assertEquals($expected, $actual); + } +} From eeb3c29fab8f7f18d198cbcfbee1ff63f6a9a3ca Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Tue, 19 Mar 2019 10:13:19 +0100 Subject: [PATCH 09/17] Remove deprecated usage null is also deprecated but must be conserved for BC purpose. Also it will will not let the develop think string is ok. --- src/Symfony/Component/Workflow/Event/GuardEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Event/GuardEvent.php b/src/Symfony/Component/Workflow/Event/GuardEvent.php index a940743f48..9a7d644964 100644 --- a/src/Symfony/Component/Workflow/Event/GuardEvent.php +++ b/src/Symfony/Component/Workflow/Event/GuardEvent.php @@ -27,7 +27,7 @@ class GuardEvent extends Event /** * {@inheritdoc} */ - public function __construct($subject, Marking $marking, Transition $transition, $workflowName = 'unnamed') + public function __construct($subject, Marking $marking, Transition $transition, $workflowName = null) { parent::__construct($subject, $marking, $transition, $workflowName); From 4ddf5a14eb6fcc4a190fced52946c7406f809a01 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Mon, 18 Mar 2019 22:46:17 +0100 Subject: [PATCH 10/17] [Form] Added ResetInterface to CachingFactoryDecorator --- .../DependencyInjection/FrameworkExtension.php | 6 ++++++ .../Bundle/FrameworkBundle/Resources/config/form.xml | 1 + .../Form/ChoiceList/Factory/CachingFactoryDecorator.php | 9 ++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b786923b8e..b390f29781 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -53,6 +53,7 @@ use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Finder\Finder; +use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; use Symfony\Component\Form\FormTypeExtensionInterface; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\FormTypeInterface; @@ -410,6 +411,11 @@ class FrameworkExtension extends Extension if (!class_exists(Translator::class)) { $container->removeDefinition('form.type_extension.upload.validator'); } + if (!method_exists(CachingFactoryDecorator::class, 'reset')) { + $container->getDefinition('form.choice_list_factory.cached') + ->clearTag('kernel.reset') + ; + } } private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index a375e527ce..4ca196e47d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -57,6 +57,7 @@ + diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php index 477afbbb07..65d17afbdf 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php @@ -14,13 +14,14 @@ namespace Symfony\Component\Form\ChoiceList\Factory; use Symfony\Component\Form\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\View\ChoiceListView; +use Symfony\Contracts\Service\ResetInterface; /** * Caches the choice lists created by the decorated factory. * * @author Bernhard Schussek */ -class CachingFactoryDecorator implements ChoiceListFactoryInterface +class CachingFactoryDecorator implements ChoiceListFactoryInterface, ResetInterface { private $decoratedFactory; @@ -134,4 +135,10 @@ class CachingFactoryDecorator implements ChoiceListFactoryInterface return $this->views[$hash]; } + + public function reset() + { + $this->lists = []; + $this->views = []; + } } From f45f0d03fc4adf347c487519b436c76bde95f8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0t=C3=ADpek?= Date: Mon, 18 Mar 2019 21:30:37 +0100 Subject: [PATCH 11/17] [Form] Preventing validation of children if parent with Valid constraint has no validation groups --- .../Validator/Constraints/FormValidator.php | 5 +++++ .../Constraints/FormValidatorTest.php | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 7922bcc74c..14adf123ec 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -44,6 +44,11 @@ class FormValidator extends ConstraintValidator if ($form->isSubmitted() && $form->isSynchronized()) { // Validate the form data only if transformation succeeded $groups = self::getValidationGroups($form); + + if (!$groups) { + return; + } + $data = $form->getData(); // Validate the data against its own constraints diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 7581f7698c..4ab56f555a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -220,6 +220,28 @@ class FormValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + public function testDontValidateChildConstraintsIfCallableNoValidationGroups() + { + $formOptions = [ + 'constraints' => [new Valid()], + 'validation_groups' => [], + ]; + $form = $this->getBuilder('name', null, $formOptions) + ->setCompound(true) + ->setDataMapper(new PropertyPathMapper()) + ->getForm(); + $childOptions = ['constraints' => [new NotBlank()]]; + $child = $this->getCompoundForm(new \stdClass(), $childOptions); + $form->add($child); + $form->submit([]); + + $this->expectNoValidate(); + + $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); + } + public function testDontValidateIfNotSynchronized() { $object = new \stdClass(); From f18751bd98604c9d271e8bc67302f91bc3fbe31d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 19 Mar 2019 22:04:09 +0100 Subject: [PATCH 12/17] throw TypeErrors to prepare for type hints in 5.0 --- src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php | 2 +- src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php | 2 +- .../Security/Core/Authorization/Voter/ExpressionVoter.php | 2 +- src/Symfony/Component/Workflow/Event/Event.php | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index b3d17e3db0..49d10a486b 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -42,7 +42,7 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE @trigger_error(sprintf('Injecting an instance of "%s" in "%s" is deprecated since Symfony 4.2, inject an instance of "%s" instead.', ClassMetadataFactory::class, __CLASS__, EntityManagerInterface::class), E_USER_DEPRECATED); $this->classMetadataFactory = $entityManager; } else { - throw new \InvalidArgumentException(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager))); + throw new \TypeError(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager))); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php index a83cf69b8b..d811faac4b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php @@ -41,7 +41,7 @@ class FirewallContext $this->logoutListener = $logoutListener; $this->config = $config; } else { - throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.', __METHOD__, LogoutListener::class, \is_object($logoutListener) ? \get_class($logoutListener) : \gettype($logoutListener))); + throw new \TypeError(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.', __METHOD__, LogoutListener::class, \is_object($logoutListener) ? \get_class($logoutListener) : \gettype($logoutListener))); } } diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php index d9530e071c..5fa0419674 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php @@ -44,7 +44,7 @@ class ExpressionVoter implements VoterInterface } elseif (null === $authChecker) { @trigger_error(sprintf('Argument 3 passed to "%s()" should be an instance of AuthorizationCheckerInterface, not passing it is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); } elseif (!$authChecker instanceof AuthorizationCheckerInterface) { - throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be an instance of %s or null, %s given.', __METHOD__, AuthorizationCheckerInterface::class, \is_object($authChecker) ? \get_class($authChecker) : \gettype($authChecker))); + throw new \TypeError(sprintf('Argument 3 passed to %s() must be an instance of %s or null, %s given.', __METHOD__, AuthorizationCheckerInterface::class, \is_object($authChecker) ? \get_class($authChecker) : \gettype($authChecker))); } $this->expressionLanguage = $expressionLanguage; diff --git a/src/Symfony/Component/Workflow/Event/Event.php b/src/Symfony/Component/Workflow/Event/Event.php index 395f2fd97b..cade7b363e 100644 --- a/src/Symfony/Component/Workflow/Event/Event.php +++ b/src/Symfony/Component/Workflow/Event/Event.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Workflow\Event; use Symfony\Component\EventDispatcher\Event as BaseEvent; -use Symfony\Component\Workflow\Exception\InvalidArgumentException; use Symfony\Component\Workflow\Marking; use Symfony\Component\Workflow\Transition; use Symfony\Component\Workflow\WorkflowInterface; @@ -49,7 +48,7 @@ class Event extends BaseEvent } elseif ($workflow instanceof WorkflowInterface) { $this->workflow = $workflow; } else { - throw new InvalidArgumentException(sprintf('The 4th parameter of "%s" should be a "%s" instance instead.', __METHOD__, WorkflowInterface::class)); + throw new \TypeError(sprintf('The 4th parameter of "%s" should be a "%s" instance instead.', __METHOD__, WorkflowInterface::class)); } } From b429950af6481a8683ab96d273992fc6d3c39df7 Mon Sep 17 00:00:00 2001 From: Serkan Yildiz Date: Thu, 7 Mar 2019 16:18:06 +0100 Subject: [PATCH 13/17] Check if Client exists when test.client does not exist, to provide clearer exception message --- src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php index e56e938dd9..74d99194ad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php @@ -36,7 +36,10 @@ abstract class WebTestCase extends KernelTestCase try { $client = $kernel->getContainer()->get('test.client'); } catch (ServiceNotFoundException $e) { - throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit".'); + if (class_exists(Client::class)) { + throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.'); + } + throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit"'); } $client->setServerParameters($server); From 393d7280e5b8e7c12737d07db2e5678c05f40f27 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 20 Mar 2019 11:45:54 -0400 Subject: [PATCH 14/17] Fix case when multiple loaders are providing paths for the same namespace --- src/Symfony/Bridge/Twig/Command/DebugCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 5c22291ff0..0c1e462fcf 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -264,7 +264,7 @@ EOF $namespace = '@'.$namespace; } - $loaderPaths[$namespace] = $paths; + $loaderPaths[$namespace] = array_merge($loaderPaths[$namespace] ?? [], $paths); } } From e78a13f7174fc17b8bfc464e19c8c1e33c06e05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 20 Mar 2019 20:20:03 +0100 Subject: [PATCH 15/17] [Workflow] Added missing license header --- src/Symfony/Component/Workflow/StateMachine.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Component/Workflow/StateMachine.php b/src/Symfony/Component/Workflow/StateMachine.php index 00cfdac7d4..bd8853ac66 100644 --- a/src/Symfony/Component/Workflow/StateMachine.php +++ b/src/Symfony/Component/Workflow/StateMachine.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Workflow; use Symfony\Component\EventDispatcher\EventDispatcherInterface; From e89c9213e2b4be2f2ae02e7a8609663b416facf2 Mon Sep 17 00:00:00 2001 From: ScoobyDam Date: Thu, 21 Mar 2019 19:51:37 +0100 Subject: [PATCH 16/17] Response prepare method update Response prepare updated for more coherence. --- src/Symfony/Component/HttpFoundation/Response.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 4d63219b2d..b7d116259d 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -310,9 +310,9 @@ class Response } // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) { - $this->headers->set('pragma', 'no-cache'); - $this->headers->set('expires', -1); + if ('1.0' == $this->getProtocolVersion() && false !== strpos($headers->get('Cache-Control'), 'no-cache')) { + $headers->set('pragma', 'no-cache'); + $headers->set('expires', -1); } $this->ensureIEOverSSLCompatibility($request); From 606b8af8ec0bac4c9ce7c60038b1cace09bb7361 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 22 Mar 2019 09:11:54 +0100 Subject: [PATCH 17/17] [Phpunit] fixed support for PHP 5.3 --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 5d203730c4..c81dcd26be 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -44,11 +44,11 @@ if ('phpdbg' === PHP_SAPI) { $PHP .= ' -qrr'; } -$defaultEnvs = [ +$defaultEnvs = array( 'COMPOSER' => 'composer.json', 'COMPOSER_VENDOR_DIR' => 'vendor', 'COMPOSER_BIN_DIR' => 'bin', -]; +); foreach ($defaultEnvs as $envName => $envValue) { if ($envValue !== getenv($envName)) {