From 93ee57b48a86137546a715cf60774ee77f71a5f2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 24 Apr 2024 10:49:08 +0200 Subject: [PATCH 01/90] convert empty CSV header names into numeric keys --- .../Component/Serializer/Encoder/CsvEncoder.php | 14 ++++++++++---- .../Serializer/Tests/Encoder/CsvEncoderTest.php | 8 +++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 55f78b1d0e013..a2d4df909dce8 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -181,18 +181,24 @@ public function decode(string $data, string $format, array $context = []) $depth = $headerCount[$i]; $arr = &$item; for ($j = 0; $j < $depth; ++$j) { + $headerName = $headers[$i][$j]; + + if ('' === $headerName) { + $headerName = $i; + } + // Handle nested arrays if ($j === ($depth - 1)) { - $arr[$headers[$i][$j]] = $cols[$i]; + $arr[$headerName] = $cols[$i]; continue; } - if (!isset($arr[$headers[$i][$j]])) { - $arr[$headers[$i][$j]] = []; + if (!isset($arr[$headerName])) { + $arr[$headerName] = []; } - $arr = &$arr[$headers[$i][$j]]; + $arr = &$arr[$headerName]; } } diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index 06cf6a0617d86..3d2163c06e923 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -218,7 +218,13 @@ public function testDecodeEmptyData() { $data = $this->encoder->decode("\n\n", 'csv'); - $this->assertSame([['' => null]], $data); + $this->assertSame([[0 => null]], $data); + } + + public function testMultipleEmptyHeaderNamesWithSeparator() + { + $this->encoder->decode(',. +,', 'csv'); } public function testEncodeVariableStructure() From 7e796e1769436e4fe01c65ce97eed34b556460e8 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Sun, 28 Apr 2024 10:53:28 +0200 Subject: [PATCH 02/90] [FrameworkBundle] Fix indentation --- .../DependencyInjection/FrameworkExtension.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 307048dd3e040..731c6e7ee4b3e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -2080,10 +2080,9 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) ->addTag('messenger.receiver', [ - 'alias' => $name, - 'is_failure_transport' => \in_array($name, $failureTransports), - ] - ) + 'alias' => $name, + 'is_failure_transport' => \in_array($name, $failureTransports), + ]) ; $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); $senderAliases[$name] = $transportId; From 93eb8a00cb0198010a4d9a39f9e1285dd517cbc6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 27 Apr 2024 12:02:12 +0200 Subject: [PATCH 03/90] handle edge cases when constructing constraints with named arguments --- .../Mapping/Loader/AbstractLoader.php | 12 +++++++ .../Mapping/Loader/XmlFileLoader.php | 8 ++++- .../Mapping/Loader/YamlFileLoader.php | 6 ++++ .../Fixtures/ConstraintWithNamedArguments.php | 33 +++++++++++++++++++ ...nstraintWithoutValueWithNamedArguments.php | 29 ++++++++++++++++ .../Mapping/Loader/XmlFileLoaderTest.php | 5 +++ .../Mapping/Loader/YamlFileLoaderTest.php | 5 +++ .../Mapping/Loader/constraint-mapping.xml | 16 +++++++++ .../Mapping/Loader/constraint-mapping.yml | 6 ++++ 9 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php create mode 100644 src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php index 3f0c0aa46fa97..146b0dc9edf54 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php @@ -87,6 +87,18 @@ protected function newConstraint(string $name, mixed $options = null): Constrain } if ($this->namedArgumentsCache[$className] ??= (bool) (new \ReflectionMethod($className, '__construct'))->getAttributes(HasNamedArguments::class)) { + if (null === $options) { + return new $className(); + } + + if (!\is_array($options)) { + return new $className($options); + } + + if (1 === \count($options) && isset($options['value'])) { + return new $className($options['value']); + } + return new $className(...$options); } diff --git a/src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php index 94d3f071e5a77..1c5f5287308df 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php @@ -80,7 +80,9 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array foreach ($nodes as $node) { if (\count($node) > 0) { if (\count($node->value) > 0) { - $options = $this->parseValues($node->value); + $options = [ + 'value' => $this->parseValues($node->value), + ]; } elseif (\count($node->constraint) > 0) { $options = $this->parseConstraints($node->constraint); } elseif (\count($node->option) > 0) { @@ -94,6 +96,10 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array $options = null; } + if (isset($options['groups']) && !\is_array($options['groups'])) { + $options['groups'] = (array) $options['groups']; + } + $constraints[] = $this->newConstraint((string) $node['name'], $options); } diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index e610b45427313..d17f96ef44741 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -91,6 +91,12 @@ protected function parseNodes(array $nodes): array $options = $this->parseNodes($options); } + if (null !== $options && (!\is_array($options) || array_is_list($options))) { + $options = [ + 'value' => $options, + ]; + } + $values[] = $this->newConstraint(key($childNodes), $options); } else { if (\is_array($childNodes)) { diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php new file mode 100644 index 0000000000000..70579011c3c94 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures; + +use Symfony\Component\Validator\Attribute\HasNamedArguments; +use Symfony\Component\Validator\Constraint; + +class ConstraintWithNamedArguments extends Constraint +{ + public $choices; + + #[HasNamedArguments] + public function __construct(array|string|null $choices = [], ?array $groups = null) + { + parent::__construct([], $groups); + + $this->choices = $choices; + } + + public function getTargets(): string + { + return self::CLASS_CONSTRAINT; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php new file mode 100644 index 0000000000000..af950fc139ad6 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures; + +use Symfony\Component\Validator\Attribute\HasNamedArguments; +use Symfony\Component\Validator\Constraint; + +class ConstraintWithoutValueWithNamedArguments extends Constraint +{ + #[HasNamedArguments] + public function __construct(?array $groups = null) + { + parent::__construct([], $groups); + } + + public function getTargets(): string + { + return self::CLASS_CONSTRAINT; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php index 5ba519ab195c5..2385dc888b276 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -32,6 +32,8 @@ use Symfony\Component\Validator\Tests\Fixtures\Entity_81; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\GroupSequenceProviderEntity; +use Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments; +use Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutValueWithNamedArguments; class XmlFileLoaderTest extends TestCase { @@ -66,6 +68,9 @@ public function testLoadClassMetadata() $expected->addConstraint(new Callback('validateMeStatic')); $expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'])); $expected->addConstraint(new Traverse(false)); + $expected->addConstraint(new ConstraintWithNamedArguments('foo')); + $expected->addConstraint(new ConstraintWithNamedArguments(['foo', 'bar'])); + $expected->addConstraint(new ConstraintWithoutValueWithNamedArguments(['foo'])); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(['min' => 3])); $expected->addPropertyConstraint('firstName', new Choice(['A', 'B'])); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php index a5c983939bcb2..e34e5466ed667 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -29,6 +29,8 @@ use Symfony\Component\Validator\Tests\Fixtures\Entity_81; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\GroupSequenceProviderEntity; +use Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments; +use Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutValueWithNamedArguments; class YamlFileLoaderTest extends TestCase { @@ -109,6 +111,9 @@ public function testLoadClassMetadata() $expected->addConstraint(new Callback('validateMe')); $expected->addConstraint(new Callback('validateMeStatic')); $expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'])); + $expected->addConstraint(new ConstraintWithoutValueWithNamedArguments()); + $expected->addConstraint(new ConstraintWithNamedArguments('foo')); + $expected->addConstraint(new ConstraintWithNamedArguments(['foo', 'bar'])); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(['min' => 3])); $expected->addPropertyConstraint('firstName', new Choice(['A', 'B'])); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml index 6183b074a65cb..8a7975f114137 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml @@ -36,6 +36,22 @@ false + + + foo + + + + + foo + bar + + + + + + + diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml index 0cf87cffe0a69..af091a89fad8b 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml @@ -15,6 +15,12 @@ Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: - Callback: validateMe - Callback: validateMeStatic - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + # Constraint with named arguments support without value + - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutValueWithNamedArguments: ~ + # Constraint with named arguments support with scalar value + - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: foo + # Constraint with named arguments support with array value + - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: [foo, bar] properties: firstName: From f456e75ec836277b16c90f522c88a1bf2e3eb808 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 29 Apr 2024 10:23:08 +0200 Subject: [PATCH 04/90] better distinguish URL schemes and windows drive letters --- src/Symfony/Component/Filesystem/Path.php | 2 +- src/Symfony/Component/Filesystem/Tests/PathTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 858e1623eb2cd..eb6d8ea080e8e 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -368,7 +368,7 @@ public static function isAbsolute(string $path): bool } // Strip scheme - if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + if (false !== ($schemeSeparatorPosition = strpos($path, '://')) && 1 !== $schemeSeparatorPosition) { $path = substr($path, $schemeSeparatorPosition + 3); } diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 77b9f2a2d0576..17c6142c3572e 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -375,6 +375,8 @@ public static function provideIsAbsolutePathTests(): \Generator yield ['C:/css/style.css', true]; yield ['D:/', true]; + yield ['C:///windows', true]; + yield ['C://test', true]; yield ['E:\\css\\style.css', true]; yield ['F:\\', true]; From d1c1cc8d48ee8d02504781f630fe643121751c6c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Apr 2024 13:16:34 +0200 Subject: [PATCH 05/90] Update CHANGELOG for 5.4.39 --- CHANGELOG-5.4.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG-5.4.md b/CHANGELOG-5.4.md index a4ba8eb29eeef..4675182aec6dd 100644 --- a/CHANGELOG-5.4.md +++ b/CHANGELOG-5.4.md @@ -7,6 +7,33 @@ in 5.4 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/v5.4.0...v5.4.1 +* 5.4.39 (2024-04-29) + + * bug #54751 [Validator]  detect wrong e-mail validation modes (xabbuh) + * bug #54723 [Form] read form values using the chain data accessor (xabbuh) + * bug #54706 [Yaml] call substr() with integer offsets (xabbuh) + * bug #54675 [PropertyInfo] Fix PHPStan properties type in trait (mtarld) + * bug #54635 [Serializer] Revert "Fix object normalizer when properties has the same name as their accessor" - it was a BC Break (NeilPeyssard) + * bug #54625 [Intl] Remove resources data from classmap generation (shyim) + * bug #54598 [TwigBridge]  implement NodeVisitorInterface instead of extending AbstractNodeVisitor (xabbuh) + * bug #54072 [HttpKernel] Fix datacollector caster for reference object property (ebuildy) + * bug #54564 [Translation] Skip state=needs-translation entries only when source == target (nicolas-grekas) + * bug #54579 [Cache] Always select database for persistent redis connections (uncaught) + * bug #54059 [Security] Validate that CSRF token in form login is string similar to username/password (glaubinix) + * bug #54547 [HttpKernel] Force non lazy controller services (smnandre) + * bug #54517 [HttpClient] Let curl handle transfer encoding (michaelhue) + * bug #52917 [Serializer] Fix unexpected allowed attributes (mtarld) + * bug #54063 [FrameworkBundle] Fix registration of the bundle path to translation (FlyingDR) + * bug #54392 [Messenger] Make Doctrine connection ignore unrelated tables on setup (MatTheCat) + * bug #54506 [HttpFoundation] Set content-type header in RedirectResponse (smnandre) + * bug #52698 [Serializer] Fix XML scalar to object denormalization (mtarld) + * bug #54485 [Serializer] Ignore when using #[Ignore] on a non-accessor (nicolas-grekas) + * bug #54242 [HttpClient] [EventSourceHttpClient] Fix consuming SSEs with \r\n separator (fancyweb) + * bug #54456 [DomCrawler] Encode html entities only if nessecary (ausi) + * bug #54471 [Filesystem] Strengthen the check of file permissions in `dumpFile` (alexandre-daubois) + * bug #54403 [FrameworkBundle] [Command] Fix #54402: Suppress PHP warning when is_readable() tries to access dirs outside of open_basedir restrictions (Jeldrik Geraedts) + * bug #54440 [Console] return null when message with name is not set (xabbuh) + * 5.4.38 (2024-04-02) * bug #54400 [HttpClient] stop all server processes after tests have run (xabbuh) From 71cb74d8ade824f08a3cf1adcdda302f5904af8b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Apr 2024 13:17:45 +0200 Subject: [PATCH 06/90] Update CONTRIBUTORS for 5.4.39 --- CONTRIBUTORS.md | 63 +++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 04ba9eca15947..2c65442650d09 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,8 +14,8 @@ The Symfony Connect username in parenthesis allows to get more information - Grégoire Pineau (lyrixx) - Thomas Calvet (fancyweb) - Christophe Coevoet (stof) - - Wouter de Jong (wouterj) - Alexandre Daubois (alexandre-daubois) + - Wouter de Jong (wouterj) - Jordi Boggiano (seldaek) - Maxime Steinhausser (ogizanagi) - Kévin Dunglas (dunglas) @@ -34,8 +34,8 @@ The Symfony Connect username in parenthesis allows to get more information - Tobias Nyholm (tobias) - Jérôme Tamarelle (gromnan) - Samuel ROZE (sroze) - - Pascal Borreli (pborreli) - Antoine Lamirault (alamirault) + - Pascal Borreli (pborreli) - Romain Neutron - HypeMC (hypemc) - Joseph Bielawski (stloyd) @@ -51,14 +51,14 @@ The Symfony Connect username in parenthesis allows to get more information - Igor Wiedler - Jan Schädlich (jschaedl) - Mathieu Lechat (mat_the_cat) - - Matthias Pigulla (mpdude) - Gabriel Ostrolucký (gadelat) + - Matthias Pigulla (mpdude) - Jonathan Wage (jwage) - Valentin Udaltsov (vudaltsov) + - Vincent Langlet (deviling) - Alexandre Salomé (alexandresalome) - Grégoire Paris (greg0ire) - William DURAND - - Vincent Langlet (deviling) - ornicar - Dany Maillard (maidmaid) - Eriksen Costa @@ -69,6 +69,7 @@ The Symfony Connect username in parenthesis allows to get more information - Francis Besset (francisbesset) - Titouan Galopin (tgalopin) - Pierre du Plessis (pierredup) + - Simon André (simonandre) - David Maicher (dmaicher) - Bulat Shakirzyanov (avalanche123) - Iltar van der Berg @@ -77,18 +78,17 @@ The Symfony Connect username in parenthesis allows to get more information - Saša Stamenković (umpirsky) - Allison Guilhem (a_guilhem) - Mathieu Piot (mpiot) - - Simon André (simonandre) - Mathieu Santostefano (welcomattic) - Alexander Schranz (alexander-schranz) - Vasilij Duško (staff) + - Tomasz Kowalczyk (thunderer) + - Mathias Arlaud (mtarld) - Sarah Khalil (saro0h) - Laurent VOULLEMIER (lvo) - Konstantin Kudryashov (everzet) - - Tomasz Kowalczyk (thunderer) - Guilhem N (guilhemn) - Bilal Amarni (bamarni) - Eriksen Costa - - Mathias Arlaud (mtarld) - Florin Patan (florinpatan) - Vladimir Reznichenko (kalessil) - Peter Rehm (rpet) @@ -96,8 +96,8 @@ The Symfony Connect username in parenthesis allows to get more information - Henrik Bjørnskov (henrikbjorn) - David Buchmann (dbu) - Andrej Hudec (pulzarraider) - - Jáchym Toušek (enumag) - Ruud Kamphuis (ruudk) + - Jáchym Toušek (enumag) - Christian Raue - Eric Clemmons (ericclemmons) - Denis (yethee) @@ -130,6 +130,7 @@ The Symfony Connect username in parenthesis allows to get more information - Vasilij Dusko | CREATION - Jordan Alliot (jalliot) - Phil E. Taylor (philetaylor) + - Joel Wurtz (brouznouf) - John Wards (johnwards) - Théo FIDRY - Antoine Hérault (herzult) @@ -137,7 +138,6 @@ The Symfony Connect username in parenthesis allows to get more information - Yanick Witschi (toflar) - Jeroen Spee (jeroens) - Arnaud Le Blanc (arnaud-lb) - - Joel Wurtz (brouznouf) - Sebastiaan Stok (sstok) - Maxime STEINHAUSSER - Rokas Mikalkėnas (rokasm) @@ -198,6 +198,7 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Niels Keurentjes (curry684) + - Dāvis Zālītis (k0d3r1s) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) - Saif Eddin Gmati (azjezz) @@ -211,7 +212,6 @@ The Symfony Connect username in parenthesis allows to get more information - Pablo Godel (pgodel) - Florent Mata (fmata) - Alessandro Chitolina (alekitto) - - Dāvis Zālītis (k0d3r1s) - Rafael Dohms (rdohms) - Roman Martinuk (a2a4) - Thomas Landauer (thomas-landauer) @@ -262,6 +262,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tyson Andre - GDIBass - Samuel NELA (snela) + - Florent Morselli (spomky_) - Vincent AUBERT (vincent) - Michael Voříšek - zairig imad (zairigimad) @@ -269,6 +270,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sébastien Alfaiate (seb33300) - James Halsall (jaitsu) - Christian Scheb + - Bob van de Vijver (bobvandevijver) - Guillaume (guill) - Mikael Pajunen - Warnar Boekkooi (boekkooi) @@ -294,10 +296,10 @@ The Symfony Connect username in parenthesis allows to get more information - Chi-teck - Andre Rømcke (andrerom) - Baptiste Leduc (korbeil) + - Karoly Gossler (connorhu) - Timo Bakx (timobakx) - soyuka - Ruben Gonzalez (rubenrua) - - Bob van de Vijver (bobvandevijver) - Benjamin Dulau (dbenjamin) - Markus Fasselt (digilist) - Denis Brumann (dbrumann) @@ -308,6 +310,7 @@ The Symfony Connect username in parenthesis allows to get more information - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - Bastien Jaillot (bastnic) + - Soner Sayakci - Stadly - Stepan Anchugov (kix) - bronze1man @@ -323,7 +326,6 @@ The Symfony Connect username in parenthesis allows to get more information - Pierre Minnieur (pminnieur) - Dominique Bongiraud - Hugo Monteiro (monteiro) - - Karoly Gossler (connorhu) - Bram Leeda (bram123) - Dmitrii Poddubnyi (karser) - Julien Pauli @@ -334,6 +336,7 @@ The Symfony Connect username in parenthesis allows to get more information - Leszek Prabucki (l3l0) - Giorgio Premi - Thomas Lallement (raziel057) + - Yassine Guedidi (yguedidi) - François Zaninotto (fzaninotto) - Dustin Whittle (dustinwhittle) - Timothée Barray (tyx) @@ -348,7 +351,6 @@ The Symfony Connect username in parenthesis allows to get more information - Michele Orselli (orso) - Sven Paulus (subsven) - Maxime Veber (nek-) - - Soner Sayakci - Valentine Boineau (valentineboineau) - Rui Marinho (ruimarinho) - Patrick Landolt (scube) @@ -367,7 +369,6 @@ The Symfony Connect username in parenthesis allows to get more information - Mantis Development - Marko Kaznovac (kaznovac) - Hidde Wieringa (hiddewie) - - Florent Morselli (spomky_) - dFayet - Rob Frawley 2nd (robfrawley) - Renan (renanbr) @@ -377,7 +378,6 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Tschinder - Christian Schmidt - Alexander Kotynia (olden) - - Yassine Guedidi (yguedidi) - Elnur Abdurrakhimov (elnur) - Manuel Reinhard (sprain) - BoShurik @@ -418,6 +418,7 @@ The Symfony Connect username in parenthesis allows to get more information - Marvin Petker - GordonsLondon - Ray + - Asis Pattisahusiwa - Philipp Cordes (corphi) - Chekote - Thomas Adam @@ -477,6 +478,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thomas Bisignani (toma) - Florian Klein (docteurklein) - Damien Alexandre (damienalexandre) + - javaDeveloperKid - Manuel Kießling (manuelkiessling) - Alexey Kopytko (sanmai) - Warxcell (warxcell) @@ -487,7 +489,6 @@ The Symfony Connect username in parenthesis allows to get more information - Bertrand Zuchuat (garfield-fr) - Marc Morera (mmoreram) - Quynh Xuan Nguyen (seriquynh) - - Asis Pattisahusiwa - Gabor Toth (tgabi333) - realmfoo - Fabien S (bafs) @@ -518,6 +519,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thierry T (lepiaf) - Lorenz Schori - Lukáš Holeczy (holicz) + - Jonathan H. Wage - Jeremy Livingston (jeremylivingston) - ivan - SUMIDA, Ippei (ippey_s) @@ -550,6 +552,7 @@ The Symfony Connect username in parenthesis allows to get more information - Artur Eshenbrener - Harm van Tilborg (hvt) - Thomas Perez (scullwm) + - Gwendolen Lynch - Cédric Anne - smoench - Felix Labrecque @@ -588,7 +591,6 @@ The Symfony Connect username in parenthesis allows to get more information - Kirill chEbba Chebunin - Pol Dellaiera (drupol) - Alex (aik099) - - javaDeveloperKid - Fabien Villepinte - SiD (plbsid) - Greg Thornton (xdissent) @@ -668,9 +670,9 @@ The Symfony Connect username in parenthesis allows to get more information - Dmitriy Mamontov (mamontovdmitriy) - Jan Schumann - Matheo Daninos (mathdns) + - Neil Peyssard (nepey) - Niklas Fiekas - Mark Challoner (markchalloner) - - Jonathan H. Wage - Markus Bachmann (baachi) - Matthieu Lempereur (mryamous) - Gunnstein Lye (glye) @@ -710,7 +712,6 @@ The Symfony Connect username in parenthesis allows to get more information - DerManoMann - Jérôme Tanghe (deuchnord) - Mathias STRASSER (roukmoute) - - Gwendolen Lynch - simon chrzanowski (simonch) - Kamil Kokot (pamil) - Seb Koelen @@ -905,6 +906,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ramunas Pabreza (doobas) - Yuriy Vilks (igrizzli) - Terje Bråten + - Andrey Lebedev (alebedev) - Sebastian Krebs - Piotr Stankowski - Pierre-Emmanuel Tanguy (petanguy) @@ -970,7 +972,6 @@ The Symfony Connect username in parenthesis allows to get more information - Christophe Villeger (seragan) - Krystian Marcisz (simivar) - Julien Fredon - - Neil Peyssard (nepey) - Xavier Leune (xleune) - Hany el-Kerdany - Wang Jingyu @@ -1065,6 +1066,7 @@ The Symfony Connect username in parenthesis allows to get more information - Robin Lehrmann - Szijarto Tamas - Thomas P + - Stephan Vock (glaubinix) - Jaroslav Kuba - Benjamin Zikarsky (bzikarsky) - Kristijan Kanalaš (kristijan_kanalas_infostud) @@ -1149,6 +1151,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ворожцов Максим (myks92) - Dalibor Karlović - Randy Geraads + - Jay Klehr - Andreas Leathley (iquito) - Vladimir Luchaninov (luchaninov) - Sebastian Grodzicki (sgrodzicki) @@ -1225,6 +1228,7 @@ The Symfony Connect username in parenthesis allows to get more information - Felds Liscia (felds) - Jérémy DECOOL (jdecool) - Sergey Panteleev + - Alexander Grimalovsky (flying) - Andrew Hilobok (hilobok) - Noah Heck (myesain) - Christian Soronellas (theunic) @@ -1421,6 +1425,7 @@ The Symfony Connect username in parenthesis allows to get more information - Michael Roterman (wtfzdotnet) - Philipp Keck - Pavol Tuka + - Shyim - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) @@ -1482,6 +1487,7 @@ The Symfony Connect username in parenthesis allows to get more information - MrMicky - Stewart Malik - Renan Taranto (renan-taranto) + - Ninos Ego - Stefan Graupner (efrane) - Gemorroj (gemorroj) - Adrien Chinour @@ -1492,6 +1498,7 @@ The Symfony Connect username in parenthesis allows to get more information - Uladzimir Tsykun - iamvar - Amaury Leroux de Lens (amo__) + - Rene de Lima Barbosa (renedelima) - Christian Jul Jensen - Alexandre GESLIN - The Whole Life to Learn @@ -1675,6 +1682,7 @@ The Symfony Connect username in parenthesis allows to get more information - Goran Juric - Laurent G. (laurentg) - Jean-Baptiste Nahan + - Thomas Decaux - Nicolas Macherey - Asil Barkin Elik (asilelik) - Bhujagendra Ishaya @@ -1740,7 +1748,6 @@ The Symfony Connect username in parenthesis allows to get more information - Denis Kop - Fabrice Locher - Kamil Szalewski (szal1k) - - Andrey Lebedev (alebedev) - Jean-Guilhem Rouel (jean-gui) - Yoann MOROCUTTI - Ivan Yivoff @@ -1769,6 +1776,7 @@ The Symfony Connect username in parenthesis allows to get more information - Hans Mackowiak - Hugo Fonseca (fonsecas72) - Marc Duboc (icemad) + - uncaught - Martynas Narbutas - Timothée BARRAY - Nilmar Sanchez Muguercia @@ -1875,6 +1883,7 @@ The Symfony Connect username in parenthesis allows to get more information - Clément - Gustavo Adrian - Jorrit Schippers (jorrit) + - Yann (yann_eugone) - Matthias Neid - Yannick - Kuzia @@ -1908,7 +1917,6 @@ The Symfony Connect username in parenthesis allows to get more information - Jason Schilling (chapterjason) - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) - - Stephan Vock (glaubinix) - Guillem Fondin (guillemfondin) - Nathan PAGE (nathix) - Ryan Rogers @@ -2005,7 +2013,6 @@ The Symfony Connect username in parenthesis allows to get more information - Stefano A. (stefano93) - PierreRebeilleau - AlbinoDrought - - Jay Klehr - Sergey Yuferev - Monet Emilien - voodooism @@ -2166,7 +2173,6 @@ The Symfony Connect username in parenthesis allows to get more information - ShiraNai7 - Cedrick Oka - Antal Áron (antalaron) - - Alexander Grimalovsky (flying) - Guillaume Sainthillier (guillaume-sainthillier) - Ivan Pepelko (pepelko) - Vašek Purchart (vasek-purchart) @@ -2273,6 +2279,7 @@ The Symfony Connect username in parenthesis allows to get more information - roog - parinz1234 - Romain Geissler + - Martin Auswöger - Adrien Moiruad - Viktoriia Zolotova - Tomaz Ahlin @@ -2351,6 +2358,7 @@ The Symfony Connect username in parenthesis allows to get more information - Wouter Diesveld - Romain - Matěj Humpál + - Kasper Hansen - Amine Matmati - Kristen Gilden - caalholm @@ -2501,6 +2509,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tiago Garcia (tiagojsag) - Artiom - Jakub Simon + - Eviljeks - robin.de.croock - Brandon Antonio Lorenzo - Bouke Haarsma @@ -2722,6 +2731,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thomas Rothe - Edwin - Troy Crawford + - Kirill Roskolii - Jeroen van den Nieuwenhuisen - nietonfir - Andriy @@ -2933,6 +2943,7 @@ The Symfony Connect username in parenthesis allows to get more information - Joel Marcey - zolikonta - Daniel Bartoníček + - Michael Hüneburg - David Christmann - root - pf @@ -3314,6 +3325,7 @@ The Symfony Connect username in parenthesis allows to get more information - cmfcmf - sarah-eit - Michal Forbak + - CarolienBEER - Drew Butler - Alexey Berezuev - pawel-lewtak @@ -3330,7 +3342,6 @@ The Symfony Connect username in parenthesis allows to get more information - Anatol Belski - Javier - Alexis BOYER - - Shyim - bch36 - Kaipi Yann - wiseguy1394 @@ -3413,6 +3424,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alex Nostadt - Michael Squires - Egor Gorbachev + - Julian Krzefski - Derek Stephen McLean - Norman Soetbeer - zorn @@ -3550,6 +3562,7 @@ The Symfony Connect username in parenthesis allows to get more information - Arkadiusz Kondas (itcraftsmanpl) - j0k (j0k) - joris de wit (jdewit) + - JG (jege) - Jérémy CROMBEZ (jeremy) - Jose Manuel Gonzalez (jgonzalez) - Joachim Krempel (jkrempel) From 2baba1875980d8f74edbd43f70881f896ca03fe8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Apr 2024 13:17:46 +0200 Subject: [PATCH 07/90] Update VERSION for 5.4.39 --- 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 aae7d8f9cd32c..d4fe96b6b7b56 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.39-DEV'; + public const VERSION = '5.4.39'; public const VERSION_ID = 50439; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; public const RELEASE_VERSION = 39; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From 9f7fc26f3c72225ae30cb45fc175d0d917232529 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Apr 2024 13:21:23 +0200 Subject: [PATCH 08/90] Bump Symfony version to 5.4.40 --- 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 d4fe96b6b7b56..c51f96e861e40 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.39'; - public const VERSION_ID = 50439; + public const VERSION = '5.4.40-DEV'; + public const VERSION_ID = 50440; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 39; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 40; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From bfbf491fbb785eab1df3867fad2b8330966a77b9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Apr 2024 14:09:32 +0200 Subject: [PATCH 09/90] Bump Symfony version to 6.4.8 --- 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 d0926d42fbbdb..3fa5858430569 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.4.7'; - public const VERSION_ID = 60407; + public const VERSION = '6.4.8-DEV'; + public const VERSION_ID = 60408; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 7; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 8; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2026'; public const END_OF_LIFE = '11/2027'; From ca2040e11960a0d583461f4ebaf42a57efa6f4e4 Mon Sep 17 00:00:00 2001 From: Ivan Mezinov Date: Tue, 23 Apr 2024 02:07:40 +0300 Subject: [PATCH 10/90] show overridden vars too --- .../Component/Dotenv/Command/DebugCommand.php | 95 ++++++++++--------- .../Dotenv/Tests/Command/DebugCommandTest.php | 5 +- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Command/DebugCommand.php b/src/Symfony/Component/Dotenv/Command/DebugCommand.php index 0585043cd9463..237d7b7cfd228 100644 --- a/src/Symfony/Component/Dotenv/Command/DebugCommand.php +++ b/src/Symfony/Component/Dotenv/Command/DebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Dotenv\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; @@ -49,97 +50,105 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $envFiles = $this->getEnvFiles(); - $availableFiles = array_filter($envFiles, function (string $file) { - return is_file($this->getFilePath($file)); - }); + $filePath = $this->projectDirectory.\DIRECTORY_SEPARATOR.'.env'; + $envFiles = $this->getEnvFiles($filePath); + $availableFiles = array_filter($envFiles, 'is_file'); - if (\in_array('.env.local.php', $availableFiles, true)) { + if (\in_array(sprintf('%s.local.php', $filePath), $availableFiles, true)) { $io->warning('Due to existing dump file (.env.local.php) all other dotenv files are skipped.'); } - if (is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $io->warning('The file .env.dist gets skipped due to the existence of .env.'); + if (is_file($filePath) && is_file(sprintf('%s.dist', $filePath))) { + $io->warning(sprintf('The file %s.dist gets skipped due to the existence of %1$s.', $this->getRelativeName($filePath))); } $io->section('Scanned Files (in descending priority)'); - $io->listing(array_map(static function (string $envFile) use ($availableFiles) { + $io->listing(array_map(function (string $envFile) use ($availableFiles) { return \in_array($envFile, $availableFiles, true) - ? sprintf('✓ %s', $envFile) - : sprintf('⨯ %s', $envFile); + ? sprintf('✓ %s', $this->getRelativeName($envFile)) + : sprintf('⨯ %s', $this->getRelativeName($envFile)); }, $envFiles)); + $variables = $this->getVariables($availableFiles); + $io->section('Variables'); $io->table( - array_merge(['Variable', 'Value'], $availableFiles), - $this->getVariables($availableFiles) + array_merge(['Variable', 'Value'], array_map([$this, 'getRelativeName'], $availableFiles)), + $variables ); - $io->comment('Note real values might be different between web and CLI.'); + $io->comment('Note that values might be different between web and CLI.'); return 0; } private function getVariables(array $envFiles): array { - $dotenvVars = $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''; + $variables = []; + $fileValues = []; + $dotenvVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? '')); - if ('' === $dotenvVars) { - return []; + foreach ($envFiles as $envFile) { + $fileValues[$envFile] = $this->loadValues($envFile); + $variables += $fileValues[$envFile]; } - $vars = explode(',', $dotenvVars); - sort($vars); + foreach ($variables as $var => $varDetails) { + $realValue = $_SERVER[$var] ?? ''; + $varDetails = [$var, ''.OutputFormatter::escape($realValue).'']; + $varSeen = !isset($dotenvVars[$var]); - $output = []; - $fileValues = []; - foreach ($vars as $var) { - $realValue = $_SERVER[$var]; - $varDetails = [$var, $realValue]; foreach ($envFiles as $envFile) { - $values = $fileValues[$envFile] ?? $fileValues[$envFile] = $this->loadValues($envFile); - - $varString = $values[$var] ?? 'n/a'; - $shortenedVar = $this->getHelper('formatter')->truncate($varString, 30); - $varDetails[] = $varString === $realValue ? ''.$shortenedVar.'' : $shortenedVar; + if (null === $value = $fileValues[$envFile][$var] ?? null) { + $varDetails[] = 'n/a'; + continue; + } + + $shortenedValue = OutputFormatter::escape($this->getHelper('formatter')->truncate($value, 30)); + $varDetails[] = $value === $realValue && !$varSeen ? ''.$shortenedValue.'' : $shortenedValue; + $varSeen = $varSeen || $value === $realValue; } - $output[] = $varDetails; + $variables[$var] = $varDetails; } - return $output; + ksort($variables); + + return $variables; } - private function getEnvFiles(): array + private function getEnvFiles(string $filePath): array { $files = [ - '.env.local.php', - sprintf('.env.%s.local', $this->kernelEnvironment), - sprintf('.env.%s', $this->kernelEnvironment), + sprintf('%s.local.php', $filePath), + sprintf('%s.%s.local', $filePath, $this->kernelEnvironment), + sprintf('%s.%s', $filePath, $this->kernelEnvironment), ]; if ('test' !== $this->kernelEnvironment) { - $files[] = '.env.local'; + $files[] = sprintf('%s.local', $filePath); } - if (!is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $files[] = '.env.dist'; + if (!is_file($filePath) && is_file(sprintf('%s.dist', $filePath))) { + $files[] = sprintf('%s.dist', $filePath); } else { - $files[] = '.env'; + $files[] = $filePath; } return $files; } - private function getFilePath(string $file): string + private function getRelativeName(string $filePath): string { - return $this->projectDirectory.\DIRECTORY_SEPARATOR.$file; + if (str_starts_with($filePath, $this->projectDirectory)) { + return substr($filePath, \strlen($this->projectDirectory) + 1); + } + + return basename($filePath); } - private function loadValues(string $file): array + private function loadValues(string $filePath): array { - $filePath = $this->getFilePath($file); - if (str_ends_with($filePath, '.php')) { return include $filePath; } diff --git a/src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php index b8b7e39008607..001baec0c2539 100644 --- a/src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php @@ -52,8 +52,11 @@ public function testEmptyDotEnvVarsList() ---------- ------- ------------ ------%S Variable Value .env.local .env%S ---------- ------- ------------ ------%S + FOO baz bar%S + TEST123 n/a true%S + ---------- ------- ------------ ------%S - // Note real values might be different between web and CLI.%S + // Note that values might be different between web and CLI.%S %a OUTPUT; From 4d2679de7a0760391d6be33928d775e599897c89 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 29 Apr 2024 21:38:17 +0200 Subject: [PATCH 11/90] accept AbstractAsset instances when filtering schemas --- .../Bridge/Doctrine/Transport/Connection.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php index 100058d240fcd..6980a2e6b03fb 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php @@ -21,6 +21,7 @@ use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; +use Doctrine\DBAL\Schema\AbstractAsset; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; @@ -289,7 +290,17 @@ public function setup(): void { $configuration = $this->driverConnection->getConfiguration(); $assetFilter = $configuration->getSchemaAssetsFilter(); - $configuration->setSchemaAssetsFilter(function (string $tableName) { return $tableName === $this->configuration['table_name']; }); + $configuration->setSchemaAssetsFilter(function ($tableName) { + if ($tableName instanceof AbstractAsset) { + $tableName = $tableName->getName(); + } + + if (!\is_string($tableName)) { + throw new \TypeError(sprintf('The table name must be an instance of "%s" or a string ("%s" given).', AbstractAsset::class, get_debug_type($tableName))); + } + + return $tableName === $this->configuration['table_name']; + }); $this->updateSchema(); $configuration->setSchemaAssetsFilter($assetFilter); $this->autoSetup = false; From 3d174a96ff253a877f81fe7216e1e72eae9d1d0e Mon Sep 17 00:00:00 2001 From: Arend Hummeling Date: Mon, 29 Apr 2024 23:27:03 +0200 Subject: [PATCH 12/90] fix: remove unwanted type cast --- src/Symfony/Component/Cache/Traits/RedisTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index af6390b9bcfa5..33f37d828ea81 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -499,7 +499,7 @@ protected function doClear(string $namespace) } $this->doDelete($keys); } - } while ($cursor = (int) $cursor); + } while ($cursor); } return $cleared; From 4118849d868e0a228a83fac2c4b0c339e4b9fcfc Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 26 Apr 2024 13:35:27 +0200 Subject: [PATCH 13/90] Remove calls to `onConsecutiveCalls()` --- ...ineOpenTransactionLoggerMiddlewareTest.php | 2 +- .../Tests/Handler/ConsoleHandlerTest.php | 5 +- .../Tests/Translation/TranslatorTest.php | 2 +- .../Config/Tests/Loader/FileLoaderTest.php | 16 ++-- .../Config/Tests/Util/XmlUtilsTest.php | 3 +- .../EventListener/SessionListenerTest.php | 20 ++--- .../Fragment/InlineFragmentRendererTest.php | 15 +++- .../HttpKernel/Tests/HttpCache/EsiTest.php | 2 +- .../HttpKernel/Tests/HttpCache/SsiTest.php | 2 +- src/Symfony/Component/Lock/Tests/LockTest.php | 43 ++++++----- .../Tests/Transport/FailoverTransportTest.php | 73 ++++++++++++------ .../Transport/RoundRobinTransportTest.php | 12 ++- .../Tests/Transport/AmazonSqsSenderTest.php | 6 +- .../Amqp/Tests/Transport/AmqpSenderTest.php | 10 +-- .../Amqp/Tests/Transport/ConnectionTest.php | 66 ++++++++-------- .../Tests/Transport/BeanstalkdSenderTest.php | 4 +- .../Tests/Transport/DoctrineSenderTest.php | 4 +- .../Redis/Tests/Transport/ConnectionTest.php | 2 +- .../Redis/Tests/Transport/RedisSenderTest.php | 2 +- .../Command/SetupTransportsCommandTest.php | 12 ++- .../DispatchAfterCurrentBusMiddlewareTest.php | 76 ++++++++++--------- .../Tests/Transport/FailoverTransportTest.php | 43 +++++++---- .../Tests/Hasher/UserPasswordHasherTest.php | 2 +- .../Tests/Encoder/UserPasswordEncoderTest.php | 2 +- .../AbstractObjectNormalizerTest.php | 15 ++-- .../Mapping/Loader/PropertyInfoLoaderTest.php | 13 ++-- 26 files changed, 257 insertions(+), 195 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineOpenTransactionLoggerMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineOpenTransactionLoggerMiddlewareTest.php index 626c19eb4ceae..3682ad00d5085 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineOpenTransactionLoggerMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineOpenTransactionLoggerMiddlewareTest.php @@ -52,7 +52,7 @@ public function testMiddlewareWrapsInTransactionAndFlushes() { $this->connection->expects($this->exactly(1)) ->method('isTransactionActive') - ->will($this->onConsecutiveCalls(true, true, false)) + ->willReturn(true, true, false) ; $this->middleware->handle(new Envelope(new \stdClass()), $this->getStackMock()); diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php index 4ddaddbde1218..f83599244a298 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php @@ -117,10 +117,7 @@ public function testVerbosityChanged() $output ->expects($this->exactly(2)) ->method('getVerbosity') - ->willReturnOnConsecutiveCalls( - OutputInterface::VERBOSITY_QUIET, - OutputInterface::VERBOSITY_DEBUG - ) + ->willReturn(OutputInterface::VERBOSITY_QUIET, OutputInterface::VERBOSITY_DEBUG) ; $handler = new ConsoleHandler($output); $this->assertFalse($handler->isHandling(['level' => Logger::NOTICE]), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index dc00ef99e8210..c13d50bd23f73 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -271,7 +271,7 @@ protected function getLoader() $loader ->expects($this->exactly(7)) ->method('load') - ->willReturnOnConsecutiveCalls( + ->willReturn( $this->getCatalogue('fr', [ 'foo' => 'foo (FR)', ]), diff --git a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php index cae46ca8f9adf..7503dd196d7d6 100644 --- a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php @@ -25,13 +25,15 @@ public function testImportWithFileLocatorDelegation() $locatorMock = $this->createMock(FileLocatorInterface::class); $locatorMockForAdditionalLoader = $this->createMock(FileLocatorInterface::class); - $locatorMockForAdditionalLoader->expects($this->any())->method('locate')->will($this->onConsecutiveCalls( - ['path/to/file1'], // Default - ['path/to/file1', 'path/to/file2'], // First is imported - ['path/to/file1', 'path/to/file2'], // Second is imported - ['path/to/file1'], // Exception - ['path/to/file1', 'path/to/file2'] // Exception - )); + $locatorMockForAdditionalLoader->expects($this->any()) + ->method('locate') + ->willReturn( + ['path/to/file1'], + ['path/to/file1', 'path/to/file2'], + ['path/to/file1', 'path/to/file2'], + ['path/to/file1'], + ['path/to/file1', 'path/to/file2'] + ); $fileLoader = new TestFileLoader($locatorMock); $fileLoader->setSupports(false); diff --git a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php index 8c1cd8543be19..be8c53155f0ff 100644 --- a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php +++ b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php @@ -76,7 +76,8 @@ public function testLoadFile() } $mock = $this->createMock(Validator::class); - $mock->expects($this->exactly(2))->method('validate')->will($this->onConsecutiveCalls(false, true)); + $mock->expects($this->exactly(2))->method('validate') + ->willReturn(false, true); try { XmlUtils::loadFile($fixtures.'valid.xml', [$mock, 'validate']); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index f3265823a5765..1934af66247dd 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -45,7 +45,7 @@ class SessionListenerTest extends TestCase public function testSessionCookieOptions(array $phpSessionOptions, array $sessionOptions, array $expectedSessionOptions) { $session = $this->createMock(Session::class); - $session->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->method('getUsageIndex')->willReturn(0, 1); $session->method('getId')->willReturn('123456'); $session->method('getName')->willReturn('PHPSESSID'); $session->method('save'); @@ -398,7 +398,7 @@ public function testSessionUsesFactory() public function testResponseIsPrivateIfSessionStarted() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -423,7 +423,7 @@ public function testResponseIsPrivateIfSessionStarted() public function testResponseIsStillPublicIfSessionStartedAndHeaderPresent() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -450,7 +450,7 @@ public function testResponseIsStillPublicIfSessionStartedAndHeaderPresent() public function testSessionSaveAndResponseHasSessionCookie() { $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $session->expects($this->exactly(1))->method('getId')->willReturn('123456'); $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); $session->expects($this->exactly(1))->method('save'); @@ -535,7 +535,7 @@ public function testUninitializedSessionWithoutInitializedSession() public function testResponseHeadersMaxAgeAndExpiresNotBeOverridenIfSessionStarted() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -565,7 +565,7 @@ public function testResponseHeadersMaxAgeAndExpiresNotBeOverridenIfSessionStarte public function testResponseHeadersMaxAgeAndExpiresDefaultValuesIfSessionStarted() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -618,7 +618,7 @@ public function testSurrogateMainRequestIsPublic() { $session = $this->createMock(Session::class); $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); - $session->expects($this->exactly(4))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1, 1, 1)); + $session->expects($this->exactly(4))->method('getUsageIndex')->willReturn(0, 1, 1, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -715,7 +715,7 @@ public function testGetSessionSetsSessionOnMainRequest() public function testSessionUsageExceptionIfStatelessAndSessionUsed() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $container = new Container(); $container->set('initialized_session', $session); @@ -734,7 +734,7 @@ public function testSessionUsageExceptionIfStatelessAndSessionUsed() public function testSessionUsageLogIfStatelessAndSessionUsed() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->exactly(1))->method('warning'); @@ -759,7 +759,7 @@ public function testSessionIsSavedWhenUnexpectedSessionExceptionThrown() $session->expects($this->exactly(1))->method('getId')->willReturn('123456'); $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); $session->method('isStarted')->willReturn(true); - $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + $session->expects($this->exactly(2))->method('getUsageIndex')->willReturn(0, 1); $session->expects($this->exactly(1))->method('save'); $container = new Container(); diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index 69bd7445acfd6..fb22a1a0942b2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -102,10 +102,17 @@ public function testRenderExceptionIgnoreErrors() public function testRenderExceptionIgnoreErrorsWithAlt() { - $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls( - $this->throwException(new \RuntimeException('foo')), - $this->returnValue(new Response('bar')) - ))); + $strategy = new InlineFragmentRenderer($this->getKernel($this->returnCallback(function () { + static $firstCall = true; + + if ($firstCall) { + $firstCall = false; + + throw new \RuntimeException('foo'); + } + + return new Response('bar'); + }))); $this->assertEquals('bar', $strategy->render('/', Request::create('/'), ['ignore_errors' => true, 'alt' => '/foo'])->getContent()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php index e876f28189087..677d38be62896 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php @@ -245,7 +245,7 @@ protected function getCache($request, $response) if (\is_array($response)) { $cache->expects($this->any()) ->method('handle') - ->will($this->onConsecutiveCalls(...$response)) + ->willReturn(...$response) ; } else { $cache->expects($this->any()) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php index 97cc8fccd03d0..15e6ebcaee5c6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php @@ -201,7 +201,7 @@ protected function getCache($request, $response) if (\is_array($response)) { $cache->expects($this->any()) ->method('handle') - ->will($this->onConsecutiveCalls(...$response)) + ->willReturn(...$response) ; } else { $cache->expects($this->any()) diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php index ee019a1d8db51..0b0349e81b5dd 100644 --- a/src/Symfony/Component/Lock/Tests/LockTest.php +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -39,7 +39,7 @@ public function testAcquireNoBlocking() ->method('save'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquire(false)); } @@ -55,7 +55,7 @@ public function testAcquireNoBlockingWithPersistingStoreInterface() ->method('save'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquire(false)); } @@ -71,7 +71,7 @@ public function testAcquireBlockingWithPersistingStoreInterface() ->method('save'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquire(true)); } @@ -93,7 +93,7 @@ public function testAcquireBlockingRetryWithPersistingStoreInterface() }); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquire(true)); } @@ -110,7 +110,7 @@ public function testAcquireReturnsFalse() ->willThrowException(new LockConflictedException()); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertFalse($lock->acquire(false)); } @@ -127,7 +127,7 @@ public function testAcquireReturnsFalseStoreInterface() ->willThrowException(new LockConflictedException()); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertFalse($lock->acquire(false)); } @@ -146,7 +146,7 @@ public function testAcquireBlockingWithBlockingStoreInterface() ->method('waitAndSave'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquire(true)); } @@ -166,7 +166,7 @@ public function testAcquireSetsTtl() ->with($key, 10); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $lock->acquire(); } @@ -183,7 +183,7 @@ public function testRefresh() ->with($key, 10); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $lock->refresh(); } @@ -200,7 +200,7 @@ public function testRefreshCustom() ->with($key, 20); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $lock->refresh(20); } @@ -214,7 +214,7 @@ public function testIsAquired() $store ->method('exists') ->with($key) - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->isAcquired()); } @@ -267,8 +267,8 @@ public function testReleaseOnDestruction() $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false) - ; + ->willReturn(true, false); + $store ->expects($this->once()) ->method('delete') @@ -286,8 +286,8 @@ public function testNoAutoReleaseWhenNotConfigured() $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false) - ; + ->willReturn(true, false); + $store ->expects($this->never()) ->method('delete') @@ -313,7 +313,8 @@ public function testReleaseThrowsExceptionWhenDeletionFail() $store ->expects($this->never()) ->method('exists') - ->with($key); + ->with($key) + ->willReturn(true); $lock->release(); } @@ -426,7 +427,7 @@ public function testAcquireReadNoBlockingWithSharedLockStoreInterface() ->method('saveRead'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquireRead(false)); } @@ -534,7 +535,7 @@ public function testAcquireReadBlockingWithBlockingSharedLockStoreInterface() ->method('waitAndSaveRead'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquireRead(true)); } @@ -556,7 +557,7 @@ public function testAcquireReadBlockingWithSharedLockStoreInterface() }); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquireRead(true)); } @@ -572,7 +573,7 @@ public function testAcquireReadBlockingWithBlockingLockStoreInterface() ->method('waitAndSave'); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquireRead(true)); } @@ -594,7 +595,7 @@ public function testAcquireReadBlockingWithPersistingStoreInterface() }); $store ->method('exists') - ->willReturnOnConsecutiveCalls(true, false); + ->willReturn(true, false); $this->assertTrue($lock->acquireRead(true)); } diff --git a/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php index 99be0e01e6e87..21a5b72238927 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php @@ -85,16 +85,30 @@ public function testSendOneDead() public function testSendOneDeadAndRecoveryWithinRetryPeriod() { $t1 = $this->createMock(TransportInterface::class); - $t1->method('send')->willReturnOnConsecutiveCalls($this->throwException(new TransportException())); + + $t1Matcher = $this->any(); + $t1->expects($t1Matcher) + ->method('send') + ->willReturnCallback(function () use ($t1Matcher) { + if (1 === $t1Matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); + $t2 = $this->createMock(TransportInterface::class); - $t2->expects($this->exactly(4)) + $t2Matcher = $this->exactly(4); + $t2->expects($t2Matcher) ->method('send') - ->willReturnOnConsecutiveCalls( - null, - null, - null, - $this->throwException(new TransportException()) - ); + ->willReturnCallback(function () use ($t2Matcher) { + if (4 === $t2Matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); + $t = new FailoverTransport([$t1, $t2], 6); $t->send(new RawMessage('')); // t1>fail - t2>sent $this->assertTransports($t, 0, [$t1]); @@ -115,16 +129,19 @@ public function testSendOneDeadAndRecoveryWithinRetryPeriod() public function testSendAllDeadWithinRetryPeriod() { $t1 = $this->createMock(TransportInterface::class); - $t1->method('send')->will($this->throwException(new TransportException())); + $t1->method('send')->willThrowException(new TransportException()); $t1->expects($this->once())->method('send'); $t2 = $this->createMock(TransportInterface::class); - $t2->expects($this->exactly(3)) + $matcher = $this->exactly(3); + $t2->expects($matcher) ->method('send') - ->willReturnOnConsecutiveCalls( - null, - null, - $this->throwException(new TransportException()) - ); + ->willReturnCallback(function () use ($matcher) { + if (3 === $matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); $t = new FailoverTransport([$t1, $t2], 40); $t->send(new RawMessage('')); sleep(4); @@ -137,15 +154,27 @@ public function testSendAllDeadWithinRetryPeriod() public function testSendOneDeadButRecover() { + $t1Matcher = $this->any(); $t1 = $this->createMock(TransportInterface::class); - $t1->method('send')->willReturnOnConsecutiveCalls($this->throwException(new TransportException())); + $t1->expects($t1Matcher)->method('send')->willReturnCallback(function () use ($t1Matcher) { + if (1 === $t1Matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); + $t2 = $this->createMock(TransportInterface::class); - $t2->expects($this->exactly(3)) - ->method('send')->willReturnOnConsecutiveCalls( - null, - null, - $this->throwException(new TransportException()) - ); + $matcher = $this->exactly(3); + $t2->expects($matcher) + ->method('send') + ->willReturnCallback(function () use ($matcher) { + if (3 === $matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); $t = new FailoverTransport([$t1, $t2], 1); $t->send(new RawMessage('')); sleep(1); diff --git a/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php index 08edb245a0df9..bac1ce152a8de 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php @@ -120,10 +120,18 @@ public function testSendOneDeadAndRecoveryWithinRetryPeriod() { $t1 = $this->createMock(TransportInterface::class); $t1->expects($this->exactly(3))->method('send'); + + $matcher = $this->exactly(2); $t2 = $this->createMock(TransportInterface::class); - $t2->expects($this->exactly(2)) + $t2->expects($matcher) ->method('send') - ->willReturnOnConsecutiveCalls($this->throwException(new TransportException())); + ->willReturnCallback(function () use ($matcher) { + if (1 === $matcher->getInvocationCount()) { + throw new TransportException(); + } + + return null; + }); $t = new RoundRobinTransport([$t1, $t2], 3); $p = new \ReflectionProperty($t, 'cursor'); $p->setAccessible(true); diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php index a3269841e4dda..80840c859cb05 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php @@ -31,7 +31,7 @@ public function testSend() $connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers']); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new AmazonSqsSender($connection, $serializer); $sender->send($envelope); @@ -49,7 +49,7 @@ public function testSendWithAmazonSqsFifoStamp() ->with($encoded['body'], $encoded['headers'], 0, $stamp->getMessageGroupId(), $stamp->getMessageDeduplicationId()); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new AmazonSqsSender($connection, $serializer); $sender->send($envelope); @@ -67,7 +67,7 @@ public function testSendWithAmazonSqsXrayTraceHeaderStamp() ->with($encoded['body'], $encoded['headers'], 0, null, null, $stamp->getTraceId()); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new AmazonSqsSender($connection, $serializer); $sender->send($envelope); diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpSenderTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpSenderTest.php index 9949a0d59413f..b1dda969fb49b 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpSenderTest.php @@ -31,7 +31,7 @@ public function testItSendsTheEncodedMessage() $encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class]]; $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('publish')->with($encoded['body'], $encoded['headers']); @@ -61,7 +61,7 @@ public function testItSendsTheEncodedMessageWithoutHeaders() $encoded = ['body' => '...']; $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('publish')->with($encoded['body'], []); @@ -76,7 +76,7 @@ public function testContentTypeHeaderIsMovedToAttribute() $encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class, 'Content-Type' => 'application/json']]; $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $connection = $this->createMock(Connection::class); unset($encoded['headers']['Content-Type']); @@ -93,7 +93,7 @@ public function testContentTypeHeaderDoesNotOverwriteAttribute() $encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class, 'Content-Type' => 'application/json']]; $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $connection = $this->createMock(Connection::class); unset($encoded['headers']['Content-Type']); @@ -110,7 +110,7 @@ public function testItThrowsATransportExceptionIfItCannotSendTheMessage() $encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class]]; $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $connection = $this->createMock(Connection::class); $connection->method('publish')->with($encoded['body'], $encoded['headers'])->willThrowException(new \AMQPException()); diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php index 32abfd58438be..9de6fa8ca0919 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php @@ -306,7 +306,10 @@ public function testItSetupsTheConnection() $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); $factory->method('createExchange')->willReturn($amqpExchange); - $factory->method('createQueue')->will($this->onConsecutiveCalls($amqpQueue0, $amqpQueue1)); + + $factory + ->method('createQueue') + ->willReturn($amqpQueue0, $amqpQueue1); $amqpExchange->expects($this->once())->method('declareExchange'); $amqpExchange->expects($this->once())->method('publish')->with('body', 'routing_key', \AMQP_NOPARAM, ['headers' => [], 'delivery_mode' => 2, 'timestamp' => time()]); @@ -358,7 +361,9 @@ public function testItSetupsTheTTLConnection() $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); $factory->method('createExchange')->willReturn($amqpExchange); - $factory->method('createQueue')->will($this->onConsecutiveCalls($amqpQueue0, $amqpQueue1)); + $factory + ->method('createQueue') + ->willReturn($amqpQueue0, $amqpQueue1); $amqpExchange->expects($this->once())->method('declareExchange'); $amqpExchange->expects($this->once())->method('publish')->with('body', 'routing_key', \AMQP_NOPARAM, ['headers' => [], 'delivery_mode' => 2, 'timestamp' => time()]); @@ -495,14 +500,15 @@ public function testAutoSetupWithDelayDeclaresExchangeQueuesAndDelay() $factory = $this->createMock(AmqpFactory::class); $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); - $factory->method('createQueue')->will($this->onConsecutiveCalls( - $amqpQueue = $this->createMock(\AMQPQueue::class), - $delayQueue = $this->createMock(\AMQPQueue::class) - )); - $factory->method('createExchange')->will($this->onConsecutiveCalls( - $amqpExchange = $this->createMock(\AMQPExchange::class), - $delayExchange = $this->createMock(\AMQPExchange::class) - )); + + $amqpQueue = $this->createMock(\AMQPQueue::class); + $factory + ->method('createQueue') + ->willReturn($amqpQueue, $this->createMock(\AMQPQueue::class)); + + $amqpExchange = $this->createMock(\AMQPExchange::class); + $delayExchange = $this->createMock(\AMQPExchange::class); + $factory->method('createExchange')->willReturn($amqpExchange, $delayExchange); $amqpExchange->expects($this->once())->method('setName')->with(self::DEFAULT_EXCHANGE_NAME); $amqpExchange->expects($this->once())->method('declareExchange'); @@ -553,14 +559,12 @@ public function testItDelaysTheMessageWithADifferentRoutingKeyAndTTLs() $factory = $this->createMock(AmqpFactory::class); $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); - $factory->method('createQueue')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPQueue::class), - $delayQueue = $this->createMock(\AMQPQueue::class) - )); - $factory->method('createExchange')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPExchange::class), - $delayExchange = $this->createMock(\AMQPExchange::class) - )); + + $delayQueue = $this->createMock(\AMQPQueue::class); + $factory->method('createQueue')->willReturn($this->createMock(\AMQPQueue::class), $delayQueue); + + $delayExchange = $this->createMock(\AMQPExchange::class); + $factory->method('createExchange')->willReturn($this->createMock(\AMQPExchange::class), $delayExchange); $connectionOptions = [ 'retry' => [ @@ -693,14 +697,12 @@ public function testItDelaysTheMessageWithTheInitialSuppliedRoutingKeyAsArgument $factory = $this->createMock(AmqpFactory::class); $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); - $factory->method('createQueue')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPQueue::class), - $delayQueue = $this->createMock(\AMQPQueue::class) - )); - $factory->method('createExchange')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPExchange::class), - $delayExchange = $this->createMock(\AMQPExchange::class) - )); + + $delayQueue = $this->createMock(\AMQPQueue::class); + $factory->method('createQueue')->willReturn($this->createMock(\AMQPQueue::class), $delayQueue); + + $delayExchange = $this->createMock(\AMQPExchange::class); + $factory->method('createExchange')->willReturn($this->createMock(\AMQPExchange::class), $delayExchange); $connectionOptions = [ 'retry' => [ @@ -819,14 +821,10 @@ private function createDelayOrRetryConnection(\AMQPExchange $delayExchange, stri $factory = $this->createMock(AmqpFactory::class); $factory->method('createConnection')->willReturn($amqpConnection); $factory->method('createChannel')->willReturn($amqpChannel); - $factory->method('createQueue')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPQueue::class), - $delayQueue = $this->createMock(\AMQPQueue::class) - )); - $factory->method('createExchange')->will($this->onConsecutiveCalls( - $this->createMock(\AMQPExchange::class), - $delayExchange - )); + + $delayQueue = $this->createMock(\AMQPQueue::class); + $factory->method('createQueue')->willReturn($this->createMock(\AMQPQueue::class), $delayQueue); + $factory->method('createExchange')->willReturn($this->createMock(\AMQPExchange::class), $delayExchange); $delayQueue->expects($this->once())->method('setName')->with($delayQueueName); $delayQueue->expects($this->once())->method('setArguments')->with([ diff --git a/src/Symfony/Component/Messenger/Bridge/Beanstalkd/Tests/Transport/BeanstalkdSenderTest.php b/src/Symfony/Component/Messenger/Bridge/Beanstalkd/Tests/Transport/BeanstalkdSenderTest.php index cfc5b8fdba84f..89ac3449f3a4b 100644 --- a/src/Symfony/Component/Messenger/Bridge/Beanstalkd/Tests/Transport/BeanstalkdSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Beanstalkd/Tests/Transport/BeanstalkdSenderTest.php @@ -30,7 +30,7 @@ public function testSend() $connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'], 0); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new BeanstalkdSender($connection, $serializer); $sender->send($envelope); @@ -45,7 +45,7 @@ public function testSendWithDelay() $connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'], 500); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new BeanstalkdSender($connection, $serializer); $sender->send($envelope); diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineSenderTest.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineSenderTest.php index 8505e3dee0481..1f769533e7165 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineSenderTest.php @@ -31,7 +31,7 @@ public function testSend() $connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'])->willReturn('15'); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new DoctrineSender($connection, $serializer); $actualEnvelope = $sender->send($envelope); @@ -51,7 +51,7 @@ public function testSendWithDelay() $connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'], 500); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new DoctrineSender($connection, $serializer); $sender->send($envelope); diff --git a/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php index 2e5c7bf0b043e..b1bff95fe4b67 100644 --- a/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php @@ -408,7 +408,7 @@ public function testLastErrorGetsCleared() $redis->expects($this->once())->method('xadd')->willReturn('0'); $redis->expects($this->once())->method('xack')->willReturn(0); - $redis->method('getLastError')->willReturnOnConsecutiveCalls('xadd error', 'xack error'); + $redis->method('getLastError')->willReturn('xadd error', 'xack error'); $redis->expects($this->exactly(2))->method('clearLastError'); $connection = Connection::fromDsn('redis://localhost/messenger-clearlasterror', ['auto_setup' => false, 'delete_after_ack' => true], $redis); diff --git a/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/RedisSenderTest.php b/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/RedisSenderTest.php index 3a4d817acc140..925a7292a7e3a 100644 --- a/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/RedisSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/RedisSenderTest.php @@ -29,7 +29,7 @@ public function testSend() $connection->expects($this->once())->method('add')->with($encoded['body'], $encoded['headers']); $serializer = $this->createMock(SerializerInterface::class); - $serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded); + $serializer->method('encode')->with($envelope)->willReturn($encoded); $sender = new RedisSender($connection, $serializer); $sender->send($envelope); diff --git a/src/Symfony/Component/Messenger/Tests/Command/SetupTransportsCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/SetupTransportsCommandTest.php index e0a57563915a4..0d1f1111b0b90 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/SetupTransportsCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/SetupTransportsCommandTest.php @@ -30,10 +30,10 @@ public function testReceiverNames() // get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport $serviceLocator->expects($this->exactly(2)) ->method('get') - ->will($this->onConsecutiveCalls( + ->willReturn( $this->createMock(SetupableTransportInterface::class), $this->createMock(TransportInterface::class) - )); + ); $serviceLocator ->method('has') ->willReturn(true); @@ -53,12 +53,10 @@ public function testReceiverNameArgument() /** @var MockObject&ServiceLocator $serviceLocator */ $serviceLocator = $this->createMock(ServiceLocator::class); // get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport - $serviceLocator->expects($this->exactly(1)) + $serviceLocator->expects($this->once()) ->method('get') - ->will($this->onConsecutiveCalls( - $this->createMock(SetupableTransportInterface::class) - )); - $serviceLocator->expects($this->exactly(1)) + ->willReturn($this->createMock(SetupableTransportInterface::class)); + $serviceLocator->expects($this->once()) ->method('has') ->willReturn(true); diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php index b0cc4c4f2ed87..cd65ab046f0c6 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Messenger\Tests\Middleware; +use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Constraint\Callback; use PHPUnit\Framework\MockObject\Stub\ReturnCallback; use PHPUnit\Framework\TestCase; @@ -67,12 +68,7 @@ public function testEventsInNewTransactionAreHandledAfterMainMessage() ->with($this->callback(function (Envelope $envelope) use (&$series) { return $envelope->getMessage() === array_shift($series); })) - ->willReturnOnConsecutiveCalls( - $this->willHandleMessage(), - $this->willHandleMessage(), - $this->willHandleMessage(), - $this->willHandleMessage() - ); + ->will($this->willHandleMessage()); $messageBus->dispatch($message); } @@ -110,16 +106,19 @@ public function testThrowingEventsHandlingWontStopExecution() $secondEvent, ]; - $handlingMiddleware->expects($this->exactly(3)) + $matcher = $this->exactly(3); + $handlingMiddleware->expects($matcher) ->method('handle') ->with($this->callback(function (Envelope $envelope) use (&$series) { return $envelope->getMessage() === array_shift($series); })) - ->willReturnOnConsecutiveCalls( - $this->willHandleMessage(), - $this->throwException(new \RuntimeException('Some exception while handling first event')), - $this->willHandleMessage() - ); + ->willReturnCallback(function ($envelope, StackInterface $stack) use ($matcher) { + if (2 === $matcher->getInvocationCount()) { + throw new \RuntimeException('Some exception while handling first event'); + } + + return $stack->next()->handle($envelope, $stack); + }); $this->expectException(DelayedMessageHandlingException::class); $this->expectExceptionMessage('RuntimeException: Some exception while handling first event'); @@ -176,34 +175,39 @@ public function testLongChainWithExceptions() // Note: $eventL3a should not be handled. ]; - $handlingMiddleware->expects($this->exactly(7)) + $matcher = $this->exactly(7); + $handlingMiddleware->expects($matcher) ->method('handle') ->with($this->callback(function (Envelope $envelope) use (&$series) { return $envelope->getMessage() === array_shift($series); })) - ->willReturnOnConsecutiveCalls( - $this->willHandleMessage(), - $this->willHandleMessage(), - $this->returnCallback(function ($envelope, StackInterface $stack) use ($eventBus, $eventL2a, $eventL2b) { - $envelope1 = new Envelope($eventL2a, [new DispatchAfterCurrentBusStamp()]); - $eventBus->dispatch($envelope1); - $eventBus->dispatch(new Envelope($eventL2b, [new DispatchAfterCurrentBusStamp()])); - - return $stack->next()->handle($envelope, $stack); - }), - $this->willHandleMessage(), - $this->returnCallback(function () use ($eventBus, $eventL3a) { - $eventBus->dispatch(new Envelope($eventL3a, [new DispatchAfterCurrentBusStamp()])); - - throw new \RuntimeException('Some exception while handling Event level 2a'); - }), - $this->returnCallback(function ($envelope, StackInterface $stack) use ($eventBus, $eventL3b) { - $eventBus->dispatch(new Envelope($eventL3b, [new DispatchAfterCurrentBusStamp()])); - - return $stack->next()->handle($envelope, $stack); - }), - $this->willHandleMessage() - ); + ->willReturnCallback(function ($envelope, StackInterface $stack) use ($eventBus, $eventL2a, $eventL2b, $eventL3a, $eventL3b, $matcher) { + switch ($matcher->getInvocationCount()) { + case 1: + case 2: + case 4: + case 7: + return $stack->next()->handle($envelope, $stack); + + case 3: + $envelope1 = new Envelope($eventL2a, [new DispatchAfterCurrentBusStamp()]); + $eventBus->dispatch($envelope1); + $eventBus->dispatch(new Envelope($eventL2b, [new DispatchAfterCurrentBusStamp()])); + + return $stack->next()->handle($envelope, $stack); + + case 5: + $eventBus->dispatch(new Envelope($eventL3a, [new DispatchAfterCurrentBusStamp()])); + + throw new \RuntimeException('Some exception while handling Event level 2a'); + case 6: + $eventBus->dispatch(new Envelope($eventL3b, [new DispatchAfterCurrentBusStamp()])); + + return $stack->next()->handle($envelope, $stack); + } + + throw new AssertionFailedError('Unexpected call to handle'); + }); $this->expectException(DelayedMessageHandlingException::class); $this->expectExceptionMessage('RuntimeException: Some exception while handling Event level 2a'); diff --git a/src/Symfony/Component/Notifier/Tests/Transport/FailoverTransportTest.php b/src/Symfony/Component/Notifier/Tests/Transport/FailoverTransportTest.php index 2b48c20e20ff0..07d4720459b4d 100644 --- a/src/Symfony/Component/Notifier/Tests/Transport/FailoverTransportTest.php +++ b/src/Symfony/Component/Notifier/Tests/Transport/FailoverTransportTest.php @@ -121,13 +121,17 @@ public function testSendAllDeadWithinRetryPeriod() $t1->expects($this->once())->method('send'); $t2 = $this->createMock(TransportInterface::class); $t2->method('supports')->with($message)->willReturn(true); - $t2->expects($this->exactly(3)) + + $matcher = $this->exactly(3); + $t2->expects($matcher) ->method('send') - ->willReturnOnConsecutiveCalls( - new SentMessage($message, 't2'), - new SentMessage($message, 't2'), - $this->throwException($this->createMock(TransportExceptionInterface::class)) - ); + ->willReturnCallback(function () use ($matcher, $message) { + if (3 === $matcher->getInvocationCount()) { + throw $this->createMock(TransportExceptionInterface::class); + } + + return new SentMessage($message, 't2'); + }); $t = new FailoverTransport([$t1, $t2], 40); $t->send($message); sleep(4); @@ -146,16 +150,27 @@ public function testSendOneDeadButRecover() $t1 = $this->createMock(TransportInterface::class); $t1->method('supports')->with($message)->willReturn(true); - $t1->expects($this->exactly(2))->method('send')->willReturnOnConsecutiveCalls( - $this->throwException($this->createMock(TransportExceptionInterface::class)), - new SentMessage($message, 't1') - ); + + $t1Matcher = $this->exactly(2); + $t1->expects($t1Matcher)->method('send') + ->willReturnCallback(function () use ($t1Matcher, $message) { + if (1 === $t1Matcher->getInvocationCount()) { + throw $this->createMock(TransportExceptionInterface::class); + } + + return new SentMessage($message, 't1'); + }); $t2 = $this->createMock(TransportInterface::class); $t2->method('supports')->with($message)->willReturn(true); - $t2->expects($this->exactly(2))->method('send')->willReturnOnConsecutiveCalls( - new SentMessage($message, 't2'), - $this->throwException($this->createMock(TransportExceptionInterface::class)) - ); + + $t2Matcher = $this->exactly(2); + $t2->expects($t2Matcher)->method('send')->willReturnCallback(function () use ($t2Matcher, $message) { + if (1 === $t2Matcher->getInvocationCount()) { + return new SentMessage($message, 't1'); + } + + throw $this->createMock(TransportExceptionInterface::class); + }); $t = new FailoverTransport([$t1, $t2], 1); diff --git a/src/Symfony/Component/PasswordHasher/Tests/Hasher/UserPasswordHasherTest.php b/src/Symfony/Component/PasswordHasher/Tests/Hasher/UserPasswordHasherTest.php index 32805b1917ec7..c8f057cf85ec2 100644 --- a/src/Symfony/Component/PasswordHasher/Tests/Hasher/UserPasswordHasherTest.php +++ b/src/Symfony/Component/PasswordHasher/Tests/Hasher/UserPasswordHasherTest.php @@ -154,7 +154,7 @@ public function testNeedsRehash() $mockPasswordHasherFactory->expects($this->any()) ->method('getPasswordHasher') ->with($user) - ->will($this->onConsecutiveCalls($hasher, $hasher, new NativePasswordHasher(5, 20000, 5), $hasher)); + ->willReturn($hasher, $hasher, new NativePasswordHasher(5, 20000, 5), $hasher); $passwordHasher = new UserPasswordHasher($mockPasswordHasherFactory); diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/UserPasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/UserPasswordEncoderTest.php index 6f52fbf1b22d9..9fca415024e12 100644 --- a/src/Symfony/Component/Security/Core/Tests/Encoder/UserPasswordEncoderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/UserPasswordEncoderTest.php @@ -86,7 +86,7 @@ public function testNeedsRehash() $mockEncoderFactory->expects($this->any()) ->method('getEncoder') ->with($user) - ->will($this->onConsecutiveCalls($encoder, $encoder, new NativePasswordEncoder(5, 20000, 5), $encoder)); + ->willReturn($encoder, $encoder, new NativePasswordEncoder(5, 20000, 5), $encoder); $passwordEncoder = new UserPasswordEncoder($mockEncoderFactory); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 2ca7d79fef075..a6477e97ad331 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -172,10 +172,10 @@ private function getDenormalizerForDummyCollection() { $extractor = $this->createMock(PhpDocExtractor::class); $extractor->method('getTypes') - ->will($this->onConsecutiveCalls( + ->willReturn( [new Type('array', false, null, true, new Type('int'), new Type('object', false, DummyChild::class))], null - )); + ); $denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor); $arrayDenormalizer = new ArrayDenormalizerDummy(); @@ -227,10 +227,10 @@ private function getDenormalizerForStringCollection() { $extractor = $this->createMock(PhpDocExtractor::class); $extractor->method('getTypes') - ->will($this->onConsecutiveCalls( + ->willReturn( [new Type('array', false, null, true, new Type('int'), new Type('string'))], null - )); + ); $denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor); $arrayDenormalizer = new ArrayDenormalizerDummy(); @@ -417,7 +417,7 @@ private function getDenormalizerForObjectWithBasicProperties() { $extractor = $this->createMock(PhpDocExtractor::class); $extractor->method('getTypes') - ->will($this->onConsecutiveCalls( + ->willReturn( [new Type('bool')], [new Type('bool')], [new Type('bool')], @@ -430,7 +430,7 @@ private function getDenormalizerForObjectWithBasicProperties() [new Type('float')], [new Type('float')], [new Type('float')] - )); + ); $denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor); $arrayDenormalizer = new ArrayDenormalizerDummy(); @@ -663,8 +663,7 @@ protected function createChildContext(array $parentContext, string $attribute, ? public function testDenormalizeXmlScalar() { - $normalizer = new class () extends AbstractObjectNormalizer - { + $normalizer = new class() extends AbstractObjectNormalizer { public function __construct() { parent::__construct(null, new MetadataAwareNameConverter(new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())))); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index ee0f5fb97e60b..ab43246fe7f65 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -54,9 +54,10 @@ public function testLoadClassMetadata() 'noAutoMapping', ]) ; + $propertyInfoStub ->method('getTypes') - ->will($this->onConsecutiveCalls( + ->willReturn( [new Type(Type::BUILTIN_TYPE_STRING, true)], [new Type(Type::BUILTIN_TYPE_STRING)], [new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_BOOL)], @@ -69,11 +70,12 @@ public function testLoadClassMetadata() [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true, null, new Type(Type::BUILTIN_TYPE_FLOAT))], [new Type(Type::BUILTIN_TYPE_STRING)], [new Type(Type::BUILTIN_TYPE_STRING)] - )) + ) ; + $propertyInfoStub ->method('isWritable') - ->will($this->onConsecutiveCalls( + ->willReturn( true, true, true, @@ -86,7 +88,7 @@ public function testLoadClassMetadata() true, false, true - )) + ) ; $propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, '{.*}'); @@ -222,9 +224,10 @@ public function testClassNoAutoMapping() ->method('getProperties') ->willReturn(['string', 'autoMappingExplicitlyEnabled']) ; + $propertyInfoStub ->method('getTypes') - ->willReturnOnConsecutiveCalls( + ->willReturn( [new Type(Type::BUILTIN_TYPE_STRING)], [new Type(Type::BUILTIN_TYPE_BOOL)] ); From 03c61315498c4633adf7e9448d4f0507814ce8f5 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 30 Apr 2024 11:14:43 +0200 Subject: [PATCH 14/90] move Process component dep to require-dev --- src/Symfony/Component/Filesystem/composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 95e9f3f035ee8..5811ef5907e44 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -19,7 +19,9 @@ "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { "symfony/process": "^5.4|^6.4" }, "autoload": { From e107d3b09902522a05557017eb9be5dad303f2aa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 30 Apr 2024 11:32:08 +0200 Subject: [PATCH 15/90] fix merge --- src/Symfony/Component/Dotenv/Command/DebugCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Dotenv/Command/DebugCommand.php b/src/Symfony/Component/Dotenv/Command/DebugCommand.php index c9d3b0c235fec..46ea027fd4e63 100644 --- a/src/Symfony/Component/Dotenv/Command/DebugCommand.php +++ b/src/Symfony/Component/Dotenv/Command/DebugCommand.php @@ -128,7 +128,7 @@ private function getVariables(array $envFiles, ?string $nameFilter): array continue; } - $realValue = $_SERVER[$var]; + $realValue = $_SERVER[$var] ?? ''; $varDetails = [$var, ''.OutputFormatter::escape($realValue).'']; $varSeen = !isset($dotenvVars[$var]); From 26f8a8bc059087581836a622bf7046b91a95e4fa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 30 Apr 2024 11:47:28 +0200 Subject: [PATCH 16/90] restore deprecated properties --- .../Component/Dotenv/Command/DebugCommand.php | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Command/DebugCommand.php b/src/Symfony/Component/Dotenv/Command/DebugCommand.php index 46ea027fd4e63..d0c2723b16181 100644 --- a/src/Symfony/Component/Dotenv/Command/DebugCommand.php +++ b/src/Symfony/Component/Dotenv/Command/DebugCommand.php @@ -30,10 +30,24 @@ #[AsCommand(name: 'debug:dotenv', description: 'List all dotenv files with variables and values')] final class DebugCommand extends Command { - public function __construct( - private string $kernelEnvironment, - private string $projectDirectory, - ) { + /** + * @deprecated since Symfony 6.1 + */ + protected static $defaultName = 'debug:dotenv'; + + /** + * @deprecated since Symfony 6.1 + */ + protected static $defaultDescription = 'List all dotenv files with variables and values'; + + private string $kernelEnvironment; + private string $projectDirectory; + + public function __construct(string $kernelEnvironment, string $projectDirectory) + { + $this->kernelEnvironment = $kernelEnvironment; + $this->projectDirectory = $projectDirectory; + parent::__construct(); } From 518bc283a0793868584d1624900d8c8752839c6c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 30 Apr 2024 15:47:22 +0200 Subject: [PATCH 17/90] move wiring of the property info extractor to the ObjectNormalizer The PropertyNormalizer does not handle a property info extractor. It looks like the argument was accidentally added to instead of the ObjectNormalizer in #52917. --- .../DependencyInjection/FrameworkExtension.php | 13 +++++++------ .../FrameworkBundle/Resources/config/serializer.php | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 731c6e7ee4b3e..f7ab7e3ed5835 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1854,18 +1854,19 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->setParameter('serializer.default_context', $defaultContext); } + $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); + $context = []; + if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { - $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; + $context += ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); - $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); } if ($config['max_depth_handler'] ?? false) { - $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? $defaultContext) + ['max_depth_handler' => new Reference($config['max_depth_handler'])]; - $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); + $context += ($arguments[6] ?? $defaultContext) + ['max_depth_handler' => new Reference($config['max_depth_handler'])]; } + + $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); } private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index 63964f34f5599..7762e5a64ca86 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -125,6 +125,8 @@ service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, + null, + service('property_info')->ignoreOnInvalid(), ]) ->tag('serializer.normalizer', ['priority' => -1000]) @@ -138,7 +140,6 @@ service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, [], - service('property_info')->ignoreOnInvalid(), ]) ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') From 18e06a8e2b3efb8b4e9caa19163e6bd96ef34d68 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 29 Apr 2024 11:20:22 +0200 Subject: [PATCH 18/90] handle union and intersection types for cascaded validations --- .../Validator/Mapping/ClassMetadata.php | 31 +++++++++++++++- .../Fixtures/CascadingEntityIntersection.php | 17 +++++++++ .../Tests/Fixtures/CascadingEntityUnion.php | 25 +++++++++++++ .../Tests/Mapping/ClassMetadataTest.php | 36 +++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityIntersection.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityUnion.php diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index a7209d5377d85..957000274b2f3 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -210,7 +210,7 @@ public function addConstraint(Constraint $constraint) $this->cascadingStrategy = CascadingStrategy::CASCADE; foreach ($this->getReflectionClass()->getProperties() as $property) { - if ($property->hasType() && (('array' === $type = $property->getType()->getName()) || class_exists($type))) { + if ($this->canCascade($property->getType())) { $this->addPropertyConstraint($property->getName(), new Valid()); } } @@ -511,4 +511,33 @@ private function checkConstraint(Constraint $constraint) } } } + + private function canCascade(?\ReflectionType $type = null): bool + { + if (null === $type) { + return false; + } + + if ($type instanceof \ReflectionIntersectionType) { + foreach ($type->getTypes() as $nestedType) { + if ($this->canCascade($nestedType)) { + return true; + } + } + + return false; + } + + if ($type instanceof \ReflectionUnionType) { + foreach ($type->getTypes() as $nestedType) { + if (!$this->canCascade($nestedType)) { + return false; + } + } + + return true; + } + + return $type instanceof \ReflectionNamedType && (\in_array($type->getName(), ['array', 'null'], true) || class_exists($type->getName())); + } } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityIntersection.php b/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityIntersection.php new file mode 100644 index 0000000000000..9478f647c4b5d --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityIntersection.php @@ -0,0 +1,17 @@ + + * + * 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 CascadingEntityIntersection +{ + public CascadedChild&\stdClass $classes; +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityUnion.php b/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityUnion.php new file mode 100644 index 0000000000000..03c808fca330f --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/CascadingEntityUnion.php @@ -0,0 +1,25 @@ + + * + * 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 CascadingEntityUnion +{ + public CascadedChild|\stdClass $classes; + public CascadedChild|array $classAndArray; + public CascadedChild|null $classAndNull; + public array|null $arrayAndNull; + public CascadedChild|array|null $classAndArrayAndNull; + public int|string $scalars; + public int|null $scalarAndNull; + public CascadedChild|int $classAndScalar; + public array|int $arrayAndScalar; +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index a9f942319af83..4e0bca845a2cb 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -25,6 +25,8 @@ use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; +use Symfony\Component\Validator\Tests\Fixtures\CascadingEntityIntersection; +use Symfony\Component\Validator\Tests\Fixtures\CascadingEntityUnion; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; @@ -361,6 +363,40 @@ public function testCascadeConstraint() 'children', ], $metadata->getConstrainedProperties()); } + + /** + * @requires PHP 8.0 + */ + public function testCascadeConstraintWithUnionTypeProperties() + { + $metadata = new ClassMetadata(CascadingEntityUnion::class); + $metadata->addConstraint(new Cascade()); + + $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); + $this->assertCount(5, $metadata->properties); + $this->assertSame([ + 'classes', + 'classAndArray', + 'classAndNull', + 'arrayAndNull', + 'classAndArrayAndNull', + ], $metadata->getConstrainedProperties()); + } + + /** + * @requires PHP 8.1 + */ + public function testCascadeConstraintWithIntersectionTypeProperties() + { + $metadata = new ClassMetadata(CascadingEntityIntersection::class); + $metadata->addConstraint(new Cascade()); + + $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); + $this->assertCount(1, $metadata->properties); + $this->assertSame([ + 'classes', + ], $metadata->getConstrainedProperties()); + } } class ClassCompositeConstraint extends Composite From d1c0fb64c684adc8df9492acd396e37f6ad18f5a Mon Sep 17 00:00:00 2001 From: Tim Porter Date: Tue, 30 Apr 2024 23:58:54 +0100 Subject: [PATCH 19/90] [Strings][EnglishInflector] Fix incorrect pluralisation of 'Album' --- src/Symfony/Component/String/Inflector/EnglishInflector.php | 3 +++ .../Component/String/Tests/Inflector/EnglishInflectorTest.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/Symfony/Component/String/Inflector/EnglishInflector.php b/src/Symfony/Component/String/Inflector/EnglishInflector.php index 60eace3c9b283..d9eff19b9a950 100644 --- a/src/Symfony/Component/String/Inflector/EnglishInflector.php +++ b/src/Symfony/Component/String/Inflector/EnglishInflector.php @@ -238,6 +238,9 @@ final class EnglishInflector implements InflectorInterface // teeth (tooth) ['htoot', 5, true, true, 'teeth'], + // albums (album) + ['mubla', 5, true, true, 'albums'], + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['mu', 2, true, true, 'a'], diff --git a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php index 51849fd42540a..ba8d6d797c4d0 100644 --- a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php +++ b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php @@ -24,6 +24,7 @@ public static function singularizeProvider() ['accesses', 'access'], ['addresses', 'address'], ['agendas', 'agenda'], + ['albums', 'album'], ['alumnae', 'alumna'], ['alumni', 'alumnus'], ['analyses', ['analys', 'analyse', 'analysis']], @@ -179,6 +180,7 @@ public static function pluralizeProvider() ['address', 'addresses'], ['agenda', 'agendas'], ['aircraft', 'aircraft'], + ['album', 'albums'], ['alumnus', 'alumni'], ['analysis', 'analyses'], ['antenna', 'antennas'], // antennae From ca9f2a521a21ec918dfb3b1aa60cdb271edaa872 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Wed, 1 May 2024 22:12:44 +0200 Subject: [PATCH 20/90] [PhpUnitBridge] Fix `DeprecationErrorHandler` with PhpUnit 10 --- src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index adddfe6f76995..05c67b7b37e6e 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -368,6 +368,12 @@ private static function getPhpUnitErrorHandler() if ('PHPUnit\Util\ErrorHandler::handleError' === $eh) { return $eh; + } elseif (ErrorHandler::class === $eh) { + return function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) { + ErrorHandler::instance()($errorNumber, $errorString, $errorFile, $errorLine); + + return true; + }; } foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { From a4190b569225daeff4dba146ea4c6e7c9f04ce4f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 2 May 2024 09:44:03 +0200 Subject: [PATCH 21/90] fix compatibility with Twig 3.10 --- .../Tests/Twig/WebProfilerExtensionTest.php | 12 ++---------- .../WebProfilerBundle/Twig/WebProfilerExtension.php | 7 +++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Twig/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Twig/WebProfilerExtensionTest.php index 37438ed560206..f0cf4f36a196f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Twig/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Twig/WebProfilerExtensionTest.php @@ -15,6 +15,7 @@ use Symfony\Bundle\WebProfilerBundle\Twig\WebProfilerExtension; use Symfony\Component\VarDumper\Cloner\VarCloner; use Twig\Environment; +use Twig\Loader\ArrayLoader; class WebProfilerExtensionTest extends TestCase { @@ -23,7 +24,7 @@ class WebProfilerExtensionTest extends TestCase */ public function testDumpHeaderIsDisplayed(string $message, array $context, bool $dump1HasHeader, bool $dump2HasHeader) { - $twigEnvironment = $this->mockTwigEnvironment(); + $twigEnvironment = new Environment(new ArrayLoader()); $varCloner = new VarCloner(); $webProfilerExtension = new WebProfilerExtension(); @@ -44,13 +45,4 @@ public static function provideMessages(): iterable yield ['Some message {foo}', ['foo' => 'foo', 'bar' => 'bar'], true, false]; yield ['Some message {foo}', ['bar' => 'bar'], false, true]; } - - private function mockTwigEnvironment() - { - $twigEnvironment = $this->createMock(Environment::class); - - $twigEnvironment->expects($this->any())->method('getCharset')->willReturn('UTF-8'); - - return $twigEnvironment; - } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php index 2a4e975760426..82352f5996122 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php @@ -17,6 +17,7 @@ use Twig\Extension\EscaperExtension; use Twig\Extension\ProfilerExtension; use Twig\Profiler\Profile; +use Twig\Runtime\EscaperRuntime; use Twig\TwigFunction; /** @@ -114,6 +115,12 @@ public function getName() private static function escape(Environment $env, string $s): string { + // Twig 3.10 and above + if (class_exists(EscaperRuntime::class)) { + return $env->getRuntime(EscaperRuntime::class)->escape($s); + } + + // Twig 3.9 if (method_exists(EscaperExtension::class, 'escape')) { return EscaperExtension::escape($env, $s); } From 5cde2b50fe44f5323ae9da5a5f67f8e9f36c08ba Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 2 May 2024 10:47:54 +0200 Subject: [PATCH 22/90] [Filesystem] Run high-deps tests with Process 7 --- src/Symfony/Component/Filesystem/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 6a8671b8d9da7..fd75755b2b14a 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -21,7 +21,7 @@ "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4" + "symfony/process": "^5.4|^6.4|^7.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, From f77f78ebb5090a9c24fd38d55047baeb60fd89fb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 2 May 2024 10:49:46 +0200 Subject: [PATCH 23/90] add missing assertion --- .../Component/Serializer/Tests/Encoder/CsvEncoderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index 3d2163c06e923..9b1bbfb281672 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -223,8 +223,8 @@ public function testDecodeEmptyData() public function testMultipleEmptyHeaderNamesWithSeparator() { - $this->encoder->decode(',. -,', 'csv'); + $this->assertSame([['', [1 => '']]], $this->encoder->decode(',. +,', 'csv')); } public function testEncodeVariableStructure() From 64f020f6385adbc5bc45475e46d5d82d122c3bf9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 2 May 2024 11:21:14 +0200 Subject: [PATCH 24/90] separate the property info and write info extractors --- .../Serializer/Normalizer/ObjectNormalizer.php | 13 +++++++++++-- .../Tests/Normalizer/ObjectNormalizerTest.php | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index a1ab11177482e..6a5413f69d317 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -36,6 +36,7 @@ class ObjectNormalizer extends AbstractObjectNormalizer protected $propertyAccessor; protected $propertyInfoExtractor; + private $writeInfoExtractor; private $objectClassResolver; @@ -54,6 +55,7 @@ public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory }; $this->propertyInfoExtractor = $propertyInfoExtractor ?: new ReflectionExtractor(); + $this->writeInfoExtractor = new ReflectionExtractor(); } /** @@ -195,8 +197,15 @@ protected function isAllowedAttribute($classOrObject, string $attribute, ?string return $this->propertyInfoExtractor->isReadable($class, $attribute) || $this->hasAttributeAccessorMethod($class, $attribute); } - return $this->propertyInfoExtractor->isWritable($class, $attribute) - || ($writeInfo = $this->propertyInfoExtractor->getWriteInfo($class, $attribute)) && PropertyWriteInfo::TYPE_NONE !== $writeInfo->getType(); + if ($this->propertyInfoExtractor->isWritable($class, $attribute)) { + return true; + } + + if (($writeInfo = $this->writeInfoExtractor->getWriteInfo($class, $attribute)) && PropertyWriteInfo::TYPE_NONE !== $writeInfo->getType()) { + return true; + } + + return false; } private function hasAttributeAccessorMethod(string $class, string $attribute): bool diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 830817b8b673b..5f88844974cd9 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -274,6 +274,22 @@ public function testConstructorWithObjectDenormalize() $this->assertEquals('bar', $obj->bar); } + public function testConstructorWithObjectDenormalizeUsingPropertyInfoExtractor() + { + $serializer = $this->createMock(ObjectSerializerNormalizer::class); + $normalizer = new ObjectNormalizer(null, null, null, null, null, null, [], new PropertyInfoExtractor()); + $normalizer->setSerializer($serializer); + + $data = new \stdClass(); + $data->foo = 'foo'; + $data->bar = 'bar'; + $data->baz = true; + $data->fooBar = 'foobar'; + $obj = $normalizer->denormalize($data, ObjectConstructorDummy::class, 'any'); + $this->assertEquals('foo', $obj->getFoo()); + $this->assertEquals('bar', $obj->bar); + } + public function testConstructorWithObjectTypeHintDenormalize() { $data = [ From 5ab2d9053f7f3fc21d91342e0b33af2ca3b8bed4 Mon Sep 17 00:00:00 2001 From: mfettig Date: Fri, 24 Mar 2023 15:07:33 -0400 Subject: [PATCH 25/90] [Cache] Fix support for predis/predis:^2.0 --- composer.json | 2 +- src/Symfony/Component/Cache/Traits/RedisTrait.php | 10 ++++++---- src/Symfony/Component/Cache/composer.json | 2 +- .../Handler/PredisClusterSessionHandlerTest.php | 5 ++++- src/Symfony/Component/HttpFoundation/composer.json | 2 +- src/Symfony/Component/Lock/composer.json | 2 +- src/Symfony/Component/Semaphore/composer.json | 2 +- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 9bc012d6cee49..ba4ebe8ed6dff 100644 --- a/composer.json +++ b/composer.json @@ -138,7 +138,7 @@ "php-http/httplug": "^1.0|^2.0", "php-http/message-factory": "^1.0", "phpstan/phpdoc-parser": "^1.0", - "predis/predis": "~1.1", + "predis/predis": "^1.1|^2.0", "psr/http-client": "^1.0", "psr/simple-cache": "^1.0|^2.0", "egulias/email-validator": "^2.1.10|^3.1|^4", diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 33f37d828ea81..518a563060240 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -15,6 +15,8 @@ use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\RedisCluster; use Predis\Connection\Aggregate\ReplicationInterface; +use Predis\Connection\Cluster\ClusterInterface as Predis2ClusterInterface; +use Predis\Connection\Cluster\RedisCluster as Predis2RedisCluster; use Predis\Response\ErrorInterface; use Predis\Response\Status; use Symfony\Component\Cache\Exception\CacheException; @@ -414,7 +416,7 @@ protected function doFetch(array $ids) $result = []; - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { + if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'get' => [$id]; @@ -511,7 +513,7 @@ protected function doDelete(array $ids) return true; } - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { + if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { static $del; $del = $del ?? (class_exists(UNLINK::class) ? 'unlink' : 'del'); @@ -569,7 +571,7 @@ private function pipeline(\Closure $generator, ?object $redis = null): \Generato $ids = []; $redis = $redis ?? $this->redis; - if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { + if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && ($redis->getConnection() instanceof RedisCluster || $redis->getConnection() instanceof Predis2RedisCluster))) { // phpredis & predis don't support pipelining with RedisCluster // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 @@ -631,7 +633,7 @@ private function getHosts(): array $hosts = [$this->redis]; if ($this->redis instanceof \Predis\ClientInterface) { $connection = $this->redis->getConnection(); - if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { + if (($connection instanceof ClusterInterface || $connection instanceof Predis2ClusterInterface) && $connection instanceof \Traversable) { $hosts = []; foreach ($connection as $c) { $hosts[] = new \Predis\Client($c); diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index e3526bb8158b4..fdf794fb3b368 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -35,7 +35,7 @@ "cache/integration-tests": "dev-master", "doctrine/cache": "^1.6|^2.0", "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1", + "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php index 4990b1a1fc091..1712dcc491fc6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php @@ -23,6 +23,9 @@ class PredisClusterSessionHandlerTest extends AbstractRedisSessionHandlerTestCas */ protected function createRedisClient(string $host): object { - return new Client([array_combine(['host', 'port'], explode(':', getenv('REDIS_HOST')) + [1 => 6379])]); + return new Client( + [array_combine(['host', 'port'], explode(':', getenv('REDIS_HOST')) + [1 => 6379])], + ['cluster' => 'redis'] + ); } } diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index cb8d59ffed0d5..a2e43a99cfaae 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -22,7 +22,7 @@ "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "predis/predis": "~1.0", + "predis/predis": "^1.0|^2.0", "symfony/cache": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json index b7e2d0c0d87ea..f2558dbb7459a 100644 --- a/src/Symfony/Component/Lock/composer.json +++ b/src/Symfony/Component/Lock/composer.json @@ -23,7 +23,7 @@ }, "require-dev": { "doctrine/dbal": "^2.13|^3|^4", - "predis/predis": "~1.0" + "predis/predis": "^1.0|^2.0" }, "conflict": { "doctrine/dbal": "<2.13" diff --git a/src/Symfony/Component/Semaphore/composer.json b/src/Symfony/Component/Semaphore/composer.json index cbbd11c7ffcb4..3927cb71d964d 100644 --- a/src/Symfony/Component/Semaphore/composer.json +++ b/src/Symfony/Component/Semaphore/composer.json @@ -24,7 +24,7 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "predis/predis": "~1.0" + "predis/predis": "^1.1|^2.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Semaphore\\": "" }, From a6fe93c707f2c7fa2fe0139e2ba8abbc00d3cac4 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 2 May 2024 13:02:31 +0200 Subject: [PATCH 26/90] Fix various warnings across components test suite --- .../Tests/Functional/AbstractWebTestCase.php | 2 +- ...ContainerParametersResourceCheckerTest.php | 8 ++-- .../Tests/Loader/PhpFileLoaderTest.php | 2 + .../Dumper/CompiledUrlGeneratorDumperTest.php | 2 + .../Features/CallbacksTestTrait.php | 48 +++++++++---------- .../Features/CircularReferenceTestTrait.php | 2 +- .../SkipUninitializedValuesTestTrait.php | 2 +- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php index f9363e8290dc0..51d4d781fc233 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php @@ -33,7 +33,7 @@ public static function tearDownAfterClass(): void static::deleteTmpDir(); } - public function provideSecuritySystems() + public static function provideSecuritySystems() { yield [['enable_authenticator_manager' => true]]; yield [['enable_authenticator_manager' => false]]; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php b/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php index f13acc8f140e2..a5efc89a7c710 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php @@ -46,7 +46,7 @@ public function testSupports() */ public function testIsFresh(callable $mockContainer, $expected) { - $mockContainer($this->container); + $mockContainer($this->container, $this); $this->assertSame($expected, $this->resourceChecker->isFresh($this->resource, time())); } @@ -61,9 +61,9 @@ public static function isFreshProvider() $container->method('getParameter')->with('locales')->willReturn(['nl', 'es']); }, false]; - yield 'fresh on every identical parameters' => [function (MockObject $container) { - $container->expects(self::exactly(2))->method('hasParameter')->willReturn(true); - $container->expects(self::exactly(2))->method('getParameter') + yield 'fresh on every identical parameters' => [function (MockObject $container, TestCase $testCase) { + $container->expects($testCase->exactly(2))->method('hasParameter')->willReturn(true); + $container->expects($testCase->exactly(2))->method('getParameter') ->willReturnCallback(function (...$args) { static $series = [ [['locales'], ['fr', 'en']], diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index 8b141d2577ee3..6f15b22b95cab 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -194,6 +194,8 @@ public function testNestedBundleConfigNotAllowed() */ public function testWhenEnv() { + $this->expectNotToPerformAssertions(); + $fixtures = realpath(__DIR__.'/../Fixtures'); $container = new ContainerBuilder(); $loader = new PhpFileLoader($container, new FileLocator(), 'dev', new ConfigBuilderGenerator(sys_get_temp_dir())); diff --git a/src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php b/src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php index 64e47438386d4..ef3061db7b9ec 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php @@ -63,10 +63,12 @@ protected function tearDown(): void parent::tearDown(); @unlink($this->testTmpFilepath); + @unlink($this->largeTestTmpFilepath); $this->routeCollection = null; $this->generatorDumper = null; $this->testTmpFilepath = null; + $this->largeTestTmpFilepath = null; } public function testDumpWithRoutes() diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php index db7b226c3e14b..e573c8c227001 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php @@ -126,13 +126,13 @@ public function testUncallableCallbacks($callbacks) $normalizer->normalize($obj, null, ['callbacks' => $callbacks]); } - public function provideNormalizeCallbacks() + public static function provideNormalizeCallbacks() { return [ 'Change a string' => [ [ 'bar' => function ($bar) { - $this->assertEquals('baz', $bar); + static::assertEquals('baz', $bar); return 'baz'; }, @@ -143,11 +143,11 @@ public function provideNormalizeCallbacks() 'Null an item' => [ [ 'bar' => function ($value, $object, $attributeName, $format, $context) { - $this->assertSame('baz', $value); - $this->assertInstanceOf(CallbacksObject::class, $object); - $this->assertSame('bar', $attributeName); - $this->assertSame('any', $format); - $this->assertArrayHasKey('circular_reference_limit_counters', $context); + static::assertSame('baz', $value); + static::assertInstanceOf(CallbacksObject::class, $object); + static::assertSame('bar', $attributeName); + static::assertSame('any', $format); + static::assertArrayHasKey('circular_reference_limit_counters', $context); }, ], 'baz', @@ -156,7 +156,7 @@ public function provideNormalizeCallbacks() 'Format a date' => [ [ 'bar' => function ($bar) { - $this->assertInstanceOf(\DateTime::class, $bar); + static::assertInstanceOf(\DateTime::class, $bar); return $bar->format('d-m-Y H:i:s'); }, @@ -190,13 +190,13 @@ public function provideNormalizeCallbacks() ]; } - public function provideDenormalizeCallbacks(): array + public static function provideDenormalizeCallbacks(): array { return [ 'Change a string' => [ [ 'bar' => function ($bar) { - $this->assertEquals('bar', $bar); + static::assertEquals('bar', $bar); return $bar; }, @@ -207,11 +207,11 @@ public function provideDenormalizeCallbacks(): array 'Null an item' => [ [ 'bar' => function ($value, $object, $attributeName, $format, $context) { - $this->assertSame('baz', $value); - $this->assertTrue(is_a($object, CallbacksObject::class, true)); - $this->assertSame('bar', $attributeName); - $this->assertSame('any', $format); - $this->assertIsArray($context); + static::assertSame('baz', $value); + static::assertTrue(is_a($object, CallbacksObject::class, true)); + static::assertSame('bar', $attributeName); + static::assertSame('any', $format); + static::assertIsArray($context); }, ], 'baz', @@ -220,7 +220,7 @@ public function provideDenormalizeCallbacks(): array 'Format a date' => [ [ 'bar' => function ($bar) { - $this->assertIsString($bar); + static::assertIsString($bar); return \DateTime::createFromFormat('d-m-Y H:i:s', $bar); }, @@ -254,13 +254,13 @@ public function provideDenormalizeCallbacks(): array ]; } - public function providerDenormalizeCallbacksWithTypedProperty(): array + public static function providerDenormalizeCallbacksWithTypedProperty(): array { return [ 'Change a typed string' => [ [ 'foo' => function ($foo) { - $this->assertEquals('foo', $foo); + static::assertEquals('foo', $foo); return $foo; }, @@ -271,11 +271,11 @@ public function providerDenormalizeCallbacksWithTypedProperty(): array 'Null an typed item' => [ [ 'foo' => function ($value, $object, $attributeName, $format, $context) { - $this->assertSame('fool', $value); - $this->assertTrue(is_a($object, CallbacksObject::class, true)); - $this->assertSame('foo', $attributeName); - $this->assertSame('any', $format); - $this->assertIsArray($context); + static::assertSame('fool', $value); + static::assertTrue(is_a($object, CallbacksObject::class, true)); + static::assertSame('foo', $attributeName); + static::assertSame('any', $format); + static::assertIsArray($context); }, ], 'fool', @@ -284,7 +284,7 @@ public function providerDenormalizeCallbacksWithTypedProperty(): array ]; } - public function provideInvalidCallbacks() + public static function provideInvalidCallbacks() { return [ [['bar' => null]], diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CircularReferenceTestTrait.php b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CircularReferenceTestTrait.php index 1996e80e98a38..ffbddf2ab3f29 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CircularReferenceTestTrait.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CircularReferenceTestTrait.php @@ -23,7 +23,7 @@ abstract protected function getNormalizerForCircularReference(array $defaultCont abstract protected function getSelfReferencingModel(); - public function provideUnableToNormalizeCircularReference(): array + public static function provideUnableToNormalizeCircularReference(): array { return [ [[], [], 1], diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/SkipUninitializedValuesTestTrait.php b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/SkipUninitializedValuesTestTrait.php index 596b3404b7e24..02707768fc880 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/SkipUninitializedValuesTestTrait.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/SkipUninitializedValuesTestTrait.php @@ -44,7 +44,7 @@ public function testSkipUninitializedValues(array $context) $this->assertSame('value', $objectToPopulate->getUninitialized()); } - public function skipUninitializedValuesFlagProvider(): iterable + public static function skipUninitializedValuesFlagProvider(): iterable { yield 'passed manually' => [['skip_uninitialized_values' => true, 'groups' => ['foo']]]; yield 'using default context value' => [['groups' => ['foo']]]; From 74bc0ebb2f3e47b80eac4da5de0f12a8c13a5701 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 2 May 2024 22:30:26 +0200 Subject: [PATCH 27/90] [Serializer] Fix `GetSetMethodNormalizer` not working with setters with optional args --- .../Normalizer/GetSetMethodNormalizer.php | 2 +- .../Normalizer/GetSetMethodNormalizerTest.php | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 9aaac706f2133..619500828d506 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -107,7 +107,7 @@ private function isSetMethod(\ReflectionMethod $method): bool { return !$method->isStatic() && (\PHP_VERSION_ID < 80000 || !$method->getAttributes(Ignore::class)) - && 1 === $method->getNumberOfRequiredParameters() + && 0 < $method->getNumberOfParameters() && str_starts_with($method->name, 'set'); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index e7c23cf58a574..424dd215e7952 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -538,6 +538,18 @@ public function testSupportsAndDenormalizeWithOnlyParentSetter() $obj = $this->normalizer->denormalize(['foo' => 'foo'], GetSetDummyChild::class); $this->assertSame('foo', $obj->getFoo()); } + + /** + * @testWith [{"foo":"foo"}, "getFoo", "foo"] + * [{"bar":"bar"}, "getBar", "bar"] + */ + public function testSupportsAndDenormalizeWithOptionalSetterArgument(array $data, string $method, string $expected) + { + $this->assertTrue($this->normalizer->supportsDenormalization($data, GetSetDummyWithOptionalAndMultipleSetterArgs::class)); + + $obj = $this->normalizer->denormalize($data, GetSetDummyWithOptionalAndMultipleSetterArgs::class); + $this->assertSame($expected, $obj->$method()); + } } class GetSetDummy @@ -861,3 +873,29 @@ public function setFoo($foo) $this->foo = $foo; } } + +class GetSetDummyWithOptionalAndMultipleSetterArgs +{ + private $foo; + private $bar; + + public function getFoo() + { + return $this->foo; + } + + public function setFoo($foo = null) + { + $this->foo = $foo; + } + + public function getBar() + { + return $this->bar; + } + + public function setBar($bar = null, $other = true) + { + $this->bar = $bar; + } +} From cc0b95749fe9fd4a628bba9a048d44bd020447ee Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 3 May 2024 10:27:17 +0200 Subject: [PATCH 28/90] [HttpClient] Fix cURL default options --- src/Symfony/Component/HttpClient/Response/CurlResponse.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/HttpClient/Response/CurlResponse.php b/src/Symfony/Component/HttpClient/Response/CurlResponse.php index 633b74a1256ed..f36a05f9d6ae2 100644 --- a/src/Symfony/Component/HttpClient/Response/CurlResponse.php +++ b/src/Symfony/Component/HttpClient/Response/CurlResponse.php @@ -174,10 +174,6 @@ public function __construct(CurlClientState $multi, $ch, ?array $options = null, curl_multi_remove_handle($multi->handle, $ch); curl_setopt_array($ch, [ \CURLOPT_NOPROGRESS => true, - \CURLOPT_PROGRESSFUNCTION => null, - \CURLOPT_HEADERFUNCTION => null, - \CURLOPT_WRITEFUNCTION => null, - \CURLOPT_READFUNCTION => null, \CURLOPT_INFILE => null, ]); From 2c845fab1f23518ba3a19e558eebf87b92f4d8fe Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 3 May 2024 13:18:44 +0200 Subject: [PATCH 29/90] [Validator] Check `Locale` class existence before using it --- .../Validator/Test/ConstraintValidatorTestCase.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php index 89f8d0008e75a..0e89e78b1a039 100644 --- a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php @@ -80,8 +80,10 @@ protected function setUp(): void $this->validator = $this->createValidator(); $this->validator->initialize($this->context); - $this->defaultLocale = \Locale::getDefault(); - \Locale::setDefault('en'); + if (class_exists(\Locale::class)) { + $this->defaultLocale = \Locale::getDefault(); + \Locale::setDefault('en'); + } $this->expectedViolations = []; $this->call = 0; @@ -93,7 +95,9 @@ protected function tearDown(): void { $this->restoreDefaultTimezone(); - \Locale::setDefault($this->defaultLocale); + if (class_exists(\Locale::class)) { + \Locale::setDefault($this->defaultLocale); + } } protected function setDefaultTimezone(?string $defaultTimezone) From 1211fbedf33db47d000a0ad876b2f1825269371e Mon Sep 17 00:00:00 2001 From: Sherin Bloemendaal Date: Fri, 3 May 2024 18:54:46 +0200 Subject: [PATCH 30/90] [Mailer] [Sendgrid] Use DataPart::getContentId() when DataPart::setContentId() is used. --- .../Transport/SendgridApiTransportTest.php | 41 +++++++++++++++++++ .../Transport/SendgridApiTransport.php | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php index 86d33241a1816..4196d0897172f 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php @@ -245,4 +245,45 @@ public function testTagAndMetadataHeaders() $this->assertSame('blue', $payload['personalizations'][0]['custom_args']['Color']); $this->assertSame('12345', $payload['personalizations'][0]['custom_args']['Client-ID']); } + + public function testInlineWithCustomContentId() + { + $imagePart = (new DataPart('text-contents', 'text.txt')); + $imagePart->asInline(); + $imagePart->setContentId('content-identifier@symfony'); + + $email = new Email(); + $email->addPart($imagePart); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new SendgridApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload'); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('attachments', $payload); + $this->assertCount(1, $payload['attachments']); + $this->assertArrayHasKey('content_id', $payload['attachments'][0]); + + $this->assertSame('content-identifier@symfony', $payload['attachments'][0]['content_id']); + } + + public function testInlineWithoutCustomContentId() + { + $imagePart = (new DataPart('text-contents', 'text.txt')); + $imagePart->asInline(); + + $email = new Email(); + $email->addPart($imagePart); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new SendgridApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload'); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('attachments', $payload); + $this->assertCount(1, $payload['attachments']); + $this->assertArrayHasKey('content_id', $payload['attachments'][0]); + + $this->assertSame('text.txt', $payload['attachments'][0]['content_id']); + } } diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index 08a337ec412ab..a59255b37ce6e 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -179,7 +179,7 @@ private function getAttachments(Email $email): array ]; if ('inline' === $disposition) { - $att['content_id'] = $filename; + $att['content_id'] = $attachment->hasContentId() ? $attachment->getContentId() : $filename; } $attachments[] = $att; From 88a8d216a8ae73825254ee4ffebf66e8f6280773 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Sat, 4 May 2024 04:04:19 +0200 Subject: [PATCH 31/90] [WebProfilerBundle] Fix assignment to constant variable --- .../Resources/views/Profiler/base_js.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 8a669a5c6caa9..f81781066e0b6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -75,7 +75,7 @@ } tab.addEventListener('click', function(e) { - const activeTab = e.target || e.srcElement; + let activeTab = e.target || e.srcElement; /* needed because when the tab contains HTML contents, user can click */ /* on any of those elements instead of their parent '