From f301f1db836022c7b014b39338a848820f42b574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Thu, 16 Feb 2023 01:02:07 +0100 Subject: [PATCH 01/69] [TwigBridge] Fix raw content rendering in HTML notification emails --- .../Resources/views/Email/zurb_2/notification/body.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig index 0a52d36b374ed..28a62de3eed57 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig @@ -26,7 +26,7 @@ {% if markdown %} {{ include('@email/zurb_2/notification/content_markdown.html.twig') }} {% else %} - {{ (raw ? content|raw : content)|nl2br }} + {{ raw ? content|raw : content|nl2br }} {% endif %} {% endblock %} From 0a8ba937b727222bf5a02e15acd9264497c42899 Mon Sep 17 00:00:00 2001 From: Florent Destremau Date: Mon, 27 Feb 2023 10:32:41 +0100 Subject: [PATCH 02/69] Removed @internal tag on TraceableAuthenticator::getAuthenticator() --- .../Http/Authenticator/Debug/TraceableAuthenticator.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticator.php index 4b77d9c49f138..40ee23a273aaf 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticator.php @@ -100,9 +100,6 @@ public function isInteractive(): bool return $this->authenticator instanceof InteractiveAuthenticatorInterface && $this->authenticator->isInteractive(); } - /** - * @internal - */ public function getAuthenticator(): AuthenticatorInterface { return $this->authenticator; From 2c7eee068f7cb80cac099f64208bb17590600a81 Mon Sep 17 00:00:00 2001 From: Tugdual Saunier Date: Mon, 27 Feb 2023 14:53:42 -0500 Subject: [PATCH 03/69] [Messenger] Fix TransportNamesStamp deserialization | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | https://github.com/symfony/symfony/issues/31490#issuecomment-1439927253 | License | MIT | Doc PR | n/a Currently, when ones use `TransportNameStamp` the following exception occurs: ``` In Serializer.php line 125: [Symfony\Component\Messenger\Exception\MessageDecodingFailedException] Could not decode stamp: Cannot create an instance of "Symfony\Component\Messenger\Stamp\TransportNamesStamp" from serialized data because its constructor requires parameter "transports" to be present. In AbstractNormalizer.php line 384: [Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException] Cannot create an instance of "Symfony\Component\Messenger\Stamp\TransportNamesStamp" from serialized data because its constructor requires parameter "transports" to be present. ``` This PR renames `TransportNamesStamp` constructor argument in order to match the accesor method (`getTranspdortNames`) so that deserialization work. I know this is technically a BC break but as far as I can tell the feature can not currently work this way and also named arguments are not covered by Symfony's BC if I remember correctly. --- .../Messenger/Stamp/TransportNamesStamp.php | 6 ++--- .../Tests/Stamp/TransportNamesStampTest.php | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Messenger/Stamp/TransportNamesStamp.php b/src/Symfony/Component/Messenger/Stamp/TransportNamesStamp.php index 6eaab7ad54441..c83019166e42e 100644 --- a/src/Symfony/Component/Messenger/Stamp/TransportNamesStamp.php +++ b/src/Symfony/Component/Messenger/Stamp/TransportNamesStamp.php @@ -17,14 +17,14 @@ final class TransportNamesStamp implements StampInterface { /** - * @param string[] $transports Transport names to be used for the message + * @param string[] $transportNames Transport names to be used for the message */ - public function __construct(private array $transports) + public function __construct(private array $transportNames) { } public function getTransportNames(): array { - return $this->transports; + return $this->transportNames; } } diff --git a/src/Symfony/Component/Messenger/Tests/Stamp/TransportNamesStampTest.php b/src/Symfony/Component/Messenger/Tests/Stamp/TransportNamesStampTest.php index 4e4308ebc4c2d..9954f24c6f051 100644 --- a/src/Symfony/Component/Messenger/Tests/Stamp/TransportNamesStampTest.php +++ b/src/Symfony/Component/Messenger/Tests/Stamp/TransportNamesStampTest.php @@ -12,7 +12,13 @@ namespace Symfony\Component\Messenger\Tests\Stamp; use PHPUnit\Framework\TestCase; +use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Stamp\TransportNamesStamp; +use Symfony\Component\Messenger\Transport\Serialization\Serializer; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; +use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; +use Symfony\Component\Serializer\Serializer as SymfonySerializer; class TransportNamesStampTest extends TestCase { @@ -27,4 +33,21 @@ public function testGetSenders() $this->assertSame($sender, $stampSenders[$key]); } } + + public function testDeserialization() + { + $stamp = new TransportNamesStamp(['foo']); + $serializer = new Serializer( + new SymfonySerializer([ + new ArrayDenormalizer(), + new ObjectNormalizer(), + ], [new JsonEncoder()]) + ); + + $deserializedEnvelope = $serializer->decode($serializer->encode(new Envelope(new \stdClass(), [$stamp]))); + + $deserializedStamp = $deserializedEnvelope->last(TransportNamesStamp::class); + $this->assertInstanceOf(TransportNamesStamp::class, $deserializedStamp); + $this->assertEquals($stamp, $deserializedStamp); + } } From 86584e94044b028389d70775471901a04e2bf8c5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Feb 2023 14:19:03 +0100 Subject: [PATCH 04/69] Update CHANGELOG for 5.4.21 --- CHANGELOG-5.4.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CHANGELOG-5.4.md b/CHANGELOG-5.4.md index 98dbf9b1e7c86..ffa6be4840403 100644 --- a/CHANGELOG-5.4.md +++ b/CHANGELOG-5.4.md @@ -7,6 +7,47 @@ 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.21 (2023-02-28) + + * bug #49526 [Security] Migrate the session on login only when the user changes (nicolas-grekas) + * bug #49516 [Workflow] display label with new lines + colours properly when rendering a PUML dump (alexislefebvre) + * bug #48965 [TwigBridge] Allow floats in html5 input type number field (wimhendrikx) + * bug #48833 [Translation] Handle the translation of empty strings (javiereguiluz) + * bug #49292 [VarDumper] Fix error when reflected class has default Enum parameter in constructor (kapiwko) + * bug #49493 [FrameworkBundle] Fix denyAccessUnlessGranted for mixed attributes (delbertooo) + * bug #49484 [Validator] Fix translation of AtLeastOneOf constraint message (alexandre-daubois) + * bug #48998 [Validator] Sync IBAN formats with Swift IBAN registry (smelesh) + * bug #49405 [MonologBridge] FirePHPHandler::onKernelResponse throws PHP 8.1 deprecation when no user agent is set (juagarc4) + * bug #49421 [TwigBridge] do not drop embed label classes (xabbuh) + * bug #49422 [Cache][Messenger] fixed CallbackInterface support in async expiration handler (AdamKatzDev) + * bug #49441 [Contracts] Fix setting $container before calling parent::setContainer in ServiceSubscriberTrait (edsrzf) + * bug #49272 [Workflow] remove new lines from workflow metadata (alexislefebvre) + * bug #49427 [WebProfilerBundle] Render original (not encoded) email headers (1ed) + * bug #49368 [BC Break] Make data providers for abstract test cases static (OskarStark, alexandre-daubois) + * bug #49385 [Notifier] Make `TransportTestCase` data providers static (alexandre-daubois) + * bug #49395 fix trying to load Memcached before checking we can (nicolas-grekas) + * bug #49326 [Notifier] Fix notifier profiler when transport name is null (fabpot) + * bug #49265 [HttpKernel] Fix setting the session on the main request when it's started by a subrequest (nicolas-grekas) + * bug #49353 [Cache] Only validate dbindex parameter when applicable (loevgaard) + * bug #49346 [ErrorHandler] Do not patch return statements in closures (wouterj) + * bug #49334 [DependencyInjection] keep `proxy` tag on original definition when decorating (kbond) + * bug #47946 [FrameworkBundle] Fix checkboxes check assertions (MatTheCat) + * bug #49301 [HttpClient] Fix data collector (fancyweb) + * bug #49310 [Notifier][WebProfilerBundle] Ignore messages whose `getNotification` returns `null` (MatTheCat) + * bug #49299 [HttpClient] Fix over-encoding of URL parts to match browser's behavior (nicolas-grekas) + * bug #49214 [Mailer] add Sender to the list of bypassed headers (xabbuh) + * bug #49245 [Serializer] Fix CsvEncoder decode on empty data (cazak) + * bug #49249 [Dotenv] Fix phpdoc Dotenv (alamirault) + * bug #49248 [Config] Fix phpdoc nullable (alamirault) + * bug #48880 [Response] `getMaxAge()` returns non-negative integer (pkruithof, fabpot) + * bug #49207 [PropertyInfo] Add meaningful message when `phpstan/phpdoc-parser` is not installed when using `PhpStanExtractor` (alexandre-daubois) + * bug #49220 [Validator] Make ConstraintValidatorTestCase compatible with PHPUnit 10 (gjuric) + * bug #49226 [WebProfilerBundle] Disable Turbo for debug toolbar links (javiereguiluz) + * bug #49223 [WebProfilerBundle] Fix some minor HTML issues (javiereguiluz) + * bug #49146 [PropertyInfo] fail with a meaningful error when a needed package is missing (xabbuh) + * bug #49187 [Ldap] Allow multiple values on `extra_fields` (mvhirsch) + * bug #49128 [DependencyInjection] Fix combinatory explosion when autowiring union and intersection types (nicolas-grekas) + * 5.4.20 (2023-02-01) * bug #49141 [HttpFoundation] Fix bad return type in IpUtils::checkIp4() (tristankretzer) From e2e31cb2ea97d95cea11954584f9ad51c5d9da23 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Feb 2023 14:19:08 +0100 Subject: [PATCH 05/69] Update CONTRIBUTORS for 5.4.21 --- CONTRIBUTORS.md | 73 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 016a12f53a9c9..e9f3d759e500f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -48,19 +48,21 @@ The Symfony Connect username in parenthesis allows to get more information - Benjamin Eberlei (beberlei) - Igor Wiedler - HypeMC (hypemc) + - Alexandre Daubois (alexandre-daubois) - Valentin Udaltsov (vudaltsov) - Vasilij Duško (staff) - Matthias Pigulla (mpdude) - - Laurent VOULLEMIER (lvo) + - Gabriel Ostrolucký (gadelat) - Antoine Makdessi (amakdessi) + - Laurent VOULLEMIER (lvo) - Pierre du Plessis (pierredup) - Grégoire Paris (greg0ire) - - Gabriel Ostrolucký (gadelat) - Jonathan Wage (jwage) - - Alexandre Daubois (alexandre-daubois) - Titouan Galopin (tgalopin) + - Antoine Lamirault - David Maicher (dmaicher) - Alexander Schranz (alexander-schranz) + - Gábor Egyed (1ed) - Alexandre Salomé (alexandresalome) - William DURAND - ornicar @@ -70,18 +72,16 @@ The Symfony Connect username in parenthesis allows to get more information - Diego Saint Esteben (dosten) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - - Gábor Egyed (1ed) - Francis Besset (francisbesset) - Vasilij Dusko | CREATION - Bulat Shakirzyanov (avalanche123) + - Mathieu Lechat (mat_the_cat) - Iltar van der Berg - Miha Vrhovnik (mvrhov) - Mathieu Piot (mpiot) - Saša Stamenković (umpirsky) - - Antoine Lamirault - - Alex Pott - - Mathieu Lechat (mat_the_cat) - Vincent Langlet (deviling) + - Alex Pott - Guilhem N (guilhemn) - Vladimir Reznichenko (kalessil) - Sarah Khalil (saro0h) @@ -93,6 +93,7 @@ The Symfony Connect username in parenthesis allows to get more information - Peter Rehm (rpet) - Henrik Bjørnskov (henrikbjorn) - David Buchmann (dbu) + - Ruud Kamphuis (ruudk) - Konstantin Myakshin (koc) - Andrej Hudec (pulzarraider) - Julien Falque (julienfalque) @@ -116,7 +117,6 @@ The Symfony Connect username in parenthesis allows to get more information - Dariusz Górecki (canni) - Maxime Helias (maxhelias) - Ener-Getick - - Ruud Kamphuis (ruudk) - Sebastiaan Stok (sstok) - Jérôme Vasseur (jvasseur) - Ion Bazan (ionbazan) @@ -126,12 +126,12 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) + - Yanick Witschi (toflar) - Jordan Alliot (jalliot) - Smaine Milianni (ismail1432) - John Wards (johnwards) - Dariusz Ruminski - Lars Strojny (lstrojny) - - Yanick Witschi (toflar) - Antoine Hérault (herzult) - Konstantin.Myakshin - Rokas Mikalkėnas (rokasm) @@ -164,6 +164,7 @@ The Symfony Connect username in parenthesis allows to get more information - Włodzimierz Gajda (gajdaw) - Christian Scheb - Guillaume (guill) + - Christopher Hertel (chertel) - Tugdual Saunier (tucksaun) - Jacob Dreesen (jdreesen) - Joel Wurtz (brouznouf) @@ -172,7 +173,6 @@ The Symfony Connect username in parenthesis allows to get more information - zairig imad (zairigimad) - Hugo Alliaume (kocal) - Colin Frei - - Christopher Hertel (chertel) - Javier Spagnoletti (phansys) - excelwebzone - Phil Taylor (prazgod) @@ -189,6 +189,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gabriel Caruso - Anthony GRASSIOT (antograssiot) - Jan Rosier (rosier) + - Andreas Möller (localheinz) - Daniel Wehner (dawehner) - Hugo Monteiro (monteiro) - Baptiste Leduc (korbeil) @@ -206,7 +207,6 @@ The Symfony Connect username in parenthesis allows to get more information - Valentine Boineau (valentineboineau) - Jeroen Noten (jeroennoten) - Gocha Ossinkine (ossinkine) - - Andreas Möller (localheinz) - OGAWA Katsuhiro (fivestar) - Jhonny Lidfors (jhonne) - Martin Hujer (martinhujer) @@ -224,6 +224,7 @@ The Symfony Connect username in parenthesis allows to get more information - Colin O'Dell (colinodell) - Sebastian Hörl (blogsh) - Ben Davies (bendavies) + - Alexis Lefebvre - Daniel Gomes (danielcsgomes) - Michael Käfer (michael_kaefer) - Hidenori Goto (hidenorigoto) @@ -271,6 +272,7 @@ The Symfony Connect username in parenthesis allows to get more information - Zmey - Clemens Tolboom - Oleg Voronkovich + - Alan Poulain (alanpoulain) - Helmer Aaviksoo - Michał (bambucha15) - Remon van de Kamp @@ -298,7 +300,7 @@ The Symfony Connect username in parenthesis allows to get more information - Yoann RENARD (yrenard) - Thomas Lallement (raziel057) - Timothée Barray (tyx) - - Alexis Lefebvre + - Sébastien Alfaiate (seb33300) - James Halsall (jaitsu) - Mikael Pajunen - Warnar Boekkooi (boekkooi) @@ -338,7 +340,6 @@ The Symfony Connect username in parenthesis allows to get more information - Islam Israfilov (islam93) - Oleg Andreyev (oleg.andreyev) - Daniel Gorgan - - Sébastien Alfaiate (seb33300) - Hendrik Luup (hluup) - Martin Herndl (herndlm) - Ruben Gonzalez (rubenrua) @@ -358,7 +359,6 @@ The Symfony Connect username in parenthesis allows to get more information - Stepan Anchugov (kix) - bronze1man - sun (sun) - - Alan Poulain (alanpoulain) - Larry Garfield (crell) - Fabien Villepinte - SiD (plbsid) @@ -413,6 +413,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mantis Development - Pablo Lozano (arkadis) - quentin neyrat (qneyrat) + - Dane Powell - Antonio Jose Cerezo (ajcerezo) - Marcin Szepczynski (czepol) - Lescot Edouard (idetox) @@ -452,6 +453,7 @@ The Symfony Connect username in parenthesis allows to get more information - AnneKir - Tobias Weichart - Miro Michalicka + - Peter Kruithof (pkruithof) - M. Vondano - Xavier Perez - Arjen Brouwer (arjenjb) @@ -525,18 +527,17 @@ The Symfony Connect username in parenthesis allows to get more information - Jérôme Tanghe (deuchnord) - Kim Hemsø Rasmussen (kimhemsoe) - Maximilian Reichel (phramz) - - Dane Powell - jaugustin - Dmytro Borysovskyi (dmytr0) - Mathias STRASSER (roukmoute) - Pascal Luna (skalpa) - Wouter Van Hecke - - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Giso Stallenberg (gisostallenberg) - Blanchon Vincent (blanchonvincent) - William Arslett (warslett) - Jérémy REYNAUD (babeuloula) + - Maximilian Beckers (maxbeckers) - Christian Schmidt - Gonzalo Vilaseca (gonzalovilaseca) - Vadim Borodavko (javer) @@ -576,6 +577,7 @@ The Symfony Connect username in parenthesis allows to get more information - Evert Harmeling (evertharmeling) - Jan Decavele (jandc) - Gustavo Piltcher + - Joachim Løvgaard (loevgaard) - Shakhobiddin - Grenier Kévin (mcsky_biig) - Stepan Tanasiychuk (stfalcon) @@ -620,6 +622,7 @@ The Symfony Connect username in parenthesis allows to get more information - Lorenzo Millucci (lmillucci) - Jérôme Tamarelle (jtamarelle-prismamedia) - Emil Masiakowski + - Sergey Melesh (sergex) - Alexandre Parent - Angelov Dejan (angelov) - DT Inier (gam6itko) @@ -775,7 +778,6 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Tschinder - Diego Agulló (aeoris) - Tomasz Ignatiuk - - Joachim Løvgaard (loevgaard) - vladimir.reznichenko - Kai - Lee Rowlands @@ -850,6 +852,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matheo Daninos (mathdns) - Niklas Fiekas - Mark Challoner (markchalloner) + - Allison Guilhem (a_guilhem) - Markus Bachmann (baachi) - Roger Guasch (rogerguasch) - Luis Tacón (lutacon) @@ -862,6 +865,7 @@ The Symfony Connect username in parenthesis allows to get more information - Joost van Driel (j92) - ampaze - Arturs Vonda + - Michael Hirschler (mvhirsch) - Xavier Briand (xavierbriand) - Daniel Badura - vagrant @@ -907,7 +911,6 @@ The Symfony Connect username in parenthesis allows to get more information - ReenExe - Fabian Lange (codingfabian) - Yoshio HANAWA - - Sergey Melesh (sergex) - Toon Verwerft (veewee) - Jiri Barous - Gert de Pagter @@ -1076,7 +1079,6 @@ The Symfony Connect username in parenthesis allows to get more information - Arnaud Frézet - Nicolas Martin (cocorambo) - luffy1727 - - Allison Guilhem (a_guilhem) - LHommet Nicolas (nicolaslh) - Sebastian Blum - Amirreza Shafaat (amirrezashafaat) @@ -1138,7 +1140,6 @@ The Symfony Connect username in parenthesis allows to get more information - Maxime Douailin - Jean Pasdeloup - Laurent Moreau - - Michael Hirschler (mvhirsch) - Javier López (loalf) - tamar peled - Reinier Kip @@ -1152,6 +1153,7 @@ The Symfony Connect username in parenthesis allows to get more information - Karl Shea - dantleech - Valentin + - Jack Worman (jworman) - Sebastian Marek (proofek) - Łukasz Chruściel (lchrusciel) - Jan Vernieuwe (vernija) @@ -1234,6 +1236,7 @@ The Symfony Connect username in parenthesis allows to get more information - Oleg Mifle - Michael Devery (mickadoo) - Loïc Ovigne (oviglo) + - Gregor Nathanael Meyer (spackmat) - Antoine Corcy - Markkus Millend - Clément @@ -1301,7 +1304,6 @@ The Symfony Connect username in parenthesis allows to get more information - Konstantin Bogomolov - Mark Spink - Cesar Scur (cesarscur) - - Maximilian Beckers (maxbeckers) - Kevin (oxfouzer) - Paweł Wacławczyk (pwc) - Sagrario Meneses @@ -1986,9 +1988,11 @@ The Symfony Connect username in parenthesis allows to get more information - Antoine Bluchet (soyuka) - Patrick Kaufmann - Anton Dyshkant + - Ramunas Pabreza - Kirill Nesmeyanov (serafim) - Reece Fowell (reecefowell) - Muhammad Aakash + - Charly Goblet (_mocodo) - Guillaume Gammelin - Valérian Galliat - d-ph @@ -2041,7 +2045,6 @@ The Symfony Connect username in parenthesis allows to get more information - Anne-Sophie Bachelard - Marvin Butkereit - Ben Oman - - Jack Worman (jworman) - Chris de Kok - Andreas Kleemann (andesk) - Hubert Moreau (hmoreau) @@ -2110,7 +2113,9 @@ The Symfony Connect username in parenthesis allows to get more information - gr1ev0us - Léo VINCENT - mlazovla + - Markus Baumer - Max Beutel + - adnen chouibi - Nathan Sepulveda - Antanas Arvasevicius - Pierre Dudoret @@ -2137,12 +2142,14 @@ The Symfony Connect username in parenthesis allows to get more information - allison guilhem - benatespina (benatespina) - Denis Kop + - Kamil Szalewski (szal1k) - Jean-Guilhem Rouel (jean-gui) - Ivan Yivoff - EdgarPE - jfcixmedia - Dominic Tubach - Martijn Evers + - Dustin Wilson - Benjamin Paap (benjaminpaap) - Christian - ju1ius @@ -2154,6 +2161,7 @@ The Symfony Connect username in parenthesis allows to get more information - Martynas Narbutas - Bailey Parker - curlycarla2004 + - Kevin Auvinet - Antanas Arvasevicius - Kris Kelly - Eddie Abou-Jaoude (eddiejaoude) @@ -2180,6 +2188,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jonathan Hedstrom - Peter Smeets (darkspartan) - Julien Bianchi (jubianchi) + - Michael Dawart (mdawart) - Robert Meijers - Tijs Verkoyen - James Sansbury @@ -2230,6 +2239,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mehrdad - Eduardo García Sanz (coma) - fduch (fduch) + - Takashi Kanemoto (ttskch) - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) - Stephan Vock (glaubinix) @@ -2250,6 +2260,7 @@ The Symfony Connect username in parenthesis allows to get more information - John Espiritu (johnillo) - Oxan van Leeuwen - pkowalczyk + - Alexandre parent - Soner Sayakci - Max Voloshin (maxvoloshin) - Nicolas Fabre (nfabre) @@ -2274,6 +2285,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alain Flaus (halundra) - tsufeki - Philipp Strube + - Wim Hendrikx - Petar Obradović - Clement Herreman (clemherreman) - Dan Ionut Dumitriu (danionut90) @@ -2287,6 +2299,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alberto Aldegheri - Dalibor Karlović - Cyril Vermandé (cyve) + - Raul Garcia Canet (juagarc4) - Dmitri Petmanson - heccjj - Alexandre Melard @@ -2298,6 +2311,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tobias Stöckler - Mario Young - martkop26 + - Evan Shaw - Sander Hagen - Ilia (aliance) - cilefen (cilefen) @@ -2322,6 +2336,7 @@ The Symfony Connect username in parenthesis allows to get more information - Rubén Calvo (rubencm) - Abdul.Mohsen B. A. A - Cédric Girard + - Robert Worgul - pthompson - Malaney J. Hill - Patryk Kozłowski @@ -2510,6 +2525,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ergie Gonzaga - Matthew J Mucklo - AnrDaemon + - Tristan Kretzer - Charly Terrier (charlypoppins) - Emre Akinci (emre) - psampaz (psampaz) @@ -2563,6 +2579,7 @@ The Symfony Connect username in parenthesis allows to get more information - Antonio Peric-Mazar (antonioperic) - César Suárez (csuarez) - Bjorn Twachtmann (dotbjorn) + - Goran (gog) - Tobias Genberg (lorceroth) - Michael Simonson (mikes) - Nicolas Badey (nico-b) @@ -2663,7 +2680,9 @@ The Symfony Connect username in parenthesis allows to get more information - Kris Buist - Houziaux mike - Phobetor + - Yoann MOROCUTTI - Markus + - Zayan Goripov - Janusz Mocek - Thomas Chmielowiec - shdev @@ -2684,6 +2703,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jeremiah VALERIE - Mike Francis - Nil Borodulia + - Adam Katz - Almog Baku (almogbaku) - Arrakis (arrakis) - Benjamin Schultz (bschultz) @@ -2693,6 +2713,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) - Radek Wionczek (rwionczek) + - Florent Destremau - Nick Stemerdink - David Stone - Vincent Bouzeran @@ -2709,6 +2730,7 @@ The Symfony Connect username in parenthesis allows to get more information - Lorenzo Adinolfi (loru88) - Ahmed Shamim Hassan (me_shaon) - Michal Kurzeja (mkurzeja) + - Adrien Roches (neirda24) - Nicolas Bastien (nicolas_bastien) - Nikola Svitlica (thecelavi) - Andrew Zhilin (zhil) @@ -2894,6 +2916,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matt Lehner - Helmut Januschka - Hein Zaw Htet™ + - Kieran - Ruben Kruiswijk - Cosmin-Romeo TANASE - Michael J @@ -2909,6 +2932,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alessandro Loffredo - Ian Phillips - Remi Collet + - Nicolas Dousson - Haritz - Matthieu Prat - Brieuc Thomas @@ -2930,6 +2954,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alan Chen - Maerlyn - Even André Fiskvik + - tourze - Erik van Wingerden - Valouleloup - Alexis MARQUIS @@ -2994,7 +3019,6 @@ The Symfony Connect username in parenthesis allows to get more information - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) - Mokhtar Tlili (sf-djuba) - - Gregor Nathanael Meyer (spackmat) - Marcin Szepczynski (szepczynski) - Simone Di Maulo (toretto460) - Cyrille Jouineau (tuxosaurus) @@ -3138,6 +3162,7 @@ The Symfony Connect username in parenthesis allows to get more information - Wojciech Skorodecki - Kevin Frantz - Neophy7e + - Evert Jan Hakvoort - bokonet - Arrilot - andrey-tech @@ -3227,6 +3252,7 @@ The Symfony Connect username in parenthesis allows to get more information - Juan Ases García (ases) - Siragusa (asiragusa) - Daniel Basten (axhm3a) + - Albert Bakker (babbert) - Bernd Matzner (bmatzner) - Bram Tweedegolf (bram_tweedegolf) - Brandon Kelly (brandonkelly) @@ -3234,6 +3260,7 @@ The Symfony Connect username in parenthesis allows to get more information - Kousuke Ebihara (co3k) - Loïc Vernet (coil) - Christoph Vincent Schaefer (cvschaefer) + - Kamil Piwowarski (cyklista) - Damon Jones (damon__jones) - David Courtey (david-crty) - Łukasz Giza (destroyer) From e7002e5bca12c720287b2c30e20d6080cc3f8169 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Feb 2023 14:19:09 +0100 Subject: [PATCH 06/69] Update VERSION for 5.4.21 --- 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 5a95e77848b61..5f79ffbfbf98b 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.21-DEV'; + public const VERSION = '5.4.21'; public const VERSION_ID = 50421; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; public const RELEASE_VERSION = 21; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From 8197ada47163856013164480fc3545b06cebd17d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Feb 2023 14:26:05 +0100 Subject: [PATCH 07/69] Bump Symfony version to 5.4.22 --- 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 5f79ffbfbf98b..7e69e9c7464e4 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.21'; - public const VERSION_ID = 50421; + public const VERSION = '5.4.22-DEV'; + public const VERSION_ID = 50422; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 21; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 22; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From ac12c4f9d8d5f3db88201d941ab639d04b08533a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Feb 2023 15:19:25 +0100 Subject: [PATCH 08/69] Bump Symfony version to 6.2.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 d84a70080729e..20031c5d1167d 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -75,12 +75,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.2.7'; - public const VERSION_ID = 60207; + public const VERSION = '6.2.8-DEV'; + public const VERSION_ID = 60208; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 2; - public const RELEASE_VERSION = 7; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 8; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '07/2023'; public const END_OF_LIFE = '07/2023'; From 97c587432081f7745e332ab1c4ed86bb9f05d24c Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 2 Mar 2023 08:36:01 +0100 Subject: [PATCH 09/69] [DependencyInjection] Fix dumping array of enums parameters --- .../DependencyInjection/Dumper/PhpDumper.php | 25 +++++++++++-------- .../Tests/Dumper/PhpDumperTest.php | 10 ++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index dd548f3c123d1..66bf26879b70e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -92,6 +92,7 @@ class PhpDumper extends Dumper private $locatedIds = []; private $serviceLocatorTag; private $exportedVariables = []; + private $dynamicParameters = []; private $baseClass; /** @@ -141,6 +142,7 @@ public function dump(array $options = []) $this->targetDirRegex = null; $this->inlinedRequires = []; $this->exportedVariables = []; + $this->dynamicParameters = []; $options = array_merge([ 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', @@ -223,11 +225,12 @@ public function dump(array $options = []) $this->preload = array_combine($options['preload_classes'], $options['preload_classes']); } + $code = $this->addDefaultParametersMethod(); $code = $this->startClass($options['class'], $baseClass, $this->inlineFactories && $proxyClasses). $this->addServices($services). $this->addDeprecatedAliases(). - $this->addDefaultParametersMethod() + $code ; $proxyClasses = $proxyClasses ?? $this->generateProxyClasses(); @@ -391,6 +394,7 @@ class %s extends {$options['class']} $this->circularReferences = []; $this->locatedIds = []; $this->exportedVariables = []; + $this->dynamicParameters = []; $this->preload = []; $unusedEnvs = []; @@ -1512,6 +1516,7 @@ private function addDefaultParametersMethod(): string if ($hasEnum || preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $export[1])) { $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]); + $this->dynamicParameters[$key] = true; } else { $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]); } @@ -1916,20 +1921,18 @@ private function dumpLiteralClass(string $class): string private function dumpParameter(string $name): string { - if ($this->container->hasParameter($name)) { - $value = $this->container->getParameter($name); - $dumpedValue = $this->dumpValue($value, false); + if (!$this->container->hasParameter($name) || ($this->dynamicParameters[$name] ?? false)) { + return sprintf('$this->getParameter(%s)', $this->doExport($name)); + } - if (!$value || !\is_array($value)) { - return $dumpedValue; - } + $value = $this->container->getParameter($name); + $dumpedValue = $this->dumpValue($value, false); - if (!preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $dumpedValue)) { - return sprintf('$this->parameters[%s]', $this->doExport($name)); - } + if (!$value || !\is_array($value)) { + return $dumpedValue; } - return sprintf('$this->getParameter(%s)', $this->doExport($name)); + return sprintf('$this->parameters[%s]', $this->doExport($name)); } private function getServiceCall(string $id, Reference $reference = null): string diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 9763d2c158731..694413d670047 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -1237,6 +1237,11 @@ public function testDumpHandlesEnumeration() ->register('foo', FooClassWithEnumAttribute::class) ->setPublic(true) ->addArgument(FooUnitEnum::BAR); + $container + ->register('bar', \stdClass::class) + ->setPublic(true) + ->addArgument('%unit_enum%') + ->addArgument('%enum_array%'); $container->setParameter('unit_enum', FooUnitEnum::BAR); $container->setParameter('enum_array', [FooUnitEnum::BAR, FooUnitEnum::FOO]); @@ -1254,6 +1259,11 @@ public function testDumpHandlesEnumeration() $this->assertSame(FooUnitEnum::BAR, $container->getParameter('unit_enum')); $this->assertSame([FooUnitEnum::BAR, FooUnitEnum::FOO], $container->getParameter('enum_array')); $this->assertStringMatchesFormat(<<<'PHP' +%A + protected function getBarService() + { + return $this->services['bar'] = new \stdClass(\Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAR, $this->getParameter('enum_array')); + } %A private function getDynamicParameter(string $name) { From e79eebb7ba8cb2ef88e8719d6627d7257d9d5a87 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 2 Mar 2023 11:11:10 +0100 Subject: [PATCH 10/69] [HttpClient] Fix encoding "+" in URLs --- src/Symfony/Component/HttpClient/HttpClientTrait.php | 1 - .../Component/HttpClient/Tests/HttpClientTraitTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 20c2cebbe9113..18e71fe7f552d 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -629,7 +629,6 @@ private static function mergeQueryString(?string $queryString, array $queryArray '%28' => '(', '%29' => ')', '%2A' => '*', - '%2B' => '+', '%2C' => ',', '%2F' => '/', '%3A' => ':', diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php index baa97dd360236..ebbe329cca93e 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php @@ -157,8 +157,8 @@ public static function provideParseUrl(): iterable yield [['http:', null, null, null, null], 'http:']; yield [['http:', null, 'bar', null, null], 'http:bar']; yield [[null, null, 'bar', '?a=1&c=c', null], 'bar?a=a&b=b', ['b' => null, 'c' => 'c', 'a' => 1]]; - yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*+,;%3D:@%25\\^`{|}', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; - yield [[null, null, 'bar', '?a=b+%20c', null], 'bar?a=b+c', ['a' => 'b+ c']]; + yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*%2B,;%3D:@%25\\^`{|}', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; + yield [[null, null, 'bar', '?a=b%2B%20c', null], 'bar?a=b+c', ['a' => 'b+ c']]; yield [[null, null, 'bar', '?a[b]=c', null], 'bar', ['a' => ['b' => 'c']]]; yield [[null, null, 'bar', '?a[b[c]=d', null], 'bar?a[b[c]=d', []]; yield [[null, null, 'bar', '?a[b][c]=dd', null], 'bar?a[b][c]=d&e[f]=g', ['a' => ['b' => ['c' => 'dd']], 'e[f]' => null]]; From 2b11a453dbbb67f2a06d94e655b0d6421aa71974 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Sun, 5 Mar 2023 11:59:41 +0100 Subject: [PATCH 11/69] [TwigBridge] Fix flagged malicious url --- src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css b/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css index b826813ec5d76..dab0df58abecb 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css +++ b/src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css @@ -1,7 +1,7 @@ /* * Copyright (c) 2017 ZURB, inc. -- MIT License * - * https://raw.githubusercontent.com/foundation/foundation-emails/v2.2.1/dist/foundation-emails.css + * https://github.com/foundation/foundation-emails/blob/v2.2.1/dist/foundation-emails.css */ .wrapper { From f73f2247474b5019e3b82b69dadfe85ffc785690 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Sun, 5 Mar 2023 18:17:42 +0100 Subject: [PATCH 12/69] [VarDumper] Add a bit of test coverage --- .../Tests/Caster/DoctrineCasterTest.php | 45 ++++++++++ .../Tests/Caster/ExceptionCasterTest.php | 89 +++++++++++++++++++ .../Tests/Caster/FiberCasterTest.php | 85 ++++++++++++++++++ .../RequestContextProviderTest.php | 49 ++++++++++ 4 files changed, 268 insertions(+) create mode 100644 src/Symfony/Component/VarDumper/Tests/Caster/DoctrineCasterTest.php create mode 100644 src/Symfony/Component/VarDumper/Tests/Caster/FiberCasterTest.php create mode 100644 src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DoctrineCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DoctrineCasterTest.php new file mode 100644 index 0000000000000..85f6293b13514 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DoctrineCasterTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Test\VarDumperTestTrait; + +/** + * @requires function \Doctrine\Common\Collections\ArrayCollection::__construct + */ +class DoctrineCasterTest extends TestCase +{ + use VarDumperTestTrait; + + public function testCastPersistentCollection() + { + $classMetadata = new ClassMetadata(__CLASS__); + + $collection = new PersistentCollection($this->createMock(EntityManagerInterface::class), $classMetadata, new ArrayCollection(['test'])); + + $expected = <<assertDumpMatchesFormat($expected, $collection); + } +} diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 47cac85066eca..157dc99c900a7 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ExceptionCaster; use Symfony\Component\VarDumper\Caster\FrameStub; @@ -29,6 +30,21 @@ private function getTestException($msg, &$ref = null) return new \Exception(''.$msg); } + private function getTestError($msg): \Error + { + return new \Error(''.$msg); + } + + private function getTestErrorException($msg): \ErrorException + { + return new \ErrorException(''.$msg); + } + + private function getTestSilencedErrorContext(): SilencedErrorContext + { + return new SilencedErrorContext(\E_ERROR, __FILE__, __LINE__); + } + protected function tearDown(): void { ExceptionCaster::$srcContext = 1; @@ -61,6 +77,79 @@ public function testDefaultSettings() $this->assertSame(['foo'], $ref); } + public function testDefaultSettingsOnError() + { + $e = $this->getTestError('foo'); + + $expectedDump = <<<'EODUMP' +Error { + #message: "foo" + #code: 0 + #file: "%sExceptionCasterTest.php" + #line: %d + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestError($msg): Error + › { + › return new \Error(''.$msg); + › } + } + %s%eTests%eCaster%eExceptionCasterTest.php:%d { …} +%A +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + + public function testDefaultSettingsOnErrorException() + { + $e = $this->getTestErrorException('foo'); + + $expectedDump = <<<'EODUMP' +ErrorException { + #message: "foo" + #code: 0 + #file: "%sExceptionCasterTest.php" + #line: %d + #severity: E_ERROR + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestErrorException($msg): ErrorException + › { + › return new \ErrorException(''.$msg); + › } + } + %s%eTests%eCaster%eExceptionCasterTest.php:%d { …} +%A +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + + /** + * @requires function \Symfony\Component\ErrorHandler\Exception\SilencedErrorContext::__construct + */ + public function testCastSilencedErrorContext() + { + $e = $this->getTestSilencedErrorContext(); + + $expectedDump = <<<'EODUMP' +Symfony\Component\ErrorHandler\Exception\SilencedErrorContext { + +count: 1 + -severity: E_ERROR + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + › { + › return new SilencedErrorContext(\E_ERROR, __FILE__, __LINE__); + › } + } + } +} +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + public function testSeek() { $e = $this->getTestException(2); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/FiberCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/FiberCasterTest.php new file mode 100644 index 0000000000000..ff501db0b6742 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Caster/FiberCasterTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Test\VarDumperTestTrait; + +/** + * @requires PHP 8.1 + */ +class FiberCasterTest extends TestCase +{ + use VarDumperTestTrait; + + public function testCastFiberNotStarted() + { + $fiber = new \Fiber(static function () { + return true; + }); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberTerminated() + { + $fiber = new \Fiber(static function () { + return true; + }); + $fiber->start(); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberSuspended() + { + $fiber = new \Fiber(static function () { + \Fiber::suspend(); + }); + $fiber->start(); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberRunning() + { + $fiber = new \Fiber(function () { + $expected = <<assertDumpEquals($expected, \Fiber::getCurrent()); + }); + + $fiber->start(); + } +} diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php new file mode 100644 index 0000000000000..5c1415951fc8b --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Dumper\ContextProvider; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; + +/** + * @requires function \Symfony\Component\HttpFoundation\RequestStack::__construct + */ +class RequestContextProviderTest extends TestCase +{ + public function testGetContextOnNullRequest() + { + $requestStack = new RequestStack(); + $provider = new RequestContextProvider($requestStack); + + $this->assertNull($provider->getContext()); + } + + public function testGetContextOnRequest() + { + $request = Request::create('https://example.org/', 'POST'); + $request->attributes->set('_controller', 'MyControllerClass'); + + $requestStack = new RequestStack(); + $requestStack->push($request); + + $context = (new RequestContextProvider($requestStack))->getContext(); + $this->assertSame('https://example.org/', $context['uri']); + $this->assertSame('POST', $context['method']); + $this->assertInstanceOf(Data::class, $context['controller']); + $this->assertSame('MyControllerClass', $context['controller']->getValue()); + $this->assertSame('https://example.org/', $context['uri']); + $this->assertArrayHasKey('identifier', $context); + } +} From 0a12ee695fed385b51fcb0834cc6c2a8552e7062 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Mar 2023 20:53:37 +0100 Subject: [PATCH 13/69] [Translation] Decouple TranslatorPathsPass from "debug." convention --- .../RegisterListenersPass.php | 4 +-- .../TranslatorPathsPass.php | 29 +++++++------------ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 8eabe7d741a0f..f47120db9068b 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -122,7 +122,7 @@ public function process(ContainerBuilder $container) $dispatcherDefinition = $globalDispatcherDefinition; if (isset($event['dispatcher'])) { - $dispatcherDefinition = $container->getDefinition($event['dispatcher']); + $dispatcherDefinition = $container->findDefinition($event['dispatcher']); } $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); @@ -161,7 +161,7 @@ public function process(ContainerBuilder $container) continue; } - $dispatcherDefinitions[$attributes['dispatcher']] = $container->getDefinition($attributes['dispatcher']); + $dispatcherDefinitions[$attributes['dispatcher']] = $container->findDefinition($attributes['dispatcher']); } if (!$dispatcherDefinitions) { diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php index 18a71c45ae662..2ee13640c78b8 100644 --- a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; /** * @author Yonel Ceruto @@ -136,28 +137,20 @@ protected function processValue($value, bool $isRoot = false) private function findControllerArguments(ContainerBuilder $container): array { - if ($container->hasDefinition($this->resolverServiceId)) { - $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0); - if ($argument instanceof Reference) { - $argument = $container->getDefinition($argument); - } - - return $argument->getArgument(0); + if (!$container->has($this->resolverServiceId)) { + return []; } + $resolverDef = $container->findDefinition($this->resolverServiceId); - if ($container->hasDefinition('debug.'.$this->resolverServiceId)) { - $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0); - if ($argument instanceof Reference) { - $argument = $container->getDefinition($argument); - } - $argument = $argument->getArgument(0); - if ($argument instanceof Reference) { - $argument = $container->getDefinition($argument); - } + if (TraceableValueResolver::class === $resolverDef->getClass()) { + $resolverDef = $container->getDefinition($resolverDef->getArgument(0)); + } - return $argument->getArgument(0); + $argument = $resolverDef->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); } - return []; + return $argument->getArgument(0); } } From 9a4328b0fc4598c6fa11b2d252f9808154b6036f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Mar 2023 21:44:01 +0100 Subject: [PATCH 14/69] Fix tests --- .../Loco/Tests/LocoProviderWithoutTranslatorBagTest.php | 4 ++-- src/Symfony/Component/Translation/Bridge/Loco/composer.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php index ef312248e2a12..c9584820b8968 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php @@ -45,7 +45,7 @@ public function testReadWithLastModified(array $locales, array $domains, array $ foreach ($domains as $domain) { $responses[] = function (string $method, string $url, array $options = []) use ($responseContents, $lastModifieds, $locale, $domain): ResponseInterface { $this->assertSame('GET', $method); - $this->assertSame('https://localise.biz/api/export/locale/'.$locale.'.xlf?filter='.$domain.'&status=translated,blank-translation', $url); + $this->assertSame('https://localise.biz/api/export/locale/'.$locale.'.xlf?filter='.rawurlencode($domain).'&status=translated%2Cblank-translation', $url); $this->assertSame(['filter' => $domain, 'status' => 'translated,blank-translation'], $options['query']); $this->assertSame(['Accept: */*'], $options['headers']); @@ -84,7 +84,7 @@ public function testReadWithLastModified(array $locales, array $domains, array $ foreach ($domains as $domain) { $responses[] = function (string $method, string $url, array $options = []) use ($responseContents, $lastModifieds, $locale, $domain): ResponseInterface { $this->assertSame('GET', $method); - $this->assertSame('https://localise.biz/api/export/locale/'.$locale.'.xlf?filter='.$domain.'&status=translated,blank-translation', $url); + $this->assertSame('https://localise.biz/api/export/locale/'.$locale.'.xlf?filter='.rawurlencode($domain).'&status=translated%2Cblank-translation', $url); $this->assertSame(['filter' => $domain, 'status' => 'translated,blank-translation'], $options['query']); $this->assertNotContains('If-Modified-Since: '.$lastModifieds[$locale], $options['headers']); $this->assertSame(['Accept: */*'], $options['headers']); diff --git a/src/Symfony/Component/Translation/Bridge/Loco/composer.json b/src/Symfony/Component/Translation/Bridge/Loco/composer.json index 5d0e7c2494b98..08d6141d82eb0 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/composer.json +++ b/src/Symfony/Component/Translation/Bridge/Loco/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.1", - "symfony/http-client": "^5.4.21|^6.2.7", + "symfony/http-client": "^5.4|^6.0", "symfony/config": "^5.4|^6.0", "symfony/translation": "^6.2.7" }, From 9b86c72b6900b1c0d869838fd4caf0bf51b0960f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Mar 2023 22:06:00 +0100 Subject: [PATCH 15/69] [HttpClient] Encode "," in query strings --- src/Symfony/Component/HttpClient/HttpClientTrait.php | 1 - src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 18e71fe7f552d..68c3dcd7de03f 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -629,7 +629,6 @@ private static function mergeQueryString(?string $queryString, array $queryArray '%28' => '(', '%29' => ')', '%2A' => '*', - '%2C' => ',', '%2F' => '/', '%3A' => ':', '%3B' => ';', diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php index ebbe329cca93e..6e7163af2309f 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php @@ -157,7 +157,7 @@ public static function provideParseUrl(): iterable yield [['http:', null, null, null, null], 'http:']; yield [['http:', null, 'bar', null, null], 'http:bar']; yield [[null, null, 'bar', '?a=1&c=c', null], 'bar?a=a&b=b', ['b' => null, 'c' => 'c', 'a' => 1]]; - yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*%2B,;%3D:@%25\\^`{|}', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; + yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*%2B%2C;%3D:@%25\\^`{|}', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; yield [[null, null, 'bar', '?a=b%2B%20c', null], 'bar?a=b+c', ['a' => 'b+ c']]; yield [[null, null, 'bar', '?a[b]=c', null], 'bar', ['a' => ['b' => 'c']]]; yield [[null, null, 'bar', '?a[b[c]=d', null], 'bar?a[b[c]=d', []]; From d8ec2afb539b9e950c7bc94bc1b08bd88f50af25 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 6 Mar 2023 21:48:01 +0100 Subject: [PATCH 16/69] [Tests] Replace `setMethods()` by `onlyMethods()` and `addMethods()` --- .../DoctrineExtensionTest.php | 2 +- .../ChoiceList/ORMQueryBuilderLoaderTest.php | 55 +++++++++++++------ .../Doctrine/Tests/Logger/DbalLoggerTest.php | 10 ++-- .../Security/User/EntityUserProviderTest.php | 2 +- .../Constraints/UniqueEntityValidatorTest.php | 3 +- .../Tests/Handler/ConsoleHandlerTest.php | 2 +- .../AnnotationsCacheWarmerTest.php | 2 +- .../CacheWarmer/RouterCacheWarmerTest.php | 8 +-- .../Tests/KernelBrowserTest.php | 2 +- .../Tests/Routing/RouterTest.php | 2 +- .../Tests/EventListener/VoteListenerTest.php | 2 +- .../Cache/Tests/Adapter/ChainAdapterTest.php | 4 +- .../Tests/Adapter/MaxIdLengthAdapterTest.php | 2 +- .../Console/Tests/ApplicationTest.php | 10 ++-- .../MergeExtensionConfigurationPassTest.php | 4 +- .../Component/DomCrawler/Tests/FormTest.php | 2 +- .../Test/Traits/ValidatorExtensionTrait.php | 2 +- .../Handler/MemcachedSessionHandlerTest.php | 2 +- .../DataCollector/LoggerDataCollectorTest.php | 12 ++-- .../Debug/TraceableEventDispatcherTest.php | 4 +- .../EventListener/LocaleListenerTest.php | 4 +- .../HttpKernel/Tests/HttpCache/EsiTest.php | 2 +- .../Tests/HttpCache/HttpCacheTest.php | 2 +- .../HttpKernel/Tests/HttpCache/SsiTest.php | 2 +- .../Tests/HttpKernelBrowserTest.php | 3 +- .../HttpKernel/Tests/HttpKernelTest.php | 2 +- .../Component/HttpKernel/Tests/KernelTest.php | 19 ++++--- .../Tests/Profiler/ProfilerTest.php | 2 +- .../Tests/ProcessFailedExceptionTest.php | 6 +- .../Routing/Tests/Loader/ObjectLoaderTest.php | 2 +- .../CompiledRedirectableUrlMatcherTest.php | 2 +- .../Dumper/CompiledUrlMatcherDumperTest.php | 2 +- .../AuthenticationProviderManagerTest.php | 2 +- .../AnonymousAuthenticationProviderTest.php | 2 +- .../DaoAuthenticationProviderTest.php | 2 +- ...uthenticatedAuthenticationProviderTest.php | 2 +- .../RememberMeAuthenticationProviderTest.php | 2 +- .../UserAuthenticationProviderTest.php | 2 +- .../Storage/UsageTrackingTokenStorageTest.php | 2 +- .../TraceableAccessDecisionManagerTest.php | 6 +- .../Tests/GuardAuthenticatorHandlerTest.php | 2 +- ...efaultAuthenticationFailureHandlerTest.php | 2 +- .../CheckCredentialsListenerTest.php | 4 +- .../Tests/Firewall/ContextListenerTest.php | 2 +- .../Test/ConstraintValidatorTestCase.php | 8 +-- .../Validator/RecursiveValidatorTest.php | 4 +- .../Contracts/Tests/Cache/CacheTraitTest.php | 8 +-- 47 files changed, 128 insertions(+), 102 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index 97cec26cf7ed7..a84804813da4d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -34,7 +34,7 @@ protected function setUp(): void $this->extension = $this ->getMockBuilder(AbstractDoctrineExtension::class) - ->setMethods([ + ->onlyMethods([ 'getMappingResourceConfigDirectory', 'getObjectManagerElementName', 'getMappingObjectDefaultName', diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 50e083234d7cd..10c73ca3d4c36 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -12,8 +12,10 @@ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Types\GuidType; use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\Version; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; @@ -46,8 +48,8 @@ protected function checkIdentifierType($classname, $expectedType) { $em = DoctrineTestHelper::createTestEntityManager(); - $query = $this->getMockBuilder(\QueryMock::class) - ->setMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) + $query = $this->getMockBuilder(QueryMock::class) + ->onlyMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) ->getMock(); $query @@ -61,7 +63,7 @@ protected function checkIdentifierType($classname, $expectedType) $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->once()) @@ -79,8 +81,8 @@ public function testFilterNonIntegerValues() { $em = DoctrineTestHelper::createTestEntityManager(); - $query = $this->getMockBuilder(\QueryMock::class) - ->setMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) + $query = $this->getMockBuilder(QueryMock::class) + ->onlyMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) ->getMock(); $query @@ -94,7 +96,7 @@ public function testFilterNonIntegerValues() $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->once()) @@ -115,8 +117,8 @@ public function testFilterEmptyUuids($entityClass) { $em = DoctrineTestHelper::createTestEntityManager(); - $query = $this->getMockBuilder(\QueryMock::class) - ->setMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) + $query = $this->getMockBuilder(QueryMock::class) + ->onlyMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) ->getMock(); $query @@ -130,7 +132,7 @@ public function testFilterEmptyUuids($entityClass) $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->once()) @@ -160,8 +162,8 @@ public function testFilterUid($entityClass) $em = DoctrineTestHelper::createTestEntityManager(); - $query = $this->getMockBuilder(\QueryMock::class) - ->setMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) + $query = $this->getMockBuilder(QueryMock::class) + ->onlyMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) ->getMock(); $query @@ -175,7 +177,7 @@ public function testFilterUid($entityClass) $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->once()) @@ -207,7 +209,7 @@ public function testUidThrowProperException($entityClass) $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->never()) @@ -234,8 +236,8 @@ public function testEmbeddedIdentifierName() $em = DoctrineTestHelper::createTestEntityManager(); - $query = $this->getMockBuilder(\QueryMock::class) - ->setMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) + $query = $this->getMockBuilder(QueryMock::class) + ->onlyMethods(['setParameter', 'getResult', 'getSql', '_doExecute']) ->getMock(); $query @@ -249,7 +251,7 @@ public function testEmbeddedIdentifierName() $qb = $this->getMockBuilder(\Doctrine\ORM\QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethods(['getQuery']) + ->onlyMethods(['getQuery']) ->getMock(); $qb->expects($this->once()) ->method('getQuery') @@ -278,3 +280,24 @@ public static function provideUidEntityClasses() ]; } } + +class QueryMock extends AbstractQuery +{ + public function __construct() + { + } + + /** + * @return array|string + */ + public function getSQL() + { + } + + /** + * @return Result|int + */ + protected function _doExecute() + { + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php index 91061632815d8..2e9ed80e3115a 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php @@ -30,7 +30,7 @@ public function testLog($sql, $params, $logParams) $dbalLogger = $this ->getMockBuilder(DbalLogger::class) ->setConstructorArgs([$logger, null]) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock() ; @@ -62,7 +62,7 @@ public function testLogNonUtf8() $dbalLogger = $this ->getMockBuilder(DbalLogger::class) ->setConstructorArgs([$logger, null]) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock() ; @@ -85,7 +85,7 @@ public function testLogNonUtf8Array() $dbalLogger = $this ->getMockBuilder(DbalLogger::class) ->setConstructorArgs([$logger, null]) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock() ; @@ -116,7 +116,7 @@ public function testLogLongString() $dbalLogger = $this ->getMockBuilder(DbalLogger::class) ->setConstructorArgs([$logger, null]) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock() ; @@ -144,7 +144,7 @@ public function testLogUTF8LongString() $dbalLogger = $this ->getMockBuilder(DbalLogger::class) ->setConstructorArgs([$logger, null]) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock() ; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php index 20d1e487a23d2..7a09cb8802f72 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php @@ -211,7 +211,7 @@ private function getManager($em, $name = null) private function getObjectManager($repository) { $em = $this->getMockBuilder(ObjectManager::class) - ->setMethods(['getClassMetadata', 'getRepository']) + ->onlyMethods(['getClassMetadata', 'getRepository']) ->getMockForAbstractClass(); $em->expects($this->any()) ->method('getRepository') diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index a4e928438cf0c..14f60165eeac2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -96,7 +96,8 @@ protected function createRegistryMock($em = null) protected function createRepositoryMock() { $repository = $this->getMockBuilder(ObjectRepository::class) - ->setMethods(['findByCustom', 'find', 'findAll', 'findOneBy', 'findBy', 'getClassName']) + ->onlyMethods(['find', 'findAll', 'findOneBy', 'findBy', 'getClassName']) + ->addMethods(['findByCustom']) ->getMock() ; diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php index 85cb1f8d74617..e3d06b52f4035 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php @@ -64,7 +64,7 @@ public function testVerbosityMapping($verbosity, $level, $isHandling, array $map $levelName = Logger::getLevelName($level); $levelName = sprintf('%-9s', $levelName); - $realOutput = $this->getMockBuilder(Output::class)->setMethods(['doWrite'])->getMock(); + $realOutput = $this->getMockBuilder(Output::class)->onlyMethods(['doWrite'])->getMock(); $realOutput->setVerbosity($verbosity); if ($realOutput->isDebug()) { $log = "16:21:54 $levelName [app] My info message\n"; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php index 806cf46b8f4b7..eaee983b13488 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php @@ -136,7 +136,7 @@ public function testWarmupRemoveCacheMisses() $cacheFile = tempnam($this->cacheDir, __FUNCTION__); $warmer = $this->getMockBuilder(AnnotationsCacheWarmer::class) ->setConstructorArgs([new AnnotationReader(), $cacheFile]) - ->setMethods(['doWarmUp']) + ->onlyMethods(['doWarmUp']) ->getMock(); $warmer->method('doWarmUp')->willReturnCallback(function ($cacheDir, ArrayAdapter $arrayAdapter) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/RouterCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/RouterCacheWarmerTest.php index 61214b039c64a..727b566e1ddb3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/RouterCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/RouterCacheWarmerTest.php @@ -21,9 +21,9 @@ class RouterCacheWarmerTest extends TestCase { public function testWarmUpWithWarmebleInterface() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->setMethods(['get', 'has'])->getMock(); + $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); - $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmebleInterface::class)->setMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); + $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmebleInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); $routerCacheWarmer = new RouterCacheWarmer($containerMock); @@ -34,9 +34,9 @@ public function testWarmUpWithWarmebleInterface() public function testWarmUpWithoutWarmebleInterface() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->setMethods(['get', 'has'])->getMock(); + $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); - $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmebleInterface::class)->setMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); + $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmebleInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); $routerCacheWarmer = new RouterCacheWarmer($containerMock); $this->expectException(\LogicException::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php index 404a239b51282..1e462f7d0a8f6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php @@ -64,7 +64,7 @@ public function testRequestAfterKernelShutdownAndPerformedRequest() private function getKernelMock() { $mock = $this->getMockBuilder($this->getKernelClass()) - ->setMethods(['shutdown', 'boot', 'handle', 'getContainer']) + ->onlyMethods(['shutdown', 'boot', 'handle', 'getContainer']) ->disableOriginalConstructor() ->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php index d8ad6e2cf6b89..2cebebed14df0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php @@ -609,7 +609,7 @@ private function getServiceContainer(RouteCollection $routes): Container ->willReturn($routes) ; - $sc = $this->getMockBuilder(Container::class)->setMethods(['get'])->getMock(); + $sc = $this->getMockBuilder(Container::class)->onlyMethods(['get'])->getMock(); $sc ->expects($this->once()) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/EventListener/VoteListenerTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/EventListener/VoteListenerTest.php index 3406e16503f43..d262effae29ac 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/EventListener/VoteListenerTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/EventListener/VoteListenerTest.php @@ -26,7 +26,7 @@ public function testOnVoterVote() $traceableAccessDecisionManager = $this ->getMockBuilder(TraceableAccessDecisionManager::class) ->disableOriginalConstructor() - ->setMethods(['addVoterVote']) + ->onlyMethods(['addVoterVote']) ->getMock(); $traceableAccessDecisionManager diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php index 10924914cd47b..c6772f9f5a8f9 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php @@ -215,7 +215,7 @@ public function testExpirationOnAllAdapters() $adapter1 = $this->getMockBuilder(FilesystemAdapter::class) ->setConstructorArgs(['', 2]) - ->setMethods(['save']) + ->onlyMethods(['save']) ->getMock(); $adapter1->expects($this->once()) ->method('save') @@ -224,7 +224,7 @@ public function testExpirationOnAllAdapters() $adapter2 = $this->getMockBuilder(FilesystemAdapter::class) ->setConstructorArgs(['', 4]) - ->setMethods(['save']) + ->onlyMethods(['save']) ->getMock(); $adapter2->expects($this->once()) ->method('save') diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php index 7120558f0f369..3934b458434b2 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php @@ -21,7 +21,7 @@ public function testLongKey() { $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) ->setConstructorArgs([str_repeat('-', 10)]) - ->setMethods(['doHave', 'doFetch', 'doDelete', 'doSave', 'doClear']) + ->onlyMethods(['doHave', 'doFetch', 'doDelete', 'doSave', 'doClear']) ->getMock(); $cache->expects($this->exactly(2)) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 698a9679bf764..d06abcb8c10dc 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -716,7 +716,7 @@ public function testFindAlternativesOutput() public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() { - $application = $this->getMockBuilder(Application::class)->setMethods(['getNamespaces'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['getNamespaces'])->getMock(); $application->expects($this->once()) ->method('getNamespaces') ->willReturn(['foo:sublong', 'bar:sub']); @@ -876,7 +876,7 @@ public function testRenderExceptionEscapesLines() public function testRenderExceptionLineBreaks() { - $application = $this->getMockBuilder(Application::class)->setMethods(['getTerminalWidth'])->getMock(); + $application = $this->getMockBuilder(Application::class)->addMethods(['getTerminalWidth'])->getMock(); $application->setAutoExit(false); $application->expects($this->any()) ->method('getTerminalWidth') @@ -1103,7 +1103,7 @@ public function testRunReturnsIntegerExitCode() { $exception = new \Exception('', 4); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') @@ -1142,7 +1142,7 @@ public function testRunReturnsExitCodeOneForExceptionCodeZero() { $exception = new \Exception('', 0); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') @@ -1185,7 +1185,7 @@ public function testRunReturnsExitCodeOneForNegativeExceptionCode($exceptionCode { $exception = new \Exception('', $exceptionCode); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index f695c428712fa..2a719c15ec3dd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -61,7 +61,7 @@ public function testExpressionLanguageProviderForwarding() public function testExtensionLoadGetAMergeExtensionConfigurationContainerBuilderInstance() { - $extension = $this->getMockBuilder(FooExtension::class)->setMethods(['load'])->getMock(); + $extension = $this->getMockBuilder(FooExtension::class)->onlyMethods(['load'])->getMock(); $extension->expects($this->once()) ->method('load') ->with($this->isType('array'), $this->isInstanceOf(MergeExtensionConfigurationContainerBuilder::class)) @@ -77,7 +77,7 @@ public function testExtensionLoadGetAMergeExtensionConfigurationContainerBuilder public function testExtensionConfigurationIsTrackedByDefault() { - $extension = $this->getMockBuilder(FooExtension::class)->setMethods(['getConfiguration'])->getMock(); + $extension = $this->getMockBuilder(FooExtension::class)->onlyMethods(['getConfiguration'])->getMock(); $extension->expects($this->exactly(2)) ->method('getConfiguration') ->willReturn(new FooConfiguration()); diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 7248a31a6be05..339716c20ebd5 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -874,7 +874,7 @@ protected function getFormFieldMock($name, $value = null) { $field = $this ->getMockBuilder(FormField::class) - ->setMethods(['getName', 'getValue', 'setValue', 'initialize']) + ->onlyMethods(['getName', 'getValue', 'setValue', 'initialize']) ->disableOriginalConstructor() ->getMock() ; diff --git a/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php b/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php index b4b35fadf9c40..721371996996b 100644 --- a/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php +++ b/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php @@ -35,7 +35,7 @@ protected function getValidatorExtension(): ValidatorExtension } $this->validator = $this->createMock(ValidatorInterface::class); - $metadata = $this->getMockBuilder(ClassMetadata::class)->setConstructorArgs([''])->setMethods(['addPropertyConstraint'])->getMock(); + $metadata = $this->getMockBuilder(ClassMetadata::class)->setConstructorArgs([''])->onlyMethods(['addPropertyConstraint'])->getMock(); $this->validator->expects($this->any())->method('getMetadataFor')->will($this->returnValue($metadata)); $this->validator->expects($this->any())->method('validate')->will($this->returnValue(new ConstraintViolationList())); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index 2e2ec3647656a..a3aea2e8e759b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -45,7 +45,7 @@ protected function setUp(): void $this->memcached = $this->getMockBuilder(\Memcached::class) ->disableOriginalConstructor() - ->setMethods($methodsToMock) + ->onlyMethods($methodsToMock) ->getMock(); $this->storage = new MemcachedSessionHandler( diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php index 44b740c98b167..7dee8891101ee 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -26,7 +26,7 @@ public function testCollectWithUnexpectedFormat() { $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('countErrors')->willReturn(123); $logger->expects($this->exactly(2))->method('getLogs')->willReturn([]); @@ -66,7 +66,7 @@ public function testCollectFromDeprecationsLog() $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('countErrors')->willReturn(0); @@ -100,7 +100,7 @@ public function testWithMainRequest() $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('countErrors')->with(null); $logger->expects($this->exactly(2))->method('getLogs')->with(null)->willReturn([]); @@ -121,7 +121,7 @@ public function testWithSubRequest() $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('countErrors')->with($subRequest); $logger->expects($this->exactly(2))->method('getLogs')->with($subRequest)->willReturn([]); @@ -139,7 +139,7 @@ public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount { $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('countErrors')->willReturn($nb); $logger->expects($this->exactly(2))->method('getLogs')->willReturn($logs); @@ -171,7 +171,7 @@ public function testReset() { $logger = $this ->getMockBuilder(DebugLoggerInterface::class) - ->setMethods(['countErrors', 'getLogs', 'clear']) + ->onlyMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('clear'); diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php index a307bbff55d6c..f37d0f414931b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php @@ -48,7 +48,7 @@ public function testStopwatchSections() public function testStopwatchCheckControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder(Stopwatch::class) - ->setMethods(['isStarted']) + ->onlyMethods(['isStarted']) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') @@ -64,7 +64,7 @@ public function testStopwatchCheckControllerOnRequestEvent() public function testStopwatchStopControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder(Stopwatch::class) - ->setMethods(['isStarted', 'stop']) + ->onlyMethods(['isStarted', 'stop']) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php index 824d906340460..04d951747407d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php @@ -76,7 +76,7 @@ public function testLocaleSetForRoutingContext() $context = $this->createMock(RequestContext::class); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); - $router = $this->getMockBuilder(Router::class)->setMethods(['getContext'])->disableOriginalConstructor()->getMock(); + $router = $this->getMockBuilder(Router::class)->onlyMethods(['getContext'])->disableOriginalConstructor()->getMock(); $router->expects($this->once())->method('getContext')->willReturn($context); $request = Request::create('/'); @@ -92,7 +92,7 @@ public function testRouterResetWithParentRequestOnKernelFinishRequest() $context = $this->createMock(RequestContext::class); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); - $router = $this->getMockBuilder(Router::class)->setMethods(['getContext'])->disableOriginalConstructor()->getMock(); + $router = $this->getMockBuilder(Router::class)->onlyMethods(['getContext'])->disableOriginalConstructor()->getMock(); $router->expects($this->once())->method('getContext')->willReturn($context); $parentRequest = Request::create('/'); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php index 32bd3ac7b5c75..290bd94bdcb97 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php @@ -232,7 +232,7 @@ public function testHandleWhenResponseIsNotModified() protected function getCache($request, $response) { - $cache = $this->getMockBuilder(HttpCache::class)->setMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); + $cache = $this->getMockBuilder(HttpCache::class)->onlyMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); $cache->expects($this->any()) ->method('getRequest') ->willReturn($request) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index 22cf88daa2b51..2a9f48463c842 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -41,7 +41,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface() // implements TerminableInterface $kernelMock = $this->getMockBuilder(Kernel::class) ->disableOriginalConstructor() - ->setMethods(['terminate', 'registerBundles', 'registerContainerConfiguration']) + ->onlyMethods(['terminate', 'registerBundles', 'registerContainerConfiguration']) ->getMock(); $kernelMock->expects($this->once()) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php index 8dfc472d23213..a1f1f1593d3f3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php @@ -190,7 +190,7 @@ public function testHandleWhenResponseIsNot200AndAltIsPresent() protected function getCache($request, $response) { - $cache = $this->getMockBuilder(HttpCache::class)->setMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); + $cache = $this->getMockBuilder(HttpCache::class)->onlyMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); $cache->expects($this->any()) ->method('getRequest') ->willReturn($request) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php index b6e391625c038..55963a16c391e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php @@ -155,7 +155,8 @@ public function testUploadedFileWhenSizeExceedsUploadMaxFileSize() $file = $this ->getMockBuilder(UploadedFile::class) ->setConstructorArgs([$source, 'original', 'mime/original', \UPLOAD_ERR_OK, true]) - ->setMethods(['getSize', 'getClientSize']) + ->onlyMethods(['getSize']) + ->addMethods(['getClientSize']) ->getMock() ; /* should be modified when the getClientSize will be removed */ diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 0a1dc60e4a39d..09e7b9a524c45 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -361,7 +361,7 @@ public function testVerifyRequestStackPushPopDuringHandle() { $request = new Request(); - $stack = $this->getMockBuilder(RequestStack::class)->setMethods(['push', 'pop'])->getMock(); + $stack = $this->getMockBuilder(RequestStack::class)->onlyMethods(['push', 'pop'])->getMock(); $stack->expects($this->once())->method('push')->with($this->equalTo($request)); $stack->expects($this->once())->method('pop'); diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index fa2074694ee99..30055163ceb4c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -148,7 +148,7 @@ public function testBootSetsTheBootedFlagToTrue() public function testClassCacheIsNotLoadedByDefault() { - $kernel = $this->getKernel(['initializeBundles', 'doLoadClassCache']); + $kernel = $this->getKernel(['initializeBundles'], [], false, ['doLoadClassCache']); $kernel->expects($this->never()) ->method('doLoadClassCache'); @@ -449,7 +449,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface() // implements TerminableInterface $httpKernelMock = $this->getMockBuilder(HttpKernel::class) ->disableOriginalConstructor() - ->setMethods(['terminate']) + ->onlyMethods(['terminate']) ->getMock(); $httpKernelMock @@ -630,7 +630,7 @@ protected function getBundle($dir = null, $parent = null, $className = null, $bu { $bundle = $this ->getMockBuilder(BundleInterface::class) - ->setMethods(['getPath', 'getName']) + ->onlyMethods(['getPath', 'getName']) ->disableOriginalConstructor() ; @@ -661,16 +661,21 @@ protected function getBundle($dir = null, $parent = null, $className = null, $bu * @param array $methods Additional methods to mock (besides the abstract ones) * @param array $bundles Bundles to register */ - protected function getKernel(array $methods = [], array $bundles = [], bool $debug = false): Kernel + protected function getKernel(array $methods = [], array $bundles = [], bool $debug = false, array $methodsToAdd = []): Kernel { $methods[] = 'registerBundles'; - $kernel = $this + $kernelMockBuilder = $this ->getMockBuilder(KernelForTest::class) - ->setMethods($methods) + ->onlyMethods($methods) ->setConstructorArgs(['test', $debug]) - ->getMock() ; + + if (0 !== \count($methodsToAdd)) { + $kernelMockBuilder->addMethods($methodsToAdd); + } + + $kernel = $kernelMockBuilder->getMock(); $kernel->expects($this->any()) ->method('registerBundles') ->willReturn($bundles) diff --git a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php index dfa5f1e4ed9e1..5512399d4c4b3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php @@ -45,7 +45,7 @@ public function testCollect() public function testReset() { $collector = $this->getMockBuilder(DataCollectorInterface::class) - ->setMethods(['collect', 'getName', 'reset']) + ->onlyMethods(['collect', 'getName', 'reset']) ->getMock(); $collector->expects($this->any())->method('getName')->willReturn('mock'); $collector->expects($this->once())->method('reset'); diff --git a/src/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php b/src/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php index d6d7bfb07e66c..259ffd63c0c3f 100644 --- a/src/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php @@ -25,7 +25,7 @@ class ProcessFailedExceptionTest extends TestCase */ public function testProcessFailedExceptionThrowsException() { - $process = $this->getMockBuilder(Process::class)->setMethods(['isSuccessful'])->setConstructorArgs([['php']])->getMock(); + $process = $this->getMockBuilder(Process::class)->onlyMethods(['isSuccessful'])->setConstructorArgs([['php']])->getMock(); $process->expects($this->once()) ->method('isSuccessful') ->willReturn(true); @@ -49,7 +49,7 @@ public function testProcessFailedExceptionPopulatesInformationFromProcessOutput( $errorOutput = 'FATAL: Unexpected error'; $workingDirectory = getcwd(); - $process = $this->getMockBuilder(Process::class)->setMethods(['isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText', 'isOutputDisabled', 'getWorkingDirectory'])->setConstructorArgs([[$cmd]])->getMock(); + $process = $this->getMockBuilder(Process::class)->onlyMethods(['isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText', 'isOutputDisabled', 'getWorkingDirectory'])->setConstructorArgs([[$cmd]])->getMock(); $process->expects($this->once()) ->method('isSuccessful') ->willReturn(false); @@ -97,7 +97,7 @@ public function testDisabledOutputInFailedExceptionDoesNotPopulateOutput() $exitText = 'General error'; $workingDirectory = getcwd(); - $process = $this->getMockBuilder(Process::class)->setMethods(['isSuccessful', 'isOutputDisabled', 'getExitCode', 'getExitCodeText', 'getOutput', 'getErrorOutput', 'getWorkingDirectory'])->setConstructorArgs([[$cmd]])->getMock(); + $process = $this->getMockBuilder(Process::class)->onlyMethods(['isSuccessful', 'isOutputDisabled', 'getExitCode', 'getExitCodeText', 'getOutput', 'getErrorOutput', 'getWorkingDirectory'])->setConstructorArgs([[$cmd]])->getMock(); $process->expects($this->once()) ->method('isSuccessful') ->willReturn(false); diff --git a/src/Symfony/Component/Routing/Tests/Loader/ObjectLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/ObjectLoaderTest.php index 6027c3fd63059..498e1fab6e775 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/ObjectLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/ObjectLoaderTest.php @@ -82,7 +82,7 @@ public function testExceptionOnMethodNotReturningCollection() { $this->expectException(\LogicException::class); $service = $this->getMockBuilder(\stdClass::class) - ->setMethods(['loadRoutes']) + ->addMethods(['loadRoutes']) ->getMock(); $service->expects($this->once()) ->method('loadRoutes') diff --git a/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php index faf5f181a2aa8..2dcadc27e5cc3 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php @@ -26,7 +26,7 @@ protected function getUrlMatcher(RouteCollection $routes, RequestContext $contex return $this->getMockBuilder(TestCompiledRedirectableUrlMatcher::class) ->setConstructorArgs([$compiledRoutes, $context ?? new RequestContext()]) - ->setMethods(['redirect']) + ->onlyMethods(['redirect']) ->getMock(); } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php index 913456775a3f1..ffab6780ce156 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php @@ -486,7 +486,7 @@ private function generateDumpedMatcher(RouteCollection $collection) return $this->getMockBuilder(TestCompiledUrlMatcher::class) ->setConstructorArgs([$compiledRoutes, new RequestContext()]) - ->setMethods(['redirect']) + ->onlyMethods(['redirect']) ->getMock(); } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php index 661ffa4521dd2..11f36629a7f9c 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php @@ -201,7 +201,7 @@ protected function getAuthenticationProvider($supports, $token = null, $exceptio } elseif (null !== $exception) { $provider->expects($this->once()) ->method('authenticate') - ->willThrowException($this->getMockBuilder($exception)->setMethods(null)->getMock()) + ->willThrowException($this->getMockBuilder($exception)->onlyMethods([])->getMock()) ; } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php index 08127b6cbd807..3dbc38988539b 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php @@ -58,7 +58,7 @@ public function testAuthenticate() protected function getSupportedToken($secret) { - $token = $this->getMockBuilder(AnonymousToken::class)->setMethods(['getSecret'])->disableOriginalConstructor()->getMock(); + $token = $this->getMockBuilder(AnonymousToken::class)->onlyMethods(['getSecret'])->disableOriginalConstructor()->getMock(); $token->expects($this->any()) ->method('getSecret') ->willReturn($secret) diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php index 63a9261fadf8a..a40c27f2d517d 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php @@ -310,7 +310,7 @@ public function testPasswordUpgrades() protected function getSupportedToken() { - $mock = $this->getMockBuilder(UsernamePasswordToken::class)->setMethods(['getCredentials', 'getUser', 'getProviderKey'])->disableOriginalConstructor()->getMock(); + $mock = $this->getMockBuilder(UsernamePasswordToken::class)->onlyMethods(['getCredentials', 'getUser', 'getProviderKey'])->disableOriginalConstructor()->getMock(); $mock ->expects($this->any()) ->method('getProviderKey') diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php index e178d9c73993c..341122baa138f 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php @@ -96,7 +96,7 @@ public function testAuthenticateWhenUserCheckerThrowsException() protected function getSupportedToken($user = false, $credentials = false) { - $token = $this->getMockBuilder(PreAuthenticatedToken::class)->setMethods(['getUser', 'getCredentials', 'getFirewallName'])->disableOriginalConstructor()->getMock(); + $token = $this->getMockBuilder(PreAuthenticatedToken::class)->onlyMethods(['getUser', 'getCredentials', 'getFirewallName'])->disableOriginalConstructor()->getMock(); if (false !== $user) { $token->expects($this->once()) ->method('getUser') diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php index 9a6a417b0dff6..d8e5331df92a3 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php @@ -108,7 +108,7 @@ protected function getSupportedToken($user = null, $secret = 'test') ->willReturn([]); } - $token = $this->getMockBuilder(RememberMeToken::class)->setMethods(['getFirewallName'])->setConstructorArgs([$user, 'foo', $secret])->getMock(); + $token = $this->getMockBuilder(RememberMeToken::class)->onlyMethods(['getFirewallName'])->setConstructorArgs([$user, 'foo', $secret])->getMock(); $token ->expects($this->once()) ->method('getFirewallName') diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php index 446a04061d091..8eaf3bb15f378 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php @@ -232,7 +232,7 @@ public function testAuthenticatePreservesOriginalToken() protected function getSupportedToken() { - $mock = $this->getMockBuilder(UsernamePasswordToken::class)->setMethods(['getCredentials', 'getFirewallName', 'getRoles'])->disableOriginalConstructor()->getMock(); + $mock = $this->getMockBuilder(UsernamePasswordToken::class)->onlyMethods(['getCredentials', 'getFirewallName'])->addMethods(['getRoles'])->disableOriginalConstructor()->getMock(); $mock ->expects($this->any()) ->method('getFirewallName') diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php index f8f11d1347289..1009dab6afd95 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php @@ -31,7 +31,7 @@ public function testGetSetToken() $request = new Request(); $request->setSession($session); - $requestStack = $this->getMockBuilder(RequestStack::class)->setMethods(['getSession'])->getMock(); + $requestStack = $this->getMockBuilder(RequestStack::class)->onlyMethods(['getSession'])->getMock(); $requestStack->push($request); $requestStack->expects($this->any())->method('getSession')->willReturnCallback(function () use ($session, &$sessionAccess) { ++$sessionAccess; diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php index 770495137c40e..ebfda2762ac59 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php @@ -186,17 +186,17 @@ public function testAccessDecisionManagerCalledByVoter() { $voter1 = $this ->getMockBuilder(VoterInterface::class) - ->setMethods(['vote']) + ->onlyMethods(['vote']) ->getMock(); $voter2 = $this ->getMockBuilder(VoterInterface::class) - ->setMethods(['vote']) + ->onlyMethods(['vote']) ->getMock(); $voter3 = $this ->getMockBuilder(VoterInterface::class) - ->setMethods(['vote']) + ->onlyMethods(['vote']) ->getMock(); $sut = new TraceableAccessDecisionManager(new AccessDecisionManager([$voter1, $voter2, $voter3])); diff --git a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php index d14bf43d0f91f..4f39ad61f6f3a 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -160,7 +160,7 @@ public function testSessionStrategyIsNotCalledWhenStateless() public function testSessionIsNotInstantiatedOnStatelessFirewall() { $sessionFactory = $this->getMockBuilder(\stdClass::class) - ->setMethods(['__invoke']) + ->addMethods(['__invoke']) ->getMock(); $sessionFactory->expects($this->never()) diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php index 46ac724383519..31018aec4a23f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php @@ -42,7 +42,7 @@ protected function setUp(): void $this->session = $this->createMock(SessionInterface::class); $this->request = $this->createMock(Request::class); $this->request->expects($this->any())->method('getSession')->willReturn($this->session); - $this->exception = $this->getMockBuilder(AuthenticationException::class)->setMethods(['getMessage'])->getMock(); + $this->exception = $this->getMockBuilder(AuthenticationException::class)->onlyMethods(['getMessage'])->getMock(); } public function testForward() diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php index 7135edbcb80b6..ea5b3dd9e02b0 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php @@ -136,7 +136,7 @@ public function testAddsNoPasswordUpgradeBadgeIfItAlreadyExists() $this->hasherFactory->expects($this->any())->method('getPasswordHasher')->with($this->identicalTo($this->user))->willReturn($hasher); $passport = $this->getMockBuilder(Passport::class) - ->setMethods(['addBadge']) + ->onlyMethods(['addBadge']) ->setConstructorArgs([new UserBadge('wouter', function () { return $this->user; }), new PasswordCredentials('ThePa$$word'), [new PasswordUpgradeBadge('ThePa$$word')]]) ->getMock(); @@ -153,7 +153,7 @@ public function testAddsNoPasswordUpgradeBadgeIfPasswordIsInvalid() $this->hasherFactory->expects($this->any())->method('getPasswordHasher')->with($this->identicalTo($this->user))->willReturn($hasher); $passport = $this->getMockBuilder(Passport::class) - ->setMethods(['addBadge']) + ->onlyMethods(['addBadge']) ->setConstructorArgs([new UserBadge('wouter', function () { return $this->user; }), new PasswordCredentials('ThePa$$word'), [new PasswordUpgradeBadge('ThePa$$word')]]) ->getMock(); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index b98dc77651ff8..58905eaf62d1a 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -366,7 +366,7 @@ public function testWithPreviousNotStartedSession() public function testSessionIsNotReported() { - $usageReporter = $this->getMockBuilder(\stdClass::class)->setMethods(['__invoke'])->getMock(); + $usageReporter = $this->getMockBuilder(\stdClass::class)->addMethods(['__invoke'])->getMock(); $usageReporter->expects($this->never())->method('__invoke'); $session = new Session(new MockArraySessionStorage(), null, null, $usageReporter); diff --git a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php index 073dd17f741df..9cc6f0ab868c2 100644 --- a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php @@ -139,12 +139,8 @@ protected function createContext() 'validatePropertyValue', 'getViolations', ]; - // PHPUnit 10 removed MockBuilder::setMethods() - if (method_exists($contextualValidatorMockBuilder, 'onlyMethods')) { - $contextualValidatorMockBuilder->onlyMethods($contextualValidatorMethods); - } else { - $contextualValidatorMockBuilder->setMethods($contextualValidatorMethods); - } + + $contextualValidatorMockBuilder->onlyMethods($contextualValidatorMethods); $contextualValidator = $contextualValidatorMockBuilder->getMock(); $contextualValidator->expects($this->any()) ->method('atPath') diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index 2bb212eaac293..926fba7e66784 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -2091,7 +2091,7 @@ public function testEmptyGroupsArrayDoesNotTriggerDeprecation() $validator = $this ->getMockBuilder(RecursiveValidator::class) ->disableOriginalConstructor() - ->setMethods(['startContext']) + ->onlyMethods(['startContext']) ->getMock(); $validator ->expects($this->once()) @@ -2125,7 +2125,7 @@ public function testRelationBetweenChildAAndChildB() $validator = $this ->getMockBuilder(RecursiveValidator::class) ->disableOriginalConstructor() - ->setMethods(['startContext']) + ->onlyMethods(['startContext']) ->getMock(); $validator ->expects($this->once()) diff --git a/src/Symfony/Contracts/Tests/Cache/CacheTraitTest.php b/src/Symfony/Contracts/Tests/Cache/CacheTraitTest.php index 6572a458381e6..baf6ef4a4b5da 100644 --- a/src/Symfony/Contracts/Tests/Cache/CacheTraitTest.php +++ b/src/Symfony/Contracts/Tests/Cache/CacheTraitTest.php @@ -34,7 +34,7 @@ public function testSave() ->with('computed data'); $cache = $this->getMockBuilder(TestPool::class) - ->setMethods(['getItem', 'save']) + ->onlyMethods(['getItem', 'save']) ->getMock(); $cache->expects($this->once()) ->method('getItem') @@ -60,7 +60,7 @@ public function testNoCallbackCallOnHit() ->method('set'); $cache = $this->getMockBuilder(TestPool::class) - ->setMethods(['getItem', 'save']) + ->onlyMethods(['getItem', 'save']) ->getMock(); $cache->expects($this->once()) @@ -91,7 +91,7 @@ public function testRecomputeOnBetaInf() ->with('computed data'); $cache = $this->getMockBuilder(TestPool::class) - ->setMethods(['getItem', 'save']) + ->onlyMethods(['getItem', 'save']) ->getMock(); $cache->expects($this->once()) @@ -111,7 +111,7 @@ public function testRecomputeOnBetaInf() public function testExceptionOnNegativeBeta() { $cache = $this->getMockBuilder(TestPool::class) - ->setMethods(['getItem', 'save']) + ->onlyMethods(['getItem', 'save']) ->getMock(); $callback = function (CacheItemInterface $item) { From c043e93fd704325aafb9fae3f173b7d9143d5386 Mon Sep 17 00:00:00 2001 From: Lee Rowlands Date: Tue, 7 Mar 2023 10:06:46 +1000 Subject: [PATCH 17/69] Wrap use of \Locale in a class_exists test --- src/Symfony/Component/Translation/LocaleSwitcher.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/LocaleSwitcher.php b/src/Symfony/Component/Translation/LocaleSwitcher.php index 0fc56e3380ef1..48ef4396f29d8 100644 --- a/src/Symfony/Component/Translation/LocaleSwitcher.php +++ b/src/Symfony/Component/Translation/LocaleSwitcher.php @@ -34,7 +34,10 @@ public function __construct( public function setLocale(string $locale): void { - \Locale::setDefault($this->locale = $locale); + if (class_exists(\Locale::class)) { + \Locale::setDefault($locale); + } + $this->locale = $locale; $this->requestContext?->setParameter('_locale', $locale); foreach ($this->localeAwareServices as $service) { From d609b670ff134d2460f07ce57f59559f43d55eba Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 7 Mar 2023 09:33:48 +0100 Subject: [PATCH 18/69] [GHA] use stubs instead of extensions for psalm job --- .github/workflows/integration-tests.yml | 2 +- .github/workflows/psalm.yml | 19 +------------------ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 49056fd7816eb..8e450f82f8f8d 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -159,7 +159,7 @@ jobs: echo COMPOSER_ROOT_VERSION=$COMPOSER_ROOT_VERSION >> $GITHUB_ENV echo "::group::composer update" - composer require --dev --no-update mongodb/mongodb:"1.9.1@dev|^1.9.1@stable" + composer require --dev --no-update mongodb/mongodb composer update --no-progress --ansi echo "::endgroup::" diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index f8f8f4d92db5e..219b8677325d0 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -21,28 +21,11 @@ jobs: env: php-version: '8.1' - extensions: json,couchbase,memcached,mongodb,redis,xsl,ldap,dom steps: - - name: Setup cache environment - id: extcache - uses: shivammathur/cache-extensions@v1 - with: - php-version: ${{ env.php-version }} - extensions: ${{ env.extensions }} - key: cache-v1 # can be any string, change to clear the extension cache. - - - name: Cache extensions - uses: actions/cache@v3 - with: - path: ${{ steps.extcache.outputs.dir }} - key: ${{ steps.extcache.outputs.key }} - restore-keys: ${{ steps.extcache.outputs.key }} - - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ env.php-version }} - extensions: ${{ env.extensions }} ini-values: "memory_limit=-1" coverage: none @@ -60,7 +43,7 @@ jobs: ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" export COMPOSER_ROOT_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+').x-dev composer remove --dev --no-update --no-interaction symfony/phpunit-bridge - composer require --no-progress --ansi --no-plugins psalm/phar phpunit/phpunit:^9.5 php-http/discovery psr/event-dispatcher mongodb/mongodb + composer require --no-progress --ansi --no-plugins psalm/phar phpunit/phpunit:^9.5 php-http/discovery psr/event-dispatcher mongodb/mongodb jetbrains/phpstorm-stubs - name: Generate Psalm baseline run: | From f9077f9bde29b8cbf2c2390079b2019ee3a76650 Mon Sep 17 00:00:00 2001 From: AntoineDly Date: Wed, 8 Mar 2023 11:46:50 +0100 Subject: [PATCH 19/69] [Security] remove deprecated conditions in supports and authenticate methods from AccessListener class --- .../Security/Http/Firewall/AccessListener.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php index ccf3fde9490d8..1194c45e8a32e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php @@ -50,10 +50,7 @@ public function supports(Request $request): ?bool [$attributes] = $this->map->getPatterns($request); $request->attributes->set('_access_control_attributes', $attributes); - if ($attributes && ( - (\defined(AuthenticatedVoter::class.'::IS_AUTHENTICATED_ANONYMOUSLY') ? [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !== $attributes : true) - && [AuthenticatedVoter::PUBLIC_ACCESS] !== $attributes - )) { + if ($attributes && [AuthenticatedVoter::PUBLIC_ACCESS] !== $attributes) { return true; } @@ -72,10 +69,9 @@ public function authenticate(RequestEvent $event) $attributes = $request->attributes->get('_access_control_attributes'); $request->attributes->remove('_access_control_attributes'); - if (!$attributes || (( - (\defined(AuthenticatedVoter::class.'::IS_AUTHENTICATED_ANONYMOUSLY') ? [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] === $attributes : false) - || [AuthenticatedVoter::PUBLIC_ACCESS] === $attributes - ) && $event instanceof LazyResponseEvent)) { + if (!$attributes || ( + [AuthenticatedVoter::PUBLIC_ACCESS] === $attributes && $event instanceof LazyResponseEvent + )) { return; } From 80c7a65c45dcd5608476ea57c408996ce5910070 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Thu, 9 Mar 2023 21:36:58 +0100 Subject: [PATCH 20/69] [Dotenv] Improve Dotenv::usePutenv phpdoc --- src/Symfony/Component/Dotenv/Dotenv.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 4091c673432fa..4406e1fbc218d 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -67,7 +67,7 @@ public function setProdEnvs(array $prodEnvs): self /** * @param bool $usePutenv If `putenv()` should be used to define environment variables or not. - * Beware that `putenv()` is not thread safe, that's why this setting defaults to false + * Beware that `putenv()` is not thread safe, that's why it's not enabled by default * * @return $this */ From 8541643756f031d8ec4d39f04e0564f20a2cff79 Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Fri, 10 Mar 2023 02:15:31 +0100 Subject: [PATCH 21/69] Fix support binary values in parameters. --- src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php | 2 +- .../Tests/Fixtures/containers/container8.php | 2 ++ .../DependencyInjection/Tests/Fixtures/php/services8.php | 2 ++ .../DependencyInjection/Tests/Fixtures/xml/services8.xml | 2 ++ .../DependencyInjection/Tests/Fixtures/yaml/services8.yml | 2 ++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 4f7b16d5f1035..402828b8e001f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -320,7 +320,7 @@ private function convertParameters(array $parameters, string $type, \DOMElement $element->setAttribute('type', 'expression'); $text = $this->document->createTextNode(self::phpToXml((string) $value)); $element->appendChild($text); - } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]*+$/u', $value)) { + } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]*+$/u', $value)) { $element->setAttribute('type', 'binary'); $text = $this->document->createTextNode(self::phpToXml(base64_encode($value))); $element->appendChild($text); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php index aa09db4c0c021..0caa0fe3ef2b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php @@ -9,8 +9,10 @@ 'bar' => 'foo is %%foo bar', 'escape' => '@escapeme', 'values' => [true, false, null, 0, 1000.3, 'true', 'false', 'null'], + 'utf-8 valid string' => "\u{021b}\u{1b56}\ttest", 'binary' => "\xf0\xf0\xf0\xf0", 'binary-control-char' => "This is a Bell char \x07", + 'console banner' => "\e[37;44m#StandWith\e[30;43mUkraine\e[0m", 'null string' => 'null', 'string of digits' => '123', 'string of digits prefixed with minus character' => '-123', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index 827e4bf394cf3..840bab52aa580 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -106,8 +106,10 @@ protected function getDefaultParameters(): array 6 => 'false', 7 => 'null', ], + 'utf-8 valid string' => 'ț᭖ test', 'binary' => '', 'binary-control-char' => 'This is a Bell char ', + 'console banner' => '#StandWithUkraine', 'null string' => 'null', 'string of digits' => '123', 'string of digits prefixed with minus character' => '-123', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml index 906958d622a2b..8e095e7119fa9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml @@ -18,8 +18,10 @@ false null + ț᭖ test 8PDw8A== VGhpcyBpcyBhIEJlbGwgY2hhciAH + G1szNzs0NG0jU3RhbmRXaXRoG1szMDs0M21Va3JhaW5lG1swbQ== null 123 -123 diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml index c410214e54c2b..ef9782f0a018b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml @@ -4,8 +4,10 @@ parameters: bar: 'foo is %%foo bar' escape: '@@escapeme' values: [true, false, null, 0, 1000.3, 'true', 'false', 'null'] + utf-8 valid string: "ț᭖\ttest" binary: !!binary 8PDw8A== binary-control-char: !!binary VGhpcyBpcyBhIEJlbGwgY2hhciAH + console banner: "\e[37;44m#StandWith\e[30;43mUkraine\e[0m" null string: 'null' string of digits: '123' string of digits prefixed with minus character: '-123' From 20477636491959db200730bcb30dfb1d56df5e6e Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 6 Mar 2023 20:42:33 +0100 Subject: [PATCH 22/69] [Tests] Remove occurrences of `withConsecutive()` --- .../Extension/StopwatchExtensionTest.php | 30 ++- .../Tests/Console/ApplicationTest.php | 25 ++- .../Tests/Translation/TranslatorTest.php | 23 ++- .../CacheWarmer/ExpressionCacheWarmerTest.php | 17 +- .../Tests/Adapter/MaxIdLengthAdapterTest.php | 14 +- ...ContainerParametersResourceCheckerTest.php | 19 +- .../Handler/StrictSessionHandlerTest.php | 14 +- .../DebugHandlersListenerTest.php | 8 +- .../EventListener/LocaleAwareListenerTest.php | 36 ++-- .../Component/HttpKernel/Tests/KernelTest.php | 10 +- .../Bundle/Reader/BundleEntryReaderTest.php | 179 ++++++++++++------ .../CheckLdapCredentialsListenerTest.php | 24 ++- .../Tests/Store/DoctrineDbalStoreTest.php | 95 ++++++---- .../Tests/Transport/ConnectionTest.php | 56 +++--- .../Amqp/Tests/Transport/ConnectionTest.php | 64 +++++-- .../Redis/Tests/Transport/ConnectionTest.php | 44 +++-- .../FailedMessagesRemoveCommandTest.php | 76 ++++++-- .../FailedMessagesRetryCommandTest.php | 45 ++++- .../DispatchAfterCurrentBusMiddlewareTest.php | 74 +++++--- .../Middleware/TraceableMiddlewareTest.php | 33 +++- .../Serialization/SerializerTest.php | 61 ++++-- .../Component/Messenger/Tests/WorkerTest.php | 36 ++-- .../Tests/Event/FailedMessageEventTest.php | 14 +- .../PropertyAccessorCollectionTestCase.php | 14 +- .../LdapBindAuthenticationProviderTest.php | 36 +++- .../AccessDecisionManagerTest.php | 13 +- ...efaultAuthenticationFailureHandlerTest.php | 13 +- .../PasswordMigratingListenerTest.php | 14 +- .../Tests/LoginLink/LoginLinkHandlerTest.php | 16 +- .../Normalizer/ArrayDenormalizerTest.php | 44 +++-- .../Bridge/Loco/Tests/LocoProviderTest.php | 7 +- .../Lokalise/Tests/LokaliseProviderTest.php | 7 +- 32 files changed, 796 insertions(+), 365 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php index 59a393744a9e2..d7ff03d72ff98 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\StopwatchExtension; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; use Twig\Environment; use Twig\Error\RuntimeError; use Twig\Loader\ArrayLoader; @@ -67,12 +68,29 @@ protected function getStopwatch($events = []) $expectedStopCalls[] = [$this->equalTo($eventName)]; } - $startInvocationMocker = $stopwatch->expects($this->exactly($expectedCalls)) - ->method('start'); - \call_user_func_array([$startInvocationMocker, 'withConsecutive'], $expectedStartCalls); - $stopInvocationMocker = $stopwatch->expects($this->exactly($expectedCalls)) - ->method('stop'); - \call_user_func_array([$stopInvocationMocker, 'withConsecutive'], $expectedStopCalls); + $stopwatch + ->expects($this->exactly($expectedCalls)) + ->method('start') + ->willReturnCallback(function (string $name, string $category) use (&$expectedStartCalls) { + [$expectedName, $expectedCategory] = array_shift($expectedStartCalls); + + $expectedName->evaluate($name); + $this->assertSame($expectedCategory, $category); + + return $this->createMock(StopwatchEvent::class); + }) + ; + + $stopwatch + ->expects($this->exactly($expectedCalls)) + ->method('stop') + ->willReturnCallback(function (string $name) use (&$expectedStopCalls) { + [$expectedName] = array_shift($expectedStopCalls); + $expectedName->evaluate($name); + + return $this->createMock(StopwatchEvent::class); + }) + ; return $stopwatch; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index d075ad75f32c1..83c8553b2706d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -258,14 +258,31 @@ private function getKernel(array $bundles, $useDispatcher = false) $container ->expects($this->exactly(2)) ->method('hasParameter') - ->withConsecutive(['console.command.ids'], ['console.lazy_command.ids']) - ->willReturnOnConsecutiveCalls(true, true) + ->willReturnCallback(function (...$args) { + static $series = [ + ['console.command.ids'], + ['console.lazy_command.ids'], + ]; + + $this->assertSame(array_shift($series), $args); + + return true; + }) ; + $container ->expects($this->exactly(2)) ->method('getParameter') - ->withConsecutive(['console.lazy_command.ids'], ['console.command.ids']) - ->willReturnOnConsecutiveCalls([], []) + ->willReturnCallback(function (...$args) { + static $series = [ + ['console.lazy_command.ids'], + ['console.command.ids'], + ]; + + $this->assertSame(array_shift($series), $args); + + return []; + }) ; $kernel = $this->createMock(KernelInterface::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index 583ebbb774666..dc00ef99e8210 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -148,18 +148,21 @@ public function testResourceFilesOptionLoadsBeforeOtherAddedResources($debug, $e $loader = $this->createMock(LoaderInterface::class); + $series = [ + /* The "messages.some_locale.loader" is passed via the resource_file option and shall be loaded first */ + [['messages.some_locale.loader', 'some_locale', 'messages'], $someCatalogue], + /* This resource is added by an addResource() call and shall be loaded after the resource_files */ + [['second_resource.some_locale.loader', 'some_locale', 'messages'], $someCatalogue], + ]; + $loader->expects($this->exactly(2)) ->method('load') - ->withConsecutive( - /* The "messages.some_locale.loader" is passed via the resource_file option and shall be loaded first */ - ['messages.some_locale.loader', 'some_locale', 'messages'], - /* This resource is added by an addResource() call and shall be loaded after the resource_files */ - ['second_resource.some_locale.loader', 'some_locale', 'messages'] - ) - ->willReturnOnConsecutiveCalls( - $someCatalogue, - $someCatalogue - ); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }); $options = [ 'resource_files' => ['some_locale' => ['messages.some_locale.loader']], diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/CacheWarmer/ExpressionCacheWarmerTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/CacheWarmer/ExpressionCacheWarmerTest.php index 53b16fcdf7774..d32e2d5de560f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/CacheWarmer/ExpressionCacheWarmerTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/CacheWarmer/ExpressionCacheWarmerTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\CacheWarmer\ExpressionCacheWarmer; use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\ExpressionLanguage\ParsedExpression; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; class ExpressionCacheWarmerTest extends TestCase @@ -22,13 +23,21 @@ public function testWarmUp() { $expressions = [new Expression('A'), new Expression('B')]; + $series = [ + [$expressions[0], ['token', 'user', 'object', 'subject', 'role_names', 'request', 'trust_resolver']], + [$expressions[1], ['token', 'user', 'object', 'subject', 'role_names', 'request', 'trust_resolver']], + ]; + $expressionLang = $this->createMock(ExpressionLanguage::class); $expressionLang->expects($this->exactly(2)) ->method('parse') - ->withConsecutive( - [$expressions[0], ['token', 'user', 'object', 'subject', 'role_names', 'request', 'trust_resolver']], - [$expressions[1], ['token', 'user', 'object', 'subject', 'role_names', 'request', 'trust_resolver']] - ); + ->willReturnCallback(function (...$args) use (&$series) { + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $this->createMock(ParsedExpression::class); + }) + ; (new ExpressionCacheWarmer($expressions, $expressionLang))->warmUp(''); } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php index 7120558f0f369..764817a1e7487 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php @@ -26,10 +26,16 @@ public function testLongKey() $cache->expects($this->exactly(2)) ->method('doHave') - ->withConsecutive( - [$this->equalTo('----------:nWfzGiCgLczv3SSUzXL3kg:')], - [$this->equalTo('----------:---------------------------------------')] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['----------:nWfzGiCgLczv3SSUzXL3kg:'], + ['----------:---------------------------------------'], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }) + ; $cache->hasItem(str_repeat('-', 40)); $cache->hasItem(str_repeat('-', 39)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php b/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php index 3563a313814db..f13acc8f140e2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Config/ContainerParametersResourceCheckerTest.php @@ -64,14 +64,17 @@ public static function isFreshProvider() 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') - ->withConsecutive( - [self::equalTo('locales')], - [self::equalTo('default_locale')] - ) - ->willReturnMap([ - ['locales', ['fr', 'en']], - ['default_locale', 'fr'], - ]) + ->willReturnCallback(function (...$args) { + static $series = [ + [['locales'], ['fr', 'en']], + [['default_locale'], 'fr'], + ]; + + [$expectedArgs, $return] = array_shift($series); + self::assertSame($expectedArgs, $args); + + return $return; + }) ; }, true]; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php index 4f91016ac5cd8..68db5f4cf1cc6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php @@ -84,8 +84,18 @@ public function testReadWithValidateIdMismatch() { $handler = $this->createMock(\SessionHandlerInterface::class); $handler->expects($this->exactly(2))->method('read') - ->withConsecutive(['id1'], ['id2']) - ->will($this->onConsecutiveCalls('data1', 'data2')); + ->willReturnCallback(function (...$args) { + static $series = [ + [['id1'], 'data1'], + [['id2'], 'data2'], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $proxy = new StrictSessionHandler($handler); $this->assertTrue($proxy->validateId('id1')); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php index 81a84e92f17ee..1014c7a180d77 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php @@ -222,7 +222,13 @@ public function testLevelsAssignedToLoggers(bool $hasLogger, bool $hasDeprecatio $handler ->expects($this->exactly(\count($expectedCalls))) ->method('setDefaultLogger') - ->withConsecutive(...$expectedCalls); + ->willReturnCallback(function (LoggerInterface $logger, $levels) use (&$expectedCalls) { + [$expectedLogger, $expectedLevels] = array_shift($expectedCalls); + + $this->assertSame($expectedLogger, $logger); + $this->assertSame($expectedLevels, $levels); + }) + ; $sut = new DebugHandlersListener(null, $logger, $levels, null, true, true, $deprecationLogger); $prevHander = set_exception_handler([$handler, 'handleError']); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleAwareListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleAwareListenerTest.php index 3c89cafd04f01..f6328e250734b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleAwareListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleAwareListenerTest.php @@ -46,16 +46,18 @@ public function testLocaleIsSetInOnKernelRequest() public function testDefaultLocaleIsUsedOnExceptionsInOnKernelRequest() { + $matcher = $this->exactly(2); $this->localeAwareService - ->expects($this->exactly(2)) + ->expects($matcher) ->method('setLocale') - ->withConsecutive( - [$this->anything()], - ['en'] - ) - ->willReturnOnConsecutiveCalls( - $this->throwException(new \InvalidArgumentException()) - ); + ->willReturnCallback(function (string $locale) use ($matcher) { + if (1 === $matcher->getInvocationCount()) { + throw new \InvalidArgumentException(); + } + + $this->assertSame('en', $locale); + }) + ; $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $this->createRequest('fr'), HttpKernelInterface::MAIN_REQUEST); $this->listener->onKernelRequest($event); @@ -90,16 +92,18 @@ public function testLocaleIsSetToDefaultOnKernelFinishRequestWhenParentRequestDo public function testDefaultLocaleIsUsedOnExceptionsInOnKernelFinishRequest() { + $matcher = $this->exactly(2); $this->localeAwareService - ->expects($this->exactly(2)) + ->expects($matcher) ->method('setLocale') - ->withConsecutive( - [$this->anything()], - ['en'] - ) - ->willReturnOnConsecutiveCalls( - $this->throwException(new \InvalidArgumentException()) - ); + ->willReturnCallback(function (string $locale) use ($matcher) { + if (1 === $matcher->getInvocationCount()) { + throw new \InvalidArgumentException(); + } + + $this->assertSame('en', $locale); + }) + ; $this->requestStack->push($this->createRequest('fr')); $this->requestStack->push($subRequest = $this->createRequest('de')); diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index fa2074694ee99..3ff7bed430467 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -182,10 +182,12 @@ public function testShutdownGivesNullContainerToAllBundles() $bundle = $this->createMock(Bundle::class); $bundle->expects($this->exactly(2)) ->method('setContainer') - ->withConsecutive( - [$this->isInstanceOf(ContainerInterface::class)], - [null] - ); + ->willReturnCallback(function ($container) { + if (null !== $container) { + $this->assertInstanceOf(ContainerInterface::class, $container); + } + }) + ; $kernel = $this->getKernel(['getBundles']); $kernel->expects($this->any()) diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php index 267857bc78c0e..8d6c91f9d0101 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php @@ -84,11 +84,18 @@ public function testReadEntireDataFileIfNoIndicesGiven() { $this->readerImpl->expects($this->exactly(2)) ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en'], - [self::RES_DIR, 'root'] - ) - ->willReturnOnConsecutiveCalls(self::DATA, self::FALLBACK_DATA); + ->willReturnCallback(function (...$args) { + static $series = [ + [[self::RES_DIR, 'en'], self::DATA], + [[self::RES_DIR, 'root'], self::FALLBACK_DATA], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $this->assertSame(self::MERGED_DATA, $this->reader->readEntry(self::RES_DIR, 'en', [])); } @@ -118,11 +125,18 @@ public function testFallbackIfEntryDoesNotExist() { $this->readerImpl->expects($this->exactly(2)) ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls(self::DATA, self::FALLBACK_DATA); + ->willReturnCallback(function (...$args) { + static $series = [ + [[self::RES_DIR, 'en_GB'], self::DATA], + [[self::RES_DIR, 'en'], self::FALLBACK_DATA], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $this->assertSame('Lah', $this->reader->readEntry(self::RES_DIR, 'en_GB', ['Entries', 'Bam'])); } @@ -140,16 +154,25 @@ public function testDontFallbackIfEntryDoesNotExistAndFallbackDisabled() public function testFallbackIfLocaleDoesNotExist() { + $exception = new ResourceBundleNotFoundException(); + $series = [ + [[self::RES_DIR, 'en_GB'], $exception], + [[self::RES_DIR, 'en'], self::FALLBACK_DATA], + ]; + $this->readerImpl->expects($this->exactly(2)) ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls( - $this->throwException(new ResourceBundleNotFoundException()), - self::FALLBACK_DATA - ); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + if ($return instanceof \Exception) { + throw $return; + } + + return $return; + }) + ; $this->assertSame('Lah', $this->reader->readEntry(self::RES_DIR, 'en_GB', ['Entries', 'Bam'])); } @@ -184,13 +207,20 @@ public static function provideMergeableValues() public function testMergeDataWithFallbackData($childData, $parentData, $result) { if (null === $childData || \is_array($childData)) { + $series = [ + [[self::RES_DIR, 'en'], $childData], + [[self::RES_DIR, 'root'], $parentData], + ]; + $this->readerImpl->expects($this->exactly(2)) ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en'], - [self::RES_DIR, 'root'] - ) - ->willReturnOnConsecutiveCalls($childData, $parentData); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; } else { $this->readerImpl->expects($this->once()) ->method('read') @@ -220,16 +250,20 @@ public function testDontMergeDataIfFallbackDisabled($childData, $parentData, $re public function testMergeExistingEntryWithExistingFallbackEntry($childData, $parentData, $result) { if (null === $childData || \is_array($childData)) { + $series = [ + [[self::RES_DIR, 'en'], ['Foo' => ['Bar' => $childData]]], + [[self::RES_DIR, 'root'], ['Foo' => ['Bar' => $parentData]]], + ]; + $this->readerImpl->expects($this->exactly(2)) ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en'], - [self::RES_DIR, 'root'] - ) - ->willReturnOnConsecutiveCalls( - ['Foo' => ['Bar' => $childData]], - ['Foo' => ['Bar' => $parentData]] - ); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; } else { $this->readerImpl->expects($this->once()) ->method('read') @@ -245,13 +279,19 @@ public function testMergeExistingEntryWithExistingFallbackEntry($childData, $par */ public function testMergeNonExistingEntryWithExistingFallbackEntry($childData, $parentData, $result) { + $series = [ + [[self::RES_DIR, 'en_GB'], ['Foo' => 'Baz']], + [[self::RES_DIR, 'en'], ['Foo' => ['Bar' => $parentData]]], + ]; + $this->readerImpl ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls(['Foo' => 'Baz'], ['Foo' => ['Bar' => $parentData]]); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + + return $expectedArgs === $args ? $return : null; + }) + ; $this->assertSame($parentData, $this->reader->readEntry(self::RES_DIR, 'en_GB', ['Foo', 'Bar'], true)); } @@ -262,13 +302,19 @@ public function testMergeNonExistingEntryWithExistingFallbackEntry($childData, $ public function testMergeExistingEntryWithNonExistingFallbackEntry($childData, $parentData, $result) { if (null === $childData || \is_array($childData)) { + $series = [ + [[self::RES_DIR, 'en_GB'], ['Foo' => ['Bar' => $childData]]], + [[self::RES_DIR, 'en'], ['Foo' => 'Bar']], + ]; + $this->readerImpl ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls(['Foo' => ['Bar' => $childData]], ['Foo' => 'Bar']); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + + return $expectedArgs === $args ? $return : null; + }) + ; } else { $this->readerImpl->expects($this->once()) ->method('read') @@ -282,13 +328,20 @@ public function testMergeExistingEntryWithNonExistingFallbackEntry($childData, $ public function testFailIfEntryFoundNeitherInParentNorChild() { $this->expectException(MissingResourceException::class); + $this->readerImpl ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls(['Foo' => 'Baz'], ['Foo' => 'Bar']); + ->willReturnCallback(function (...$args) { + static $series = [ + [[self::RES_DIR, 'en_GB'], ['Foo' => 'Baz']], + [[self::RES_DIR, 'en'], ['Foo' => 'Bar']], + ]; + + [$expectedArgs, $return] = array_shift($series); + + return $expectedArgs === $args ? $return : null; + }) + ; $this->reader->readEntry(self::RES_DIR, 'en_GB', ['Foo', 'Bar'], true); } @@ -302,13 +355,19 @@ public function testMergeTraversables($childData, $parentData, $result) $childData = \is_array($childData) ? new \ArrayObject($childData) : $childData; if (null === $childData || $childData instanceof \ArrayObject) { + $series = [ + [[self::RES_DIR, 'en_GB'], ['Foo' => ['Bar' => $childData]]], + [[self::RES_DIR, 'en'], ['Foo' => ['Bar' => $parentData]]], + ]; + $this->readerImpl ->method('read') - ->withConsecutive( - [self::RES_DIR, 'en_GB'], - [self::RES_DIR, 'en'] - ) - ->willReturnOnConsecutiveCalls(['Foo' => ['Bar' => $childData]], ['Foo' => ['Bar' => $parentData]]); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + + return $expectedArgs === $args ? $return : null; + }) + ; } else { $this->readerImpl->expects($this->once()) ->method('read') @@ -327,14 +386,20 @@ public function testFollowLocaleAliases($childData, $parentData, $result) $this->reader->setLocaleAliases(['mo' => 'ro_MD']); if (null === $childData || \is_array($childData)) { + $series = [ + [[self::RES_DIR, 'ro_MD'], ['Foo' => ['Bar' => $childData]]], + // Read fallback locale of aliased locale ("ro_MD" -> "ro") + [[self::RES_DIR, 'ro'], ['Foo' => ['Bar' => $parentData]]], + ]; + $this->readerImpl ->method('read') - ->withConsecutive( - [self::RES_DIR, 'ro_MD'], - // Read fallback locale of aliased locale ("ro_MD" -> "ro") - [self::RES_DIR, 'ro'] - ) - ->willReturnOnConsecutiveCalls(['Foo' => ['Bar' => $childData]], ['Foo' => ['Bar' => $parentData]]); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + + return $expectedArgs === $args ? $return : null; + }) + ; } else { $this->readerImpl->expects($this->once()) ->method('read') diff --git a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php index b9a63138250a2..2ca270f41fc1a 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php @@ -170,9 +170,15 @@ public function toArray(): array $this->ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 's3cr3t'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $this->ldap->expects($this->any())->method('escape')->with('Wouter', '', LdapInterface::ESCAPE_FILTER)->willReturn('wouter'); $this->ldap->expects($this->once())->method('query')->with('{username}', 'wouter_test')->willReturn($query); @@ -192,9 +198,15 @@ public function testEmptyQueryResultShouldThrowAnException() $this->ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 's3cr3t'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $this->ldap->method('escape')->willReturnArgument(0); $this->ldap->expects($this->once())->method('query')->willReturn($query); diff --git a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php index 1bd70d5aa8d4d..8cd451a6f097c 100644 --- a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php @@ -99,22 +99,27 @@ public static function provideDsn() public function testCreatesTableInTransaction(string $platform) { $conn = $this->createMock(Connection::class); + + $series = [ + [$this->stringContains('INSERT INTO'), $this->createMock(TableNotFoundException::class)], + [$this->matches('create sql stmt'), 1], + [$this->stringContains('INSERT INTO'), 1], + ]; + $conn->expects($this->atLeast(3)) ->method('executeStatement') - ->withConsecutive( - [$this->stringContains('INSERT INTO')], - [$this->matches('create sql stmt')], - [$this->stringContains('INSERT INTO')] - ) - ->will( - $this->onConsecutiveCalls( - $this->throwException( - $this->createMock(TableNotFoundException::class) - ), - 1, - 1 - ) - ); + ->willReturnCallback(function ($sql) use (&$series) { + if ([$constraint, $return] = array_shift($series)) { + $constraint->evaluate($sql); + } + + if ($return instanceof \Exception) { + throw $return; + } + + return $return ?? 1; + }) + ; $conn->method('isTransactionActive') ->willReturn(true); @@ -145,21 +150,25 @@ public static function providePlatforms() public function testTableCreationInTransactionNotSupported() { $conn = $this->createMock(Connection::class); + + $series = [ + [$this->stringContains('INSERT INTO'), $this->createMock(TableNotFoundException::class)], + [$this->stringContains('INSERT INTO'), 1], + ]; + $conn->expects($this->atLeast(2)) ->method('executeStatement') - ->withConsecutive( - [$this->stringContains('INSERT INTO')], - [$this->stringContains('INSERT INTO')] - ) - ->will( - $this->onConsecutiveCalls( - $this->throwException( - $this->createMock(TableNotFoundException::class) - ), - 1, - 1 - ) - ); + ->willReturnCallback(function ($sql) use (&$series) { + [$constraint, $return] = array_shift($series); + $constraint->evaluate($sql); + + if ($return instanceof \Exception) { + throw $return; + } + + return $return; + }) + ; $conn->method('isTransactionActive') ->willReturn(true); @@ -181,22 +190,26 @@ public function testTableCreationInTransactionNotSupported() public function testCreatesTableOutsideTransaction() { $conn = $this->createMock(Connection::class); + + $series = [ + [$this->stringContains('INSERT INTO'), $this->createMock(TableNotFoundException::class)], + [$this->matches('create sql stmt'), 1], + [$this->stringContains('INSERT INTO'), 1], + ]; + $conn->expects($this->atLeast(3)) ->method('executeStatement') - ->withConsecutive( - [$this->stringContains('INSERT INTO')], - [$this->matches('create sql stmt')], - [$this->stringContains('INSERT INTO')] - ) - ->will( - $this->onConsecutiveCalls( - $this->throwException( - $this->createMock(TableNotFoundException::class) - ), - 1, - 1 - ) - ); + ->willReturnCallback(function ($sql) use (&$series) { + [$constraint, $return] = array_shift($series); + $constraint->evaluate($sql); + + if ($return instanceof \Exception) { + throw $return; + } + + return $return; + }) + ; $conn->method('isTransactionActive') ->willReturn(false); diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php index b36f02a8850d0..6297435ee1ef3 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php @@ -210,36 +210,36 @@ public function testKeepGettingPendingMessages() ->method('getQueueUrl') ->with(['QueueName' => 'queue', 'QueueOwnerAWSAccountId' => 123]) ->willReturn(ResultMockFactory::create(GetQueueUrlResult::class, ['QueueUrl' => 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue'])); + + $firstResult = ResultMockFactory::create(ReceiveMessageResult::class, ['Messages' => [ + new Message(['MessageId' => 1, 'Body' => 'this is a test']), + new Message(['MessageId' => 2, 'Body' => 'this is a test']), + new Message(['MessageId' => 3, 'Body' => 'this is a test']), + ]]); + $secondResult = ResultMockFactory::create(ReceiveMessageResult::class, ['Messages' => []]); + + $series = [ + [[['QueueUrl' => 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue', + 'VisibilityTimeout' => null, + 'MaxNumberOfMessages' => 9, + 'MessageAttributeNames' => ['All'], + 'WaitTimeSeconds' => 20]], $firstResult], + [[['QueueUrl' => 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue', + 'VisibilityTimeout' => null, + 'MaxNumberOfMessages' => 9, + 'MessageAttributeNames' => ['All'], + 'WaitTimeSeconds' => 20]], $secondResult], + ]; + $client->expects($this->exactly(2)) ->method('receiveMessage') - ->withConsecutive( - [ - [ - 'QueueUrl' => 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue', - 'MaxNumberOfMessages' => 9, - 'WaitTimeSeconds' => 20, - 'MessageAttributeNames' => ['All'], - 'VisibilityTimeout' => null, - ], - ], - [ - [ - 'QueueUrl' => 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue', - 'MaxNumberOfMessages' => 9, - 'WaitTimeSeconds' => 20, - 'MessageAttributeNames' => ['All'], - 'VisibilityTimeout' => null, - ], - ] - ) - ->willReturnOnConsecutiveCalls( - ResultMockFactory::create(ReceiveMessageResult::class, ['Messages' => [ - new Message(['MessageId' => 1, 'Body' => 'this is a test']), - new Message(['MessageId' => 2, 'Body' => 'this is a test']), - new Message(['MessageId' => 3, 'Body' => 'this is a test']), - ]]), - ResultMockFactory::create(ReceiveMessageResult::class, ['Messages' => []]) - ); + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $connection = new Connection(['queue_name' => 'queue', 'account' => 123, 'auto_setup' => false], $client); $this->assertNotNull($connection->get()); 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 1f98b4a725a3b..1b39dc7d1a445 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php @@ -311,15 +311,29 @@ public function testItSetupsTheConnection() $amqpExchange->expects($this->once())->method('declareExchange'); $amqpExchange->expects($this->once())->method('publish')->with('body', 'routing_key', \AMQP_NOPARAM, ['headers' => [], 'delivery_mode' => 2, 'timestamp' => time()]); $amqpQueue0->expects($this->once())->method('declareQueue'); - $amqpQueue0->expects($this->exactly(2))->method('bind')->withConsecutive( - [self::DEFAULT_EXCHANGE_NAME, 'binding_key0'], - [self::DEFAULT_EXCHANGE_NAME, 'binding_key1'] - ); + $amqpQueue0->expects($this->exactly(2))->method('bind') + ->willReturnCallback(function (...$args) { + static $series = [ + [self::DEFAULT_EXCHANGE_NAME, 'binding_key0', []], + [self::DEFAULT_EXCHANGE_NAME, 'binding_key1', []], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }) + ; $amqpQueue1->expects($this->once())->method('declareQueue'); - $amqpQueue1->expects($this->exactly(2))->method('bind')->withConsecutive( - [self::DEFAULT_EXCHANGE_NAME, 'binding_key2'], - [self::DEFAULT_EXCHANGE_NAME, 'binding_key3'] - ); + $amqpQueue1->expects($this->exactly(2))->method('bind') + ->willReturnCallback(function (...$args) { + static $series = [ + [self::DEFAULT_EXCHANGE_NAME, 'binding_key2', []], + [self::DEFAULT_EXCHANGE_NAME, 'binding_key3', []], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }) + ; $dsn = 'amqp://localhost?'. 'exchange[default_publish_routing_key]=routing_key&'. @@ -349,15 +363,29 @@ public function testItSetupsTheTTLConnection() $amqpExchange->expects($this->once())->method('declareExchange'); $amqpExchange->expects($this->once())->method('publish')->with('body', 'routing_key', \AMQP_NOPARAM, ['headers' => [], 'delivery_mode' => 2, 'timestamp' => time()]); $amqpQueue0->expects($this->once())->method('declareQueue'); - $amqpQueue0->expects($this->exactly(2))->method('bind')->withConsecutive( - [self::DEFAULT_EXCHANGE_NAME, 'binding_key0'], - [self::DEFAULT_EXCHANGE_NAME, 'binding_key1'] - ); + $amqpQueue0->expects($this->exactly(2))->method('bind') + ->willReturnCallback(function (...$args) { + static $series = [ + [self::DEFAULT_EXCHANGE_NAME, 'binding_key0', []], + [self::DEFAULT_EXCHANGE_NAME, 'binding_key1', []], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }) + ; $amqpQueue1->expects($this->once())->method('declareQueue'); - $amqpQueue1->expects($this->exactly(2))->method('bind')->withConsecutive( - [self::DEFAULT_EXCHANGE_NAME, 'binding_key2'], - [self::DEFAULT_EXCHANGE_NAME, 'binding_key3'] - ); + $amqpQueue1->expects($this->exactly(2))->method('bind') + ->willReturnCallback(function (...$args) { + static $series = [ + [self::DEFAULT_EXCHANGE_NAME, 'binding_key2', []], + [self::DEFAULT_EXCHANGE_NAME, 'binding_key3', []], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }) + ; $dsn = 'amqps://localhost?'. 'cacert=/etc/ssl/certs&'. @@ -387,9 +415,7 @@ public function testBindingArguments() $amqpExchange->expects($this->once())->method('declareExchange'); $amqpExchange->expects($this->once())->method('publish')->with('body', null, \AMQP_NOPARAM, ['headers' => [], 'delivery_mode' => 2, 'timestamp' => time()]); $amqpQueue->expects($this->once())->method('declareQueue'); - $amqpQueue->expects($this->exactly(1))->method('bind')->withConsecutive( - [self::DEFAULT_EXCHANGE_NAME, null, ['x-match' => 'all']] - ); + $amqpQueue->expects($this->exactly(1))->method('bind')->with(self::DEFAULT_EXCHANGE_NAME, null, ['x-match' => 'all']); $dsn = 'amqp://localhost?exchange[type]=headers'. '&queues[queue0][binding_arguments][x-match]=all'; 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 c27931227eb26..fb98baf70b610 100644 --- a/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php @@ -272,12 +272,22 @@ public function testClaimAbandonedMessageWithRaceCondition() $redis = $this->createMock(\Redis::class); $redis->expects($this->exactly(3))->method('xreadgroup') - ->withConsecutive( - ['symfony', 'consumer', ['queue' => '0'], 1, null], // first call for pending messages - ['symfony', 'consumer', ['queue' => '0'], 1, null], // second call because of claimed message (redisid-123) - ['symfony', 'consumer', ['queue' => '>'], 1, null] // third call because of no result (other consumer claimed message redisid-123) - ) - ->willReturnOnConsecutiveCalls([], [], []); + ->willReturnCallback(function (...$args) { + static $series = [ + // first call for pending messages + [['symfony', 'consumer', ['queue' => '0'], 1, null], []], + // second call because of claimed message (redisid-123) + [['symfony', 'consumer', ['queue' => '0'], 1, null], []], + // third call because of no result (other consumer claimed message redisid-123) + [['symfony', 'consumer', ['queue' => '>'], 1, null], []], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $redis->expects($this->once())->method('xpending')->willReturn([[ 0 => 'redisid-123', // message-id @@ -298,14 +308,20 @@ public function testClaimAbandonedMessage() $redis = $this->createMock(\Redis::class); $redis->expects($this->exactly(2))->method('xreadgroup') - ->withConsecutive( - ['symfony', 'consumer', ['queue' => '0'], 1, null], // first call for pending messages - ['symfony', 'consumer', ['queue' => '0'], 1, null] // second call because of claimed message (redisid-123) - ) - ->willReturnOnConsecutiveCalls( - [], // first call returns no result - ['queue' => [['message' => '{"body":"1","headers":[]}']]] // second call returns claimed message (redisid-123) - ); + ->willReturnCallback(function (...$args) { + static $series = [ + // first call for pending messages + [['symfony', 'consumer', ['queue' => '0'], 1, null], []], + // second call because of claimed message (redisid-123) + [['symfony', 'consumer', ['queue' => '0'], 1, null], ['queue' => [['message' => '{"body":"1","headers":[]}']]]], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $redis->expects($this->once())->method('xpending')->willReturn([[ 0 => 'redisid-123', // message-id diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php index 771ab1297b5b9..c5617c15981a7 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php @@ -173,11 +173,21 @@ public function testThrowExceptionIfFailureTransportNotDefinedWithServiceLocator public function testRemoveMultipleMessages() { $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(3))->method('find')->withConsecutive([20], [30], [40])->willReturnOnConsecutiveCalls( - new Envelope(new \stdClass()), - null, - new Envelope(new \stdClass()) - ); + + $series = [ + [[20], new Envelope(new \stdClass())], + [[30], null], + [[40], new Envelope(new \stdClass())], + ]; + + $receiver->expects($this->exactly(3))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $command = new FailedMessagesRemoveCommand( 'failure_receiver', @@ -197,11 +207,21 @@ public function testRemoveMultipleMessagesWithServiceLocator() { $globalFailureReceiverName = 'failure_receiver'; $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(3))->method('find')->withConsecutive([20], [30], [40])->willReturnOnConsecutiveCalls( - new Envelope(new \stdClass()), - null, - new Envelope(new \stdClass()) - ); + + $series = [ + [[20], new Envelope(new \stdClass())], + [[30], null], + [[40], new Envelope(new \stdClass())], + ]; + + $receiver->expects($this->exactly(3))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $serviceLocator = $this->createMock(ServiceLocator::class); $serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true); @@ -227,10 +247,20 @@ public function testRemoveMultipleMessagesWithServiceLocator() public function testRemoveMultipleMessagesAndDisplayMessages() { $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(2))->method('find')->withConsecutive([20], [30])->willReturnOnConsecutiveCalls( - new Envelope(new \stdClass()), - new Envelope(new \stdClass()) - ); + + $series = [ + [[20], new Envelope(new \stdClass())], + [[30], new Envelope(new \stdClass())], + ]; + + $receiver->expects($this->exactly(2))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $command = new FailedMessagesRemoveCommand( 'failure_receiver', @@ -249,10 +279,20 @@ public function testRemoveMultipleMessagesAndDisplayMessagesWithServiceLocator() { $globalFailureReceiverName = 'failure_receiver'; $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(2))->method('find')->withConsecutive([20], [30])->willReturnOnConsecutiveCalls( - new Envelope(new \stdClass()), - new Envelope(new \stdClass()) - ); + + $series = [ + [[20], new Envelope(new \stdClass())], + [[30], new Envelope(new \stdClass())], + ]; + + $receiver->expects($this->exactly(2))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $serviceLocator = $this->createMock(ServiceLocator::class); $serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true); diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php index 2f0c09552be8f..37372a2d3a8b7 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php @@ -29,8 +29,21 @@ class FailedMessagesRetryCommandTest extends TestCase */ public function testBasicRun() { + $series = [ + [[10], new Envelope(new \stdClass())], + [[12], new Envelope(new \stdClass())], + ]; + $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(2))->method('find')->withConsecutive([10], [12])->willReturn(new Envelope(new \stdClass())); + $receiver->expects($this->exactly(2))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; + // message will eventually be ack'ed in Worker $receiver->expects($this->exactly(2))->method('ack'); @@ -54,8 +67,21 @@ public function testBasicRun() public function testBasicRunWithServiceLocator() { + $series = [ + [[10], new Envelope(new \stdClass())], + [[12], new Envelope(new \stdClass())], + ]; + $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(2))->method('find')->withConsecutive([10], [12])->willReturn(new Envelope(new \stdClass())); + $receiver->expects($this->exactly(2))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; + // message will eventually be ack'ed in Worker $receiver->expects($this->exactly(2))->method('ack'); @@ -119,8 +145,21 @@ public function testBasicRunWithServiceLocatorMultipleFailedTransportsDefined() public function testBasicRunWithServiceLocatorWithSpecificFailureTransport() { + $series = [ + [[10], new Envelope(new \stdClass())], + [[12], new Envelope(new \stdClass())], + ]; + $receiver = $this->createMock(ListableReceiverInterface::class); - $receiver->expects($this->exactly(2))->method('find')->withConsecutive([10], [12])->willReturn(new Envelope(new \stdClass())); + $receiver->expects($this->exactly(2))->method('find') + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; + // message will eventually be ack'ed in Worker $receiver->expects($this->exactly(2))->method('ack'); diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php index c6a1a34da75d4..b0cc4c4f2ed87 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php @@ -52,17 +52,21 @@ public function testEventsInNewTransactionAreHandledAfterMainMessage() $handlingMiddleware, ]); + $series = [ + // Third event is dispatch within main dispatch, but before its handling: + $thirdEvent, + // Then expect main dispatched message to be handled first: + $message, + // Then, expect events in new transaction to be handled next, in dispatched order: + $firstEvent, + $secondEvent, + ]; + $handlingMiddleware->expects($this->exactly(4)) ->method('handle') - ->withConsecutive( - // Third event is dispatch within main dispatch, but before its handling: - [$this->expectHandledMessage($thirdEvent)], - // Then expect main dispatched message to be handled first: - [$this->expectHandledMessage($message)], - // Then, expect events in new transaction to be handled next, in dispatched order: - [$this->expectHandledMessage($firstEvent)], - [$this->expectHandledMessage($secondEvent)] - ) + ->with($this->callback(function (Envelope $envelope) use (&$series) { + return $envelope->getMessage() === array_shift($series); + })) ->willReturnOnConsecutiveCalls( $this->willHandleMessage(), $this->willHandleMessage(), @@ -97,16 +101,20 @@ public function testThrowingEventsHandlingWontStopExecution() $handlingMiddleware, ]); + $series = [ + // Expect main dispatched message to be handled first: + $message, + // Then, expect events in new transaction to be handled next, in dispatched order: + $firstEvent, + // Next event is still handled despite the previous exception: + $secondEvent, + ]; + $handlingMiddleware->expects($this->exactly(3)) ->method('handle') - ->withConsecutive( - // Expect main dispatched message to be handled first: - [$this->expectHandledMessage($message)], - // Then, expect events in new transaction to be handled next, in dispatched order: - [$this->expectHandledMessage($firstEvent)], - // Next event is still handled despite the previous exception: - [$this->expectHandledMessage($secondEvent)] - ) + ->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')), @@ -153,22 +161,26 @@ public function testLongChainWithExceptions() ]); // Handling $eventL1b will dispatch 2 more events + $series = [ + // Expect main dispatched message to be handled first: + $command, + $eventL1a, + $eventL1b, + $eventL1c, + // Handle $eventL2a will dispatch event and throw exception + $eventL2a, + // Make sure $eventL2b is handled, since it was dispatched from $eventL1b + $eventL2b, + // We don't handle exception L3a since L2a threw an exception. + $eventL3b, + // Note: $eventL3a should not be handled. + ]; + $handlingMiddleware->expects($this->exactly(7)) ->method('handle') - ->withConsecutive( - // Expect main dispatched message to be handled first: - [$this->expectHandledMessage($command)], - [$this->expectHandledMessage($eventL1a)], - [$this->expectHandledMessage($eventL1b)], - [$this->expectHandledMessage($eventL1c)], - // Handle $eventL2a will dispatch event and throw exception - [$this->expectHandledMessage($eventL2a)], - // Make sure $eventL2b is handled, since it was dispatched from $eventL1b - [$this->expectHandledMessage($eventL2b)], - // We dont handle exception L3a since L2a threw an exception. - [$this->expectHandledMessage($eventL3b)] - // Note: $eventL3a should not be handled. - ) + ->with($this->callback(function (Envelope $envelope) use (&$series) { + return $envelope->getMessage() === array_shift($series); + })) ->willReturnOnConsecutiveCalls( $this->willHandleMessage(), $this->willHandleMessage(), diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/TraceableMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/TraceableMiddlewareTest.php index 65287f4972aa5..a0006bbf05e07 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/TraceableMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/TraceableMiddlewareTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; /** * @author Maxime Steinhausser @@ -43,19 +44,35 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $stopwatch = $this->createMock(Stopwatch::class); $stopwatch->expects($this->exactly(2))->method('isStarted')->willReturn(true); + + $series = [ + [$this->matches('"%sMiddlewareInterface%s" on "command_bus"'), 'messenger.middleware'], + [$this->identicalTo('Tail on "command_bus"'), 'messenger.middleware'], + ]; + $stopwatch->expects($this->exactly(2)) ->method('start') - ->withConsecutive( - [$this->matches('"%sMiddlewareInterface%s" on "command_bus"'), 'messenger.middleware'], - ['Tail on "command_bus"', 'messenger.middleware'] - ) + ->willReturnCallback(function (string $name, string $category = null) use (&$series) { + [$constraint, $expectedCategory] = array_shift($series); + + $constraint->evaluate($name); + $this->assertSame($expectedCategory, $category); + + return $this->createMock(StopwatchEvent::class); + }) ; $stopwatch->expects($this->exactly(2)) ->method('stop') - ->withConsecutive( - ['"Symfony\Component\Messenger\Middleware\MiddlewareInterface@anonymous" on "command_bus"'], - ['Tail on "command_bus"'] - ) + ->willReturnCallback(function (string $name) { + static $stopSeries = [ + '"Symfony\Component\Messenger\Middleware\MiddlewareInterface@anonymous" on "command_bus"', + 'Tail on "command_bus"', + ]; + + $this->assertSame(array_shift($stopSeries), $name); + + return $this->createMock(StopwatchEvent::class); + }) ; $traced = new TraceableMiddleware($stopwatch, $busId); diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php index d749d2d17fb7f..a2dc737a953cf 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Messenger\Tests\Transport\Serialization; +use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\MessageDecodingFailedException; @@ -83,20 +84,32 @@ public function testEncodedWithSymfonySerializerForStamps() ); $envelope = (new Envelope($message = new DummyMessage('test'))) - ->with($serializerStamp = new SerializerStamp([ObjectNormalizer::GROUPS => ['foo']])) - ->with($validationStamp = new ValidationStamp(['foo', 'bar'])); + ->with(new SerializerStamp([ObjectNormalizer::GROUPS => ['foo']])) + ->with(new ValidationStamp(['foo', 'bar'])); + + $series = [ + [$this->anything()], + [$this->anything()], + [$message, 'json', [ + ObjectNormalizer::GROUPS => ['foo'], + Serializer::MESSENGER_SERIALIZATION_CONTEXT => true, + ]], + ]; $symfonySerializer ->expects($this->exactly(3)) ->method('serialize') - ->withConsecutive( - [$this->anything()], - [$this->anything()], - [$message, 'json', [ - ObjectNormalizer::GROUPS => ['foo'], - Serializer::MESSENGER_SERIALIZATION_CONTEXT => true, - ]] - ) + ->willReturnCallback(function (...$args) use (&$series) { + $expectedArgs = array_shift($series); + + if ($expectedArgs[0] instanceof Constraint) { + $expectedArgs[0]->evaluate($args); + } else { + $this->assertSame($expectedArgs, $args); + } + + return '{}'; + }) ; $encoded = $serializer->encode($envelope); @@ -114,20 +127,26 @@ public function testDecodeWithSymfonySerializerStamp() $symfonySerializer = $this->createMock(SerializerComponentInterface::class) ); + $series = [ + [ + ['[{"context":{"groups":["foo"]}}]', SerializerStamp::class.'[]', 'json', [Serializer::MESSENGER_SERIALIZATION_CONTEXT => true]], + [new SerializerStamp(['groups' => ['foo']])], + ], + [ + ['{}', DummyMessage::class, 'json', [ObjectNormalizer::GROUPS => ['foo'], Serializer::MESSENGER_SERIALIZATION_CONTEXT => true]], + new DummyMessage('test'), + ], + ]; + $symfonySerializer ->expects($this->exactly(2)) ->method('deserialize') - ->withConsecutive( - ['[{"context":{"groups":["foo"]}}]', SerializerStamp::class.'[]', 'json', [Serializer::MESSENGER_SERIALIZATION_CONTEXT => true]], - ['{}', DummyMessage::class, 'json', [ - ObjectNormalizer::GROUPS => ['foo'], - Serializer::MESSENGER_SERIALIZATION_CONTEXT => true, - ]] - ) - ->willReturnOnConsecutiveCalls( - [new SerializerStamp(['groups' => ['foo']])], - new DummyMessage('test') - ) + ->willReturnCallback(function (...$args) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) ; $serializer->decode([ diff --git a/src/Symfony/Component/Messenger/Tests/WorkerTest.php b/src/Symfony/Component/Messenger/Tests/WorkerTest.php index 4d0f79b10e41a..d98e9f51e0a8a 100644 --- a/src/Symfony/Component/Messenger/Tests/WorkerTest.php +++ b/src/Symfony/Component/Messenger/Tests/WorkerTest.php @@ -177,15 +177,19 @@ public function testWorkerDispatchesEventsOnSuccess() $eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $series = [ + $this->isInstanceOf(WorkerStartedEvent::class), + $this->isInstanceOf(WorkerMessageReceivedEvent::class), + $this->isInstanceOf(WorkerMessageHandledEvent::class), + $this->isInstanceOf(WorkerRunningEvent::class), + $this->isInstanceOf(WorkerStoppedEvent::class), + ]; + $eventDispatcher->expects($this->exactly(5)) ->method('dispatch') - ->withConsecutive( - [$this->isInstanceOf(WorkerStartedEvent::class)], - [$this->isInstanceOf(WorkerMessageReceivedEvent::class)], - [$this->isInstanceOf(WorkerMessageHandledEvent::class)], - [$this->isInstanceOf(WorkerRunningEvent::class)], - [$this->isInstanceOf(WorkerStoppedEvent::class)] - )->willReturnCallback(function ($event) { + ->willReturnCallback(function ($event) use (&$series) { + array_shift($series)->evaluate($event, '', true); + if ($event instanceof WorkerRunningEvent) { $event->getWorker()->stop(); } @@ -208,15 +212,19 @@ public function testWorkerDispatchesEventsOnError() $eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $series = [ + $this->isInstanceOf(WorkerStartedEvent::class), + $this->isInstanceOf(WorkerMessageReceivedEvent::class), + $this->isInstanceOf(WorkerMessageFailedEvent::class), + $this->isInstanceOf(WorkerRunningEvent::class), + $this->isInstanceOf(WorkerStoppedEvent::class), + ]; + $eventDispatcher->expects($this->exactly(5)) ->method('dispatch') - ->withConsecutive( - [$this->isInstanceOf(WorkerStartedEvent::class)], - [$this->isInstanceOf(WorkerMessageReceivedEvent::class)], - [$this->isInstanceOf(WorkerMessageFailedEvent::class)], - [$this->isInstanceOf(WorkerRunningEvent::class)], - [$this->isInstanceOf(WorkerStoppedEvent::class)] - )->willReturnCallback(function ($event) { + ->willReturnCallback(function ($event) use (&$series) { + array_shift($series)->evaluate($event, '', true); + if ($event instanceof WorkerRunningEvent) { $event->getWorker()->stop(); } diff --git a/src/Symfony/Component/Notifier/Tests/Event/FailedMessageEventTest.php b/src/Symfony/Component/Notifier/Tests/Event/FailedMessageEventTest.php index 747100cd585a8..cd53bd64b6e0c 100644 --- a/src/Symfony/Component/Notifier/Tests/Event/FailedMessageEventTest.php +++ b/src/Symfony/Component/Notifier/Tests/Event/FailedMessageEventTest.php @@ -82,12 +82,18 @@ public function __toString(): string $message = new DummyMessage(); + $series = [ + new MessageEvent($message), + new FailedMessageEvent($message, $transport->exception), + ]; + $eventDispatcherMock->expects($this->exactly(2)) ->method('dispatch') - ->withConsecutive( - [new MessageEvent($message)], - [new FailedMessageEvent($message, $transport->exception)] - ); + ->willReturnCallback(function (object $event) use (&$series) { + $this->assertEquals(array_shift($series), $event); + + return $event; + }); try { $transport->send($message); } catch (NullTransportException $exception) { diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTestCase.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTestCase.php index 016d69422a2b4..742889ade2e01 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTestCase.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTestCase.php @@ -138,12 +138,18 @@ public function testSetValueCallsAdderAndRemoverForNestedCollections() $structure->expects($this->once()) ->method('removeAxis') ->with('fourth'); + $structure->expects($this->exactly(2)) ->method('addAxis') - ->withConsecutive( - ['first'], - ['third'] - ); + ->willReturnCallback(function (string $axis) { + static $series = [ + 'first', + 'third', + ]; + + $this->assertSame(array_shift($series), $axis); + }) + ; $this->propertyAccessor->setValue($car, 'structure.axes', $axesAfter); } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php index 79c5f2bc63de5..51c4e949dd86b 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php @@ -123,9 +123,15 @@ public function toArray(): array $ldap = $this->createMock(LdapInterface::class); $ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 'bar'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $ldap ->expects($this->once()) ->method('escape') @@ -169,9 +175,15 @@ public function toArray(): array $ldap = $this->createMock(LdapInterface::class); $ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 'bar'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $ldap ->expects($this->once()) ->method('escape') @@ -213,9 +225,15 @@ public function testEmptyQueryResultShouldThrowAnException() $ldap = $this->createMock(LdapInterface::class); $ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 'bar'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $ldap ->expects($this->once()) ->method('query') diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php index 9ddea2bb3344a..aa75671c8e344 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php @@ -229,8 +229,17 @@ public function testCacheableVotersWithMultipleAttributes() $voter ->expects($this->exactly(2)) ->method('supportsAttribute') - ->withConsecutive(['foo'], ['bar']) - ->willReturnOnConsecutiveCalls(false, true); + ->willReturnCallback(function (...$args) { + static $series = [ + [['foo'], false], + [['bar'], true], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }); $voter ->expects($this->once()) ->method('supportsType') diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php index 46ac724383519..bcd18740b295c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php @@ -197,10 +197,15 @@ public function testFailurePathFromRequestWithInvalidUrl() $this->logger->expects($this->exactly(2)) ->method('debug') - ->withConsecutive( - ['Ignoring query parameter "_my_failure_path": not a valid URL.'], - ['Authentication failure, redirect triggered.', ['failure_path' => '/login']] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['Ignoring query parameter "_my_failure_path": not a valid URL.', []], + ['Authentication failure, redirect triggered.', ['failure_path' => '/login']], + ]; + + $expectedArgs = array_shift($series); + $this->assertSame($expectedArgs, $args); + }); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/PasswordMigratingListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/PasswordMigratingListenerTest.php index 70725c2039243..6fc48b7a51b05 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/PasswordMigratingListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/PasswordMigratingListenerTest.php @@ -85,7 +85,19 @@ public function testUnsupportedPassport() // A custom Passport, without an UserBadge $passport = $this->createMock(UserPassportInterface::class); $passport->method('getUser')->willReturn($this->user); - $passport->method('hasBadge')->withConsecutive([PasswordUpgradeBadge::class], [UserBadge::class])->willReturnOnConsecutiveCalls(true, false); + $passport->method('hasBadge') + ->willReturnCallback(function (...$args) { + static $series = [ + [[PasswordUpgradeBadge::class], true], + [[UserBadge::class], false], + ]; + + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, $args); + + return $return; + }) + ; $passport->expects($this->once())->method('getBadge')->with(PasswordUpgradeBadge::class)->willReturn(new PasswordUpgradeBadge('pa$$word')); // We should never "getBadge" for "UserBadge::class" diff --git a/src/Symfony/Component/Security/Http/Tests/LoginLink/LoginLinkHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/LoginLink/LoginLinkHandlerTest.php index 0d6983620439d..6574a6841d974 100644 --- a/src/Symfony/Component/Security/Http/Tests/LoginLink/LoginLinkHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/LoginLink/LoginLinkHandlerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Http\Tests\LoginLink; +use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemPoolInterface; @@ -80,9 +81,22 @@ public function testCreateLoginLink($user, array $extraProperties, Request $requ ->method('getContext') ->willReturn($currentRequestContext = new RequestContext()); + $series = [ + $this->equalTo((new RequestContext())->fromRequest($request)->setParameter('_locale', $request->getLocale())), + $currentRequestContext, + ]; + $this->router->expects($this->exactly(2)) ->method('setContext') - ->withConsecutive([$this->equalTo((new RequestContext())->fromRequest($request)->setParameter('_locale', $request->getLocale()))], [$currentRequestContext]); + ->willReturnCallback(function (RequestContext $context) use (&$series) { + $expectedContext = array_shift($series); + + if ($expectedContext instanceof Constraint) { + $expectedContext->evaluate($context); + } else { + $this->assertSame($expectedContext, $context); + } + }); } $loginLink = $this->createLinker([], array_keys($extraProperties))->createLoginLink($user, $request); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php index 7b5b455c4ba5c..3bccfbbff0cca 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php @@ -41,16 +41,20 @@ protected function setUp(): void public function testDenormalize() { + $series = [ + [[['foo' => 'one', 'bar' => 'two']], new ArrayDummy('one', 'two')], + [[['foo' => 'three', 'bar' => 'four']], new ArrayDummy('three', 'four')], + ]; + $this->serializer->expects($this->exactly(2)) ->method('denormalize') - ->withConsecutive( - [['foo' => 'one', 'bar' => 'two']], - [['foo' => 'three', 'bar' => 'four']] - ) - ->willReturnOnConsecutiveCalls( - new ArrayDummy('one', 'two'), - new ArrayDummy('three', 'four') - ); + ->willReturnCallback(function ($data) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, [$data]); + + return $return; + }) + ; $result = $this->denormalizer->denormalize( [ @@ -74,18 +78,24 @@ public function testDenormalize() */ public function testDenormalizeLegacy() { - $serializer = $this->createMock(Serializer::class); + $firstArray = new ArrayDummy('one', 'two'); + $secondArray = new ArrayDummy('three', 'four'); + $series = [ + [[['foo' => 'one', 'bar' => 'two']], $firstArray], + [[['foo' => 'three', 'bar' => 'four']], $secondArray], + ]; + + $serializer = $this->createMock(Serializer::class); $serializer->expects($this->exactly(2)) ->method('denormalize') - ->withConsecutive( - [['foo' => 'one', 'bar' => 'two']], - [['foo' => 'three', 'bar' => 'four']] - ) - ->willReturnOnConsecutiveCalls( - new ArrayDummy('one', 'two'), - new ArrayDummy('three', 'four') - ); + ->willReturnCallback(function ($data) use (&$series) { + [$expectedArgs, $return] = array_shift($series); + $this->assertSame($expectedArgs, [$data]); + + return $return; + }) + ; $denormalizer = new ArrayDenormalizer(); diff --git a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php index 470aea2bb37bc..041b084f41ab2 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php @@ -742,8 +742,11 @@ public function testReadForManyLocalesAndManyDomains(array $locales, array $doma $loader = $this->getLoader(); $loader->expects($this->exactly(\count($consecutiveLoadArguments))) ->method('load') - ->withConsecutive(...$consecutiveLoadArguments) - ->willReturnOnConsecutiveCalls(...$consecutiveLoadReturns); + ->willReturnCallback(function (...$args) use (&$consecutiveLoadArguments, &$consecutiveLoadReturns) { + $this->assertSame(array_shift($consecutiveLoadArguments), $args); + + return array_shift($consecutiveLoadReturns); + }); $provider = self::createProvider((new MockHttpClient($responses))->withOptions([ 'base_uri' => 'https://localise.biz/api/', diff --git a/src/Symfony/Component/Translation/Bridge/Lokalise/Tests/LokaliseProviderTest.php b/src/Symfony/Component/Translation/Bridge/Lokalise/Tests/LokaliseProviderTest.php index 9859798efb36e..127f0b3f816e4 100644 --- a/src/Symfony/Component/Translation/Bridge/Lokalise/Tests/LokaliseProviderTest.php +++ b/src/Symfony/Component/Translation/Bridge/Lokalise/Tests/LokaliseProviderTest.php @@ -627,8 +627,11 @@ public function testReadForManyLocalesAndManyDomains(array $locales, array $doma $loader = $this->getLoader(); $loader->expects($this->exactly(\count($consecutiveLoadArguments))) ->method('load') - ->withConsecutive(...$consecutiveLoadArguments) - ->willReturnOnConsecutiveCalls(...$consecutiveLoadReturns); + ->willReturnCallback(function (...$args) use (&$consecutiveLoadArguments, &$consecutiveLoadReturns) { + $this->assertSame(array_shift($consecutiveLoadArguments), $args); + + return array_shift($consecutiveLoadReturns); + }); $provider = self::createProvider((new MockHttpClient($response))->withOptions([ 'base_uri' => 'https://api.lokalise.com/api2/projects/PROJECT_ID/', From 2641438d5fab26a75aee90f47ae4198a47265164 Mon Sep 17 00:00:00 2001 From: Tema Yud Date: Sun, 5 Mar 2023 22:32:25 +0500 Subject: [PATCH 23/69] [Mailer] STDOUT blocks infinitely under Windows when STDERR is filled --- .../Component/Mailer/Transport/Smtp/Stream/ProcessStream.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/Stream/ProcessStream.php b/src/Symfony/Component/Mailer/Transport/Smtp/Stream/ProcessStream.php index a8a8603807d27..bc721ad0cd85f 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/Stream/ProcessStream.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/Stream/ProcessStream.php @@ -35,7 +35,7 @@ public function initialize(): void $descriptorSpec = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], + 2 => ['pipe', '\\' === \DIRECTORY_SEPARATOR ? 'a' : 'w'], ]; $pipes = []; $this->stream = proc_open($this->command, $descriptorSpec, $pipes); From 40efc7b862d86b5412c0bdfff60cdf832ef84d66 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 10 Mar 2023 11:27:29 +0100 Subject: [PATCH 24/69] [Messenger] Fix `evaluate()` calls in `WorkerTest` --- src/Symfony/Component/Messenger/Tests/WorkerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/WorkerTest.php b/src/Symfony/Component/Messenger/Tests/WorkerTest.php index d98e9f51e0a8a..ef86584745747 100644 --- a/src/Symfony/Component/Messenger/Tests/WorkerTest.php +++ b/src/Symfony/Component/Messenger/Tests/WorkerTest.php @@ -188,7 +188,7 @@ public function testWorkerDispatchesEventsOnSuccess() $eventDispatcher->expects($this->exactly(5)) ->method('dispatch') ->willReturnCallback(function ($event) use (&$series) { - array_shift($series)->evaluate($event, '', true); + array_shift($series)->evaluate($event); if ($event instanceof WorkerRunningEvent) { $event->getWorker()->stop(); @@ -223,7 +223,7 @@ public function testWorkerDispatchesEventsOnError() $eventDispatcher->expects($this->exactly(5)) ->method('dispatch') ->willReturnCallback(function ($event) use (&$series) { - array_shift($series)->evaluate($event, '', true); + array_shift($series)->evaluate($event); if ($event instanceof WorkerRunningEvent) { $event->getWorker()->stop(); From fb9b0d0bd3b16d527e4765f1d7f4e313b56c257e Mon Sep 17 00:00:00 2001 From: Lesnykh Ilia Date: Fri, 10 Mar 2023 12:26:07 +0100 Subject: [PATCH 25/69] Change limit argument from string to integer. --- src/Symfony/Component/HttpKernel/Profiler/Profiler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index 25e126f731aaa..d07b887c02de8 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -116,7 +116,7 @@ public function purge() /** * Finds profiler tokens for the given criteria. * - * @param string|null $limit The maximum number of tokens to return + * @param int|null $limit The maximum number of tokens to return * @param string|null $start The start date to search from * @param string|null $end The end date to search to * @@ -124,7 +124,7 @@ public function purge() * * @see https://php.net/datetime.formats for the supported date/time formats */ - public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) { return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode); } From 6b27e78bf86e27acef140b94bcb9f63595f75245 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 10 Mar 2023 17:29:15 +0100 Subject: [PATCH 26/69] [Tests] Remove `withConsecutive()` calls from tests --- .../TemplateAttributeListenerTest.php | 18 ++++++++++++------ .../CheckLdapCredentialsListenerTest.php | 12 +++++++++--- .../Bridge/Loco/Tests/LocoProviderTest.php | 7 +++++-- .../LocoProviderWithoutTranslatorBagTest.php | 12 +++++++++--- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/EventListener/TemplateAttributeListenerTest.php b/src/Symfony/Bridge/Twig/Tests/EventListener/TemplateAttributeListenerTest.php index 8f6d6a2ca4068..e1fb7f9575902 100644 --- a/src/Symfony/Bridge/Twig/Tests/EventListener/TemplateAttributeListenerTest.php +++ b/src/Symfony/Bridge/Twig/Tests/EventListener/TemplateAttributeListenerTest.php @@ -29,12 +29,18 @@ public function testAttribute() $twig = $this->createMock(Environment::class); $twig->expects($this->exactly(3)) ->method('render') - ->withConsecutive( - ['templates/foo.html.twig', ['foo' => 'bar']], - ['templates/foo.html.twig', ['bar' => 'Bar', 'buz' => 'def']], - ['templates/foo.html.twig', []], - ) - ->willReturn('Bar'); + ->willReturnCallback(function (...$args) { + static $series = [ + ['templates/foo.html.twig', ['foo' => 'bar']], + ['templates/foo.html.twig', ['bar' => 'Bar', 'buz' => 'def']], + ['templates/foo.html.twig', []], + ]; + + $this->assertSame(array_shift($series), $args); + + return 'Bar'; + }) + ; $request = new Request(); $kernel = $this->createMock(HttpKernelInterface::class); diff --git a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php index 47492020ed452..d0397964d0d7a 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php @@ -146,9 +146,15 @@ public function toArray(): array $this->ldap ->method('bind') - ->withConsecutive( - ['elsa', 'test1234A$'] - ); + ->willReturnCallback(function (...$args) { + static $series = [ + ['elsa', 'test1234A$'], + ['', 's3cr3t'], + ]; + + $this->assertSame(array_shift($series), $args); + }) + ; $this->ldap->expects($this->any())->method('escape')->with('Wouter', '', LdapInterface::ESCAPE_FILTER)->willReturn('wouter'); $this->ldap->expects($this->once())->method('query')->with('{user_identifier}', 'wouter_test')->willReturn($query); diff --git a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php index a89422ac4e60d..9802204d2959c 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php @@ -803,8 +803,11 @@ public function testReadWithLastModified(array $locales, array $domains, array $ $loader = $this->getLoader(); $loader->expects($this->exactly(\count($consecutiveLoadArguments))) ->method('load') - ->withConsecutive(...$consecutiveLoadArguments) - ->willReturnOnConsecutiveCalls(...$consecutiveLoadReturns); + ->willReturnCallback(function (...$args) use (&$consecutiveLoadArguments, &$consecutiveLoadReturns) { + $this->assertSame(array_shift($consecutiveLoadArguments), $args); + + return array_shift($consecutiveLoadReturns); + }); $provider = self::createProvider( new MockHttpClient($responses, 'https://localise.biz/api/'), diff --git a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php index c9584820b8968..26867bbfd1cab 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderWithoutTranslatorBagTest.php @@ -61,10 +61,16 @@ public function testReadWithLastModified(array $locales, array $domains, array $ } $loader = $this->getLoader(); - $loader->expects($this->exactly(\count($consecutiveLoadArguments) * 2)) + $consecutiveLoadArguments = array_merge($consecutiveLoadArguments, $consecutiveLoadArguments); + $consecutiveLoadReturns = array_merge($consecutiveLoadReturns, $consecutiveLoadReturns); + + $loader->expects($this->exactly(\count($consecutiveLoadArguments))) ->method('load') - ->withConsecutive(...$consecutiveLoadArguments, ...$consecutiveLoadArguments) - ->willReturnOnConsecutiveCalls(...$consecutiveLoadReturns, ...$consecutiveLoadReturns); + ->willReturnCallback(function (...$args) use (&$consecutiveLoadArguments, &$consecutiveLoadReturns) { + $this->assertSame(array_shift($consecutiveLoadArguments), $args); + + return array_shift($consecutiveLoadReturns); + }); $provider = $this->createProvider( new MockHttpClient($responses, 'https://localise.biz/api/'), From dfea1db1daa773617d37064fc44e9fadb075d402 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Mar 2023 17:52:09 +0100 Subject: [PATCH 27/69] Fix test --- .../Lock/Tests/Store/DoctrineDbalStoreTest.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php index 8cd451a6f097c..17d721cdfb7a9 100644 --- a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php @@ -159,14 +159,15 @@ public function testTableCreationInTransactionNotSupported() $conn->expects($this->atLeast(2)) ->method('executeStatement') ->willReturnCallback(function ($sql) use (&$series) { - [$constraint, $return] = array_shift($series); - $constraint->evaluate($sql); + if ([$constraint, $return] = array_shift($series)) { + $constraint->evaluate($sql); + } if ($return instanceof \Exception) { throw $return; } - return $return; + return $return ?? 1; }) ; @@ -200,14 +201,15 @@ public function testCreatesTableOutsideTransaction() $conn->expects($this->atLeast(3)) ->method('executeStatement') ->willReturnCallback(function ($sql) use (&$series) { - [$constraint, $return] = array_shift($series); - $constraint->evaluate($sql); + if ([$constraint, $return] = array_shift($series)) { + $constraint->evaluate($sql); + } if ($return instanceof \Exception) { throw $return; } - return $return; + return $return ?? 1; }) ; From 76750061339d83f179c93bdc92d09f43153e44d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 13 Mar 2023 12:37:03 +0100 Subject: [PATCH 28/69] [VarDumper] Fixed dumping of CutStub --- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 3 +++ .../Component/VarDumper/Tests/Dumper/CliDumperTest.php | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 94dc8ee973fd3..e061c8d779fcc 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -198,6 +198,9 @@ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) } if ('' === $str) { $this->line .= '""'; + if ($cut) { + $this->line .= '…'.$cut; + } $this->endValue($cursor); } else { $attr += [ diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index d94b15ff4b731..968b48749f83d 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Dumper; use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\CutStub; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\AbstractDumper; use Symfony\Component\VarDumper\Dumper\CliDumper; @@ -37,6 +38,11 @@ public function testGet() ':stream' => function ($res, $a) { unset($a['uri'], $a['wrapper_data']); + return $a; + }, + 'Symfony\Component\VarDumper\Tests\Fixture\DumbFoo' => function ($foo, $a) { + $a['foo'] = new CutStub($a['foo']); + return $a; }, ]); @@ -76,7 +82,7 @@ public function testGet() %A options: [] } "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d - +foo: "foo" + +foo: ""…3 +"bar": "bar" } "closure" => Closure(\$a, PDO &\$b = null) {#%d From c19711c02700397abb23799150b503b72f1d923f Mon Sep 17 00:00:00 2001 From: MatTheCat Date: Mon, 13 Mar 2023 16:17:20 +0100 Subject: [PATCH 29/69] =?UTF-8?q?[FrameworkBundle]=20Rename=20limiter?= =?UTF-8?q?=E2=80=99s=20`strategy`=20to=20`policy`=20in=20XSD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/config/schema/symfony-1.0.xsd | 2 +- .../Fixtures/xml/rate_limiter.xml | 19 +++++++++++++++++++ .../XmlFrameworkExtensionTest.php | 8 ++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index d4be9fb6f2b7f..4366cab50d64b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -748,7 +748,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml new file mode 100644 index 0000000000000..35488c853cf5e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php index 944e19709e5b1..4a2ff788bf5c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\RateLimiter\Policy\SlidingWindowLimiter; class XmlFrameworkExtensionTest extends FrameworkExtensionTestCase { @@ -66,4 +67,11 @@ public function testLegacyExceptionsConfig() 'status_code' => 500, ], $configuration[\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class]); } + + public function testRateLimiter() + { + $container = $this->createContainerFromFile('rate_limiter'); + + $this->assertTrue($container->hasDefinition('limiter.sliding_window')); + } } From 97e932e3f2eb1954abf93bd1cef9d7f201407c6f Mon Sep 17 00:00:00 2001 From: Gwendolen Lynch Date: Tue, 14 Mar 2023 07:11:53 +0100 Subject: [PATCH 30/69] [String] Correct inflection of 'codes' and 'names' --- src/Symfony/Component/String/Inflector/EnglishInflector.php | 6 ++++++ .../String/Tests/Inflector/EnglishInflectorTest.php | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/Symfony/Component/String/Inflector/EnglishInflector.php b/src/Symfony/Component/String/Inflector/EnglishInflector.php index 9f2fac675c9cc..edd94dbc11ce0 100644 --- a/src/Symfony/Component/String/Inflector/EnglishInflector.php +++ b/src/Symfony/Component/String/Inflector/EnglishInflector.php @@ -55,6 +55,9 @@ final class EnglishInflector implements InflectorInterface // indices (index), appendices (appendix), prices (price) ['seci', 4, false, true, ['ex', 'ix', 'ice']], + // codes (code) + ['sedoc', 5, false, true, 'code'], + // selfies (selfie) ['seifles', 7, true, true, 'selfie'], @@ -64,6 +67,9 @@ final class EnglishInflector implements InflectorInterface // movies (movie) ['seivom', 6, true, true, 'movie'], + // names (name) + ['seman', 5, true, false, 'name'], + // conspectuses (conspectus), prospectuses (prospectus) ['sesutcep', 8, true, true, 'pectus'], diff --git a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php index afe3b63911d39..f3b50fc7e2f16 100644 --- a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php +++ b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php @@ -54,6 +54,7 @@ public static function singularizeProvider() ['children', 'child'], ['circuses', ['circus', 'circuse', 'circusis']], ['cliffs', 'cliff'], + ['codes', 'code'], ['committee', 'committee'], ['crises', ['cris', 'crise', 'crisis']], ['criteria', ['criterion', 'criterium']], @@ -108,6 +109,7 @@ public static function singularizeProvider() ['mice', 'mouse'], ['moves', 'move'], ['movies', 'movie'], + ['names', 'name'], ['nebulae', 'nebula'], ['neuroses', ['neuros', 'neurose', 'neurosis']], ['news', 'news'], From 4159ad89f6d958062a6d102173401434bc996edb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 14 Mar 2023 15:59:20 +0100 Subject: [PATCH 31/69] Fix some Composer keywords --- src/Symfony/Component/Console/composer.json | 2 +- src/Symfony/Component/HttpClient/composer.json | 1 + src/Symfony/Component/Ldap/composer.json | 2 +- src/Symfony/Component/PropertyAccess/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Routing/composer.json | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 9a565068cdedd..4fa4964a1dfd1 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -2,7 +2,7 @@ "name": "symfony/console", "type": "library", "description": "Eases the creation of beautiful and testable command line interfaces", - "keywords": ["console", "cli", "command line", "terminal"], + "keywords": ["console", "cli", "command-line", "terminal"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/HttpClient/composer.json b/src/Symfony/Component/HttpClient/composer.json index 084c2581219f1..57d31c12dfd8c 100644 --- a/src/Symfony/Component/HttpClient/composer.json +++ b/src/Symfony/Component/HttpClient/composer.json @@ -2,6 +2,7 @@ "name": "symfony/http-client", "type": "library", "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "keywords": ["http"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index 2ee70d32ba9c7..4a884d74ef528 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -2,7 +2,7 @@ "name": "symfony/ldap", "type": "library", "description": "Provides a LDAP client for PHP on top of PHP's ldap extension", - "keywords": ["ldap", "active directory"], + "keywords": ["ldap", "active-directory"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index fb6103a5275b3..b797151a03a20 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -2,7 +2,7 @@ "name": "symfony/property-access", "type": "library", "description": "Provides functions to read and write from/to an object or array using a simple string notation", - "keywords": ["property", "index", "access", "object", "array", "extraction", "injection", "reflection", "property path"], + "keywords": ["property", "index", "access", "object", "array", "extraction", "injection", "reflection", "property-path"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 30d77f6209c8d..79af9e860df0e 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -5,7 +5,7 @@ "keywords": [ "property", "type", - "PHPDoc", + "phpdoc", "symfony", "validator", "doctrine" diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index b21ad5f2929f3..c32219e633832 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -2,7 +2,7 @@ "name": "symfony/routing", "type": "library", "description": "Maps an HTTP request to a set of configuration variables", - "keywords": ["routing", "router", "URL", "URI"], + "keywords": ["routing", "router", "url", "uri"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ From 0362350a720e38df55531ab0cf726a082d3d34d4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 14 Mar 2023 16:48:23 +0100 Subject: [PATCH 32/69] Fix some Composer keywords --- src/Symfony/Component/Runtime/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Runtime/composer.json b/src/Symfony/Component/Runtime/composer.json index f8112d9a43d00..6c90a85947dfb 100644 --- a/src/Symfony/Component/Runtime/composer.json +++ b/src/Symfony/Component/Runtime/composer.json @@ -2,6 +2,7 @@ "name": "symfony/runtime", "type": "composer-plugin", "description": "Enables decoupling PHP applications from global state", + "keywords": ["runtime"], "homepage": "https://symfony.com", "license" : "MIT", "authors": [ From 2178d0127456b11f849639fddda5b49635444252 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 14 Mar 2023 16:48:45 +0100 Subject: [PATCH 33/69] Fix some Composer keywords --- src/Symfony/Component/VarExporter/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarExporter/composer.json b/src/Symfony/Component/VarExporter/composer.json index 67c4a279f4c7d..83140ee7d6abb 100644 --- a/src/Symfony/Component/VarExporter/composer.json +++ b/src/Symfony/Component/VarExporter/composer.json @@ -2,7 +2,7 @@ "name": "symfony/var-exporter", "type": "library", "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy loading", "proxy"], + "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy-loading", "proxy"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ From ed357c06cf281c52c4fd413155cebbeae5f32f68 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 14 Mar 2023 16:56:17 +0100 Subject: [PATCH 34/69] Fix some Composer keywords --- src/Symfony/Component/Notifier/Bridge/AllMySms/composer.json | 2 +- src/Symfony/Component/Notifier/Bridge/FreeMobile/composer.json | 2 +- src/Symfony/Component/Notifier/Bridge/GoogleChat/composer.json | 2 +- src/Symfony/Component/Notifier/Bridge/KazInfoTeh/composer.json | 2 +- src/Symfony/Component/Notifier/Bridge/OvhCloud/composer.json | 2 +- src/Symfony/Component/Notifier/Bridge/TurboSms/composer.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Notifier/Bridge/AllMySms/composer.json b/src/Symfony/Component/Notifier/Bridge/AllMySms/composer.json index 8688ec91c0196..e08c0085068a2 100644 --- a/src/Symfony/Component/Notifier/Bridge/AllMySms/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/AllMySms/composer.json @@ -2,7 +2,7 @@ "name": "symfony/all-my-sms-notifier", "type": "symfony-notifier-bridge", "description": "Symfony AllMySms Notifier Bridge", - "keywords": ["sms", "allMySms", "notifier"], + "keywords": ["sms", "all-my-sms", "notifier"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/composer.json b/src/Symfony/Component/Notifier/Bridge/FreeMobile/composer.json index 0489182933bcd..cc5ad9ef3bcfc 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/composer.json @@ -2,7 +2,7 @@ "name": "symfony/free-mobile-notifier", "type": "symfony-notifier-bridge", "description": "Symfony Free Mobile Notifier Bridge", - "keywords": ["sms", "FreeMobile", "notifier", "alerting"], + "keywords": ["sms", "free-mobile", "notifier", "alerting"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/composer.json b/src/Symfony/Component/Notifier/Bridge/GoogleChat/composer.json index cc1ffc30600c3..09e6748ce0abc 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/composer.json @@ -2,7 +2,7 @@ "name": "symfony/google-chat-notifier", "type": "symfony-notifier-bridge", "description": "Symfony Google Chat Notifier Bridge", - "keywords": ["google", "chat", "google chat", "notifier"], + "keywords": ["google", "chat", "google-chat", "notifier"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Notifier/Bridge/KazInfoTeh/composer.json b/src/Symfony/Component/Notifier/Bridge/KazInfoTeh/composer.json index 9f7288ba01026..f67e38be7dbf6 100644 --- a/src/Symfony/Component/Notifier/Bridge/KazInfoTeh/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/KazInfoTeh/composer.json @@ -2,7 +2,7 @@ "name": "symfony/kaz-info-teh-notifier", "type": "symfony-bridge", "description": "Symfony KazInfoTeh Notifier Bridge", - "keywords": ["KazInfoTeh", "notifier", "symfony", "sms"], + "keywords": ["kaz-info-teh", "notifier", "symfony", "sms"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Notifier/Bridge/OvhCloud/composer.json b/src/Symfony/Component/Notifier/Bridge/OvhCloud/composer.json index bc2c0bb1b9529..94b22538780e7 100644 --- a/src/Symfony/Component/Notifier/Bridge/OvhCloud/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/OvhCloud/composer.json @@ -2,7 +2,7 @@ "name": "symfony/ovh-cloud-notifier", "type": "symfony-notifier-bridge", "description": "Symfony OvhCloud Notifier Bridge", - "keywords": ["sms", "OvhCloud", "notifier"], + "keywords": ["sms", "ovh-cloud", "notifier"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/src/Symfony/Component/Notifier/Bridge/TurboSms/composer.json b/src/Symfony/Component/Notifier/Bridge/TurboSms/composer.json index 95da2605d054b..3d03be4ead299 100644 --- a/src/Symfony/Component/Notifier/Bridge/TurboSms/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/TurboSms/composer.json @@ -2,7 +2,7 @@ "name": "symfony/turbo-sms-notifier", "type": "symfony-notifier-bridge", "description": "Symfony TurboSms Notifier Bridge", - "keywords": ["sms", "TurboSms", "notifier"], + "keywords": ["sms", "turbo-sms", "notifier"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ From 14a4fcfedd6153885cdcd08bbd734b0f954f6a0c Mon Sep 17 00:00:00 2001 From: "A. Pauly" Date: Tue, 14 Mar 2023 17:08:31 +0100 Subject: [PATCH 35/69] [FrameworkBundle] Workflow - Fix LogicException about a wrong configuration of "enabled" node --- .../FrameworkBundle/DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index c70a07635843a..e9b95db35a0c2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -350,7 +350,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) foreach ($workflows as $key => $workflow) { if (isset($workflow['enabled']) && false === $workflow['enabled']) { - throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $workflow['name'])); + throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $key)); } unset($workflows[$key]['enabled']); From 436dcba003ce6c06d8ac839d682a689da368b119 Mon Sep 17 00:00:00 2001 From: Maximilian Beckers Date: Thu, 16 Mar 2023 08:57:07 +0100 Subject: [PATCH 36/69] [Validator] Update BIC validator IBAN mappings --- .../Validator/Constraints/BicValidator.php | 17 +++++++++++++---- .../Tests/Constraints/BicValidatorTest.php | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/BicValidator.php b/src/Symfony/Component/Validator/Constraints/BicValidator.php index 37e922de7f92f..6c038067b7940 100644 --- a/src/Symfony/Component/Validator/Constraints/BicValidator.php +++ b/src/Symfony/Component/Validator/Constraints/BicValidator.php @@ -29,8 +29,9 @@ */ class BicValidator extends ConstraintValidator { + // Reference: https://www.iban.com/structure private const BIC_COUNTRY_TO_IBAN_COUNTRY_MAP = [ - // Reference: https://www.ecbs.org/iban/france-bank-account-number.html + // FR includes: 'GF' => 'FR', // French Guiana 'PF' => 'FR', // French Polynesia 'TF' => 'FR', // French Southern Territories @@ -39,13 +40,20 @@ class BicValidator extends ConstraintValidator 'YT' => 'FR', // Mayotte 'NC' => 'FR', // New Caledonia 'RE' => 'FR', // Reunion + 'BL' => 'FR', // Saint Barthelemy + 'MF' => 'FR', // Saint Martin (French part) 'PM' => 'FR', // Saint Pierre and Miquelon 'WF' => 'FR', // Wallis and Futuna Islands - // Reference: https://www.ecbs.org/iban/united-kingdom-uk-bank-account-number.html + // GB includes: 'JE' => 'GB', // Jersey 'IM' => 'GB', // Isle of Man 'GG' => 'GB', // Guernsey 'VG' => 'GB', // British Virgin Islands + // FI includes: + 'AX' => 'FI', // Aland Islands + // ES includes: + 'IC' => 'ES', // Canary Islands + 'EA' => 'ES', // Ceuta and Melilla ]; private $propertyAccessor; @@ -104,7 +112,8 @@ public function validate($value, Constraint $constraint) return; } - if (!Countries::exists(substr($canonicalize, 4, 2))) { + $bicCountryCode = substr($canonicalize, 4, 2); + if (!isset(self::BIC_COUNTRY_TO_IBAN_COUNTRY_MAP[$bicCountryCode]) && !Countries::exists($bicCountryCode)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Bic::INVALID_COUNTRY_CODE_ERROR) @@ -137,7 +146,7 @@ public function validate($value, Constraint $constraint) return; } $ibanCountryCode = substr($iban, 0, 2); - if (ctype_alpha($ibanCountryCode) && !$this->bicAndIbanCountriesMatch(substr($canonicalize, 4, 2), $ibanCountryCode)) { + if (ctype_alpha($ibanCountryCode) && !$this->bicAndIbanCountriesMatch($bicCountryCode, $ibanCountryCode)) { $this->context->buildViolation($constraint->ibanMessage) ->setParameter('{{ value }}', $this->formatValue($value)) ->setParameter('{{ iban }}', $iban) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php index 564fa30c95957..0acfb67a63bd0 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php @@ -299,6 +299,8 @@ public static function getValidBicSpecialCases() yield ['BNPAYTGX', 'FR14 2004 1010 0505 0001 3M02 606']; yield ['BNPANCGX', 'FR14 2004 1010 0505 0001 3M02 606']; yield ['BNPAREGX', 'FR14 2004 1010 0505 0001 3M02 606']; + yield ['BNPABLGX', 'FR14 2004 1010 0505 0001 3M02 606']; + yield ['BNPAMFGX', 'FR14 2004 1010 0505 0001 3M02 606']; yield ['BNPAPMGX', 'FR14 2004 1010 0505 0001 3M02 606']; yield ['BNPAWFGX', 'FR14 2004 1010 0505 0001 3M02 606']; @@ -307,6 +309,13 @@ public static function getValidBicSpecialCases() yield ['BARCIMSA', 'GB12 CPBK 0892 9965 0449 911']; yield ['BARCGGSA', 'GB12 CPBK 0892 9965 0449 911']; yield ['BARCVGSA', 'GB12 CPBK 0892 9965 0449 911']; + + // FI related special cases + yield ['NDEAAXHH', 'FI14 1009 3000 1234 58']; + + // ES related special cases + yield ['CAIXICBBXXX', 'ES79 2100 0813 6101 2345 6789']; + yield ['CAIXEABBXXX', 'ES79 2100 0813 6101 2345 6789']; } } From 37ef83bee5767a763ac77c99c8fd5ddedbee643b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 17 Mar 2023 09:03:06 +0100 Subject: [PATCH 37/69] add translations for the filename max length validator option --- .../Validator/Resources/translations/validators.de.xlf | 4 ++++ .../Validator/Resources/translations/validators.en.xlf | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 1c6d0c6c95873..7f9a34a717cdb 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -402,6 +402,10 @@ The value of the netmask should be between {{ min }} and {{ max }}. Der Wert der Subnetzmaske sollte zwischen {{ min }} und {{ max }} liegen. + + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + Der Dateiname ist zu lang. Er sollte nicht länger als {{ filename_max_length }} Zeichen sein.|Der Dateiname ist zu lang. Er sollte nicht länger als {{ filename_max_length }} Zeichen sein. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index 34c54212d842f..f6772fdfb67ba 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -402,6 +402,10 @@ The value of the netmask should be between {{ min }} and {{ max }}. The value of the netmask should be between {{ min }} and {{ max }}. + + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + From 489f9ca64d6fd34a9e60603e5c9c552c909961df Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 17 Mar 2023 09:38:42 +0100 Subject: [PATCH 38/69] explicitly set the HTTP method override option to false --- .../Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml index 35488c853cf5e..cce1f67991177 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/rate_limiter.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + Date: Thu, 16 Mar 2023 16:48:23 +0100 Subject: [PATCH 39/69] Stop stopwatch events in case of exception --- .../EventDispatcher/Debug/WrappedListener.php | 10 +++-- .../Tests/Debug/WrappedListenerTest.php | 20 +++++++++ .../Controller/TraceableArgumentResolver.php | 10 ++--- .../TraceableControllerResolver.php | 10 ++--- .../TraceableArgumentResolverTest.php | 45 +++++++++++++++++++ .../TraceableControllerResolverTest.php | 44 ++++++++++++++++++ 6 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index 86d3854b22c4e..3c4cc13352c4c 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -114,10 +114,12 @@ public function __invoke(object $event, string $eventName, EventDispatcherInterf $e = $this->stopwatch->start($this->name, 'event_listener'); - ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); - - if ($e->isStarted()) { - $e->stop(); + try { + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); + } finally { + if ($e->isStarted()) { + $e->stop(); + } } if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php index 68db87db73bf7..115657ea6896a 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php @@ -15,6 +15,7 @@ use Symfony\Component\EventDispatcher\Debug\WrappedListener; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; class WrappedListenerTest extends TestCase { @@ -42,6 +43,25 @@ public static function provideListenersToDescribe() [\Closure::fromCallable(function () {}), 'closure'], ]; } + + public function testStopwatchEventIsStoppedWhenListenerThrows() + { + $stopwatchEvent = $this->createMock(StopwatchEvent::class); + $stopwatchEvent->expects(self::once())->method('isStarted')->willReturn(true); + $stopwatchEvent->expects(self::once())->method('stop'); + + $stopwatch = $this->createStub(Stopwatch::class); + $stopwatch->method('start')->willReturn($stopwatchEvent); + + $dispatcher = $this->createStub(EventDispatcherInterface::class); + + $wrappedListener = new WrappedListener(function () { throw new \Exception(); }, null, $stopwatch, $dispatcher); + + try { + $wrappedListener(new \stdClass(), 'foo', $dispatcher); + } catch (\Exception $ex) { + } + } } class FooListener diff --git a/src/Symfony/Component/HttpKernel/Controller/TraceableArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/TraceableArgumentResolver.php index e22cf082c4e27..859cf3a6f4844 100644 --- a/src/Symfony/Component/HttpKernel/Controller/TraceableArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/TraceableArgumentResolver.php @@ -35,10 +35,10 @@ public function getArguments(Request $request, callable $controller) { $e = $this->stopwatch->start('controller.get_arguments'); - $ret = $this->resolver->getArguments($request, $controller); - - $e->stop(); - - return $ret; + try { + return $this->resolver->getArguments($request, $controller); + } finally { + $e->stop(); + } } } diff --git a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php index bf6b6aa1f2f8c..013dfe23610cc 100644 --- a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php @@ -35,10 +35,10 @@ public function getController(Request $request) { $e = $this->stopwatch->start('controller.get_callable'); - $ret = $this->resolver->getController($request); - - $e->stop(); - - return $ret; + try { + return $this->resolver->getController($request); + } finally { + $e->stop(); + } } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php new file mode 100644 index 0000000000000..6de47bd1f4270 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Controller; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; +use Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; + +class TraceableArgumentResolverTest extends TestCase +{ + public function testStopwatchEventIsStoppedWhenResolverThrows() + { + $stopwatchEvent = $this->createMock(StopwatchEvent::class); + $stopwatchEvent->expects(self::once())->method('stop'); + + $stopwatch = $this->createStub(Stopwatch::class); + $stopwatch->method('start')->willReturn($stopwatchEvent); + + $resolver = new class() implements ArgumentResolverInterface { + public function getArguments(Request $request, callable $controller) + { + throw new \Exception(); + } + }; + + $traceableResolver = new TraceableArgumentResolver($resolver, $stopwatch); + + try { + $traceableResolver->getArguments(new Request(), function () {}); + } catch (\Exception $ex) { + } + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php new file mode 100644 index 0000000000000..707d06bc6efd2 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Controller; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\HttpKernel\Controller\TraceableControllerResolver; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; + +class TraceableControllerResolverTest extends TestCase +{ + public function testStopwatchEventIsStoppedWhenResolverThrows() + { + $stopwatchEvent = $this->createMock(StopwatchEvent::class); + $stopwatchEvent->expects(self::once())->method('stop'); + + $stopwatch = $this->createStub(Stopwatch::class); + $stopwatch->method('start')->willReturn($stopwatchEvent); + + $resolver = new class() implements ControllerResolverInterface { + public function getController(Request $request) + { + throw new \Exception(); + } + }; + + $traceableResolver = new TraceableControllerResolver($resolver, $stopwatch); + try { + $traceableResolver->getController(new Request()); + } catch (\Exception $ex) { + } + } +} From 829617746a91be4b4e7eb7d2d9c3e31a38038e1b Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Fri, 17 Mar 2023 14:46:09 +0100 Subject: [PATCH 40/69] fix: GetSetMethodNormalizer::supportss should not check ignored methods --- .../Normalizer/GetSetMethodNormalizer.php | 19 ++++++++----------- .../Normalizer/GetSetMethodNormalizerTest.php | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index b67a808cb9abd..d9339df64df5c 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Serializer\Normalizer; +use Symfony\Component\Serializer\Annotation\Ignore; + /** * Converts between objects with getter and setter methods and arrays. * @@ -81,17 +83,12 @@ private function supports(string $class): bool */ private function isGetMethod(\ReflectionMethod $method): bool { - $methodLength = \strlen($method->name); - - return - !$method->isStatic() && - ( - ((str_starts_with($method->name, 'get') && 3 < $methodLength) || - (str_starts_with($method->name, 'is') && 2 < $methodLength) || - (str_starts_with($method->name, 'has') && 3 < $methodLength)) && - 0 === $method->getNumberOfRequiredParameters() - ) - ; + return !$method->isStatic() + && (\PHP_VERSION_ID < 80000 || !$method->getAttributes(Ignore::class)) + && !$method->getNumberOfRequiredParameters() + && ((2 < ($methodLength = \strlen($method->name)) && str_starts_with($method->name, 'is')) + || (3 < $methodLength && (str_starts_with($method->name, 'has') || str_starts_with($method->name, 'get'))) + ); } /** diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index e6f8396fe9d15..bf0c7cd56f14f 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -16,6 +16,7 @@ use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; +use Symfony\Component\Serializer\Annotation\Ignore; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; @@ -430,6 +431,11 @@ public function testNoStaticGetSetSupport() $this->assertFalse($this->normalizer->supportsNormalization(new ObjectWithJustStaticSetterDummy())); } + public function testNotIgnoredMethodSupport() + { + $this->assertFalse($this->normalizer->supportsNormalization(new ClassWithIgnoreAttribute())); + } + public function testPrivateSetter() { $obj = $this->normalizer->denormalize(['foo' => 'foobar'], ObjectWithPrivateSetterDummy::class); @@ -753,3 +759,14 @@ public function __call($key, $value) throw new \RuntimeException('__call should not be called. Called with: '.$key); } } + +class ClassWithIgnoreAttribute +{ + public string $foo; + + #[Ignore] + public function isSomeIgnoredMethod(): bool + { + return true; + } +} From a70c4960254aca3a607cd1b63b875117fc54f115 Mon Sep 17 00:00:00 2001 From: Peter Bowyer Date: Fri, 17 Mar 2023 15:58:46 +0000 Subject: [PATCH 41/69] [HttpClient] Encode and decode curly brackets {} --- src/Symfony/Component/HttpClient/HttpClientTrait.php | 2 -- .../Component/HttpClient/Tests/HttpClientTraitTest.php | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 68c3dcd7de03f..47454923051d1 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -638,9 +638,7 @@ private static function mergeQueryString(?string $queryString, array $queryArray '%5D' => ']', '%5E' => '^', '%60' => '`', - '%7B' => '{', '%7C' => '|', - '%7D' => '}', ]); } diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php index 6e7163af2309f..a44a4b4b36ef6 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php @@ -70,6 +70,8 @@ public static function provideResolveUrl(): array [self::RFC3986_BASE, '/g', 'http://a/g'], [self::RFC3986_BASE, '//g', 'http://g/'], [self::RFC3986_BASE, '?y', 'http://a/b/c/d;p?y'], + [self::RFC3986_BASE, '?y={"f":1}', 'http://a/b/c/d;p?y={%22f%22:1}'], + [self::RFC3986_BASE, 'g{oof}y', 'http://a/b/c/g{oof}y'], [self::RFC3986_BASE, 'g?y', 'http://a/b/c/g?y'], [self::RFC3986_BASE, '#s', 'http://a/b/c/d;p?q#s'], [self::RFC3986_BASE, 'g#s', 'http://a/b/c/g#s'], @@ -154,10 +156,11 @@ public static function provideParseUrl(): iterable yield [['https:', '//xn--dj-kia8a.example.com:8000', '/', null, null], 'https://DÉjà.Example.com:8000/']; yield [[null, null, '/f%20o.o', '?a=b', '#c'], '/f o%2Eo?a=b#c']; yield [[null, '//a:b@foo', '/bar', null, null], '//a:b@foo/bar']; + yield [[null, '//a:b@foo', '/b{}', null, null], '//a:b@foo/b{}']; yield [['http:', null, null, null, null], 'http:']; yield [['http:', null, 'bar', null, null], 'http:bar']; yield [[null, null, 'bar', '?a=1&c=c', null], 'bar?a=a&b=b', ['b' => null, 'c' => 'c', 'a' => 1]]; - yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*%2B%2C;%3D:@%25\\^`{|}', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; + yield [[null, null, 'bar', '?a=b+c&b=b-._~!$%26/%27()[]*%2B%2C;%3D:@%25\\^`%7B|%7D', null], 'bar?a=b+c', ['b' => 'b-._~!$&/\'()[]*+,;=:@%\\^`{|}']]; yield [[null, null, 'bar', '?a=b%2B%20c', null], 'bar?a=b+c', ['a' => 'b+ c']]; yield [[null, null, 'bar', '?a[b]=c', null], 'bar', ['a' => ['b' => 'c']]]; yield [[null, null, 'bar', '?a[b[c]=d', null], 'bar?a[b[c]=d', []]; From 725008320588a99cbfaa8a8f44b7f7f17f597fd1 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 19 Mar 2023 11:06:15 +0100 Subject: [PATCH 42/69] skip test using attributes on PHP 7 --- .../Attributes/ClassWithIgnoreAttribute.php | 25 +++++++++++++++++++ .../Normalizer/GetSetMethodNormalizerTest.php | 16 +++--------- 2 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/ClassWithIgnoreAttribute.php diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/ClassWithIgnoreAttribute.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/ClassWithIgnoreAttribute.php new file mode 100644 index 0000000000000..14d5e947264bf --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/ClassWithIgnoreAttribute.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\Serializer\Tests\Fixtures\Attributes; + +use Symfony\Component\Serializer\Annotation\Ignore; + +class ClassWithIgnoreAttribute +{ + public string $foo; + + #[Ignore] + public function isSomeIgnoredMethod(): bool + { + return true; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index bf0c7cd56f14f..c2d670cfe5838 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -16,7 +16,6 @@ use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; -use Symfony\Component\Serializer\Annotation\Ignore; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; @@ -30,6 +29,7 @@ use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\Tests\Fixtures\Annotations\GroupDummy; +use Symfony\Component\Serializer\Tests\Fixtures\Attributes\ClassWithIgnoreAttribute; use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy; use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder; use Symfony\Component\Serializer\Tests\Normalizer\Features\CacheableObjectAttributesTestTrait; @@ -431,6 +431,9 @@ public function testNoStaticGetSetSupport() $this->assertFalse($this->normalizer->supportsNormalization(new ObjectWithJustStaticSetterDummy())); } + /** + * @requires PHP 8 + */ public function testNotIgnoredMethodSupport() { $this->assertFalse($this->normalizer->supportsNormalization(new ClassWithIgnoreAttribute())); @@ -759,14 +762,3 @@ public function __call($key, $value) throw new \RuntimeException('__call should not be called. Called with: '.$key); } } - -class ClassWithIgnoreAttribute -{ - public string $foo; - - #[Ignore] - public function isSomeIgnoredMethod(): bool - { - return true; - } -} From 0776decd73a3055248292982cb2030a3b4ef7ac0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 19 Mar 2023 10:39:45 +0100 Subject: [PATCH 43/69] re-allow phpdocumentor/type-resolver 1.7 --- composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 66ffa86d7bcd7..d5e8a209d3be0 100644 --- a/composer.json +++ b/composer.json @@ -158,7 +158,7 @@ "egulias/email-validator": "~3.0.0", "masterminds/html5": "<2.6", "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0|>=1.7.0", + "phpdocumentor/type-resolver": "<1.4.0", "ocramius/proxy-manager": "<2.1", "phpunit/phpunit": "<5.4.3" }, diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index ce0eeb6042947..7b9a3c719c28c 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -44,7 +44,7 @@ "conflict": { "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0|>=1.7.0", + "phpdocumentor/type-resolver": "<1.4.0", "symfony/dependency-injection": "<4.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.3.13", From e23be5834812b00b321f8cfc3a968b20546aa6f7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 20 Mar 2023 11:45:02 +0100 Subject: [PATCH 44/69] [FrameworkBundle] Fix wiring session.handler when handler_id is null --- .../DependencyInjection/FrameworkExtension.php | 12 ++---------- .../FrameworkBundle/Resources/config/session.php | 5 +++++ .../FrameworkExtensionTestCase.php | 10 ++++------ .../Storage/Handler/NativeFileSessionHandler.php | 8 ++++++-- .../Session/Storage/NativeSessionStorage.php | 7 ++++--- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 00412e5c68051..a3fed9a85b64b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1178,16 +1178,8 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c // session handler (the internal callback registered with PHP session management) if (null === $config['handler_id']) { - // Set the handler class to be null - if ($container->hasDefinition('session.storage.native')) { - $container->getDefinition('session.storage.native')->replaceArgument(1, null); - $container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null); - } else { - $container->getDefinition('session.storage.factory.native')->replaceArgument(1, null); - $container->getDefinition('session.storage.factory.php_bridge')->replaceArgument(0, null); - } - - $container->setAlias('session.handler', 'session.handler.native_file'); + $config['save_path'] = null; + $container->setAlias('session.handler', 'session.handler.native'); } else { $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php index 43c0000dded40..a26182e939b5d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php @@ -133,6 +133,11 @@ ]) ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "session.storage.factory.mock_file" instead.') + ->set('session.handler.native', StrictSessionHandler::class) + ->args([ + inline_service(\SessionHandler::class), + ]) + ->set('session.handler.native_file', StrictSessionHandler::class) ->args([ inline_service(NativeFileSessionHandler::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index a1c67eef1874c..3288e96aa5d7a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -648,9 +648,8 @@ public function testNullSessionHandler() $container = $this->createContainerFromFile('session'); $this->assertTrue($container->hasAlias(SessionInterface::class), '->registerSessionConfiguration() loads session.xml'); - $this->assertNull($container->getDefinition('session.storage.factory.native')->getArgument(1)); - $this->assertNull($container->getDefinition('session.storage.factory.php_bridge')->getArgument(0)); - $this->assertSame('session.handler.native_file', (string) $container->getAlias('session.handler')); + $this->assertNull($container->getParameter('session.save_path')); + $this->assertSame('session.handler.native', (string) $container->getAlias('session.handler')); $expected = ['session_factory', 'session', 'initialized_session', 'logger', 'session_collector']; $this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues())); @@ -667,9 +666,8 @@ public function testNullSessionHandlerLegacy() $container = $this->createContainerFromFile('session_legacy'); $this->assertTrue($container->hasAlias(SessionInterface::class), '->registerSessionConfiguration() loads session.xml'); - $this->assertNull($container->getDefinition('session.storage.native')->getArgument(1)); - $this->assertNull($container->getDefinition('session.storage.php_bridge')->getArgument(0)); - $this->assertSame('session.handler.native_file', (string) $container->getAlias('session.handler')); + $this->assertNull($container->getParameter('session.save_path')); + $this->assertSame('session.handler.native', (string) $container->getAlias('session.handler')); $expected = ['session_factory', 'session', 'initialized_session', 'logger', 'session_collector']; $this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues())); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php index a446c0c415806..52a103879bce3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -49,7 +49,11 @@ public function __construct(string $savePath = null) throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); } - ini_set('session.save_path', $savePath); - ini_set('session.save_handler', 'files'); + if ($savePath !== \ini_get('session.save_path')) { + ini_set('session.save_path', $savePath); + } + if ('files' !== \ini_get('session.save_handler')) { + ini_set('session.save_handler', 'files'); + } } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index a50c8270feb94..242478c420280 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -455,9 +455,10 @@ public function setOptions(array $options) */ public function setSaveHandler($saveHandler = null) { - if (!$saveHandler instanceof AbstractProxy && - !$saveHandler instanceof \SessionHandlerInterface && - null !== $saveHandler) { + if (!$saveHandler instanceof AbstractProxy + && !$saveHandler instanceof \SessionHandlerInterface + && null !== $saveHandler + ) { throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); } From e95bbe7a73bf0317340766709029a920dd65d5f4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 20 Mar 2023 17:10:32 +0100 Subject: [PATCH 45/69] Fix merge --- .../Tests/Controller/TraceableArgumentResolverTest.php | 2 +- .../Tests/Controller/TraceableControllerResolverTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php index 6de47bd1f4270..43bbb13e6bc9b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableArgumentResolverTest.php @@ -29,7 +29,7 @@ public function testStopwatchEventIsStoppedWhenResolverThrows() $stopwatch->method('start')->willReturn($stopwatchEvent); $resolver = new class() implements ArgumentResolverInterface { - public function getArguments(Request $request, callable $controller) + public function getArguments(Request $request, callable $controller): array { throw new \Exception(); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php index 707d06bc6efd2..ecd4a237364c6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/TraceableControllerResolverTest.php @@ -29,7 +29,7 @@ public function testStopwatchEventIsStoppedWhenResolverThrows() $stopwatch->method('start')->willReturn($stopwatchEvent); $resolver = new class() implements ControllerResolverInterface { - public function getController(Request $request) + public function getController(Request $request): callable|false { throw new \Exception(); } From cf9b13242542e11511830adc8dc6decf10b739ab Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Tue, 21 Mar 2023 17:30:23 +0100 Subject: [PATCH 46/69] [HttpFoundation] Use separate caches for IpUtils checkIp4 and checkIp6 --- src/Symfony/Component/HttpFoundation/IpUtils.php | 4 ++-- .../HttpFoundation/Tests/IpUtilsTest.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 2f31284e36c69..49d9a9d74c251 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -73,7 +73,7 @@ public static function checkIp4(?string $requestIp, string $ip) return false; } - $cacheKey = $requestIp.'-'.$ip; + $cacheKey = $requestIp.'-'.$ip.'-v4'; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } @@ -126,7 +126,7 @@ public static function checkIp6(?string $requestIp, string $ip) return false; } - $cacheKey = $requestIp.'-'.$ip; + $cacheKey = $requestIp.'-'.$ip.'-v6'; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index 085790cf606a8..f5ac4053b62a6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -19,6 +19,21 @@ class IpUtilsTest extends TestCase { use ExpectDeprecationTrait; + public function testSeparateCachesPerProtocol() + { + $ip = '192.168.52.1'; + $subnet = '192.168.0.0/16'; + + $this->assertFalse(IpUtils::checkIp6($ip, $subnet)); + $this->assertTrue(IpUtils::checkIp4($ip, $subnet)); + + $ip = '2a01:198:603:0:396e:4789:8e99:890f'; + $subnet = '2a01:198:603:0::/65'; + + $this->assertFalse(IpUtils::checkIp4($ip, $subnet)); + $this->assertTrue(IpUtils::checkIp6($ip, $subnet)); + } + /** * @dataProvider getIpv4Data */ From eb4b511329a20c077b375847e01c7453367eb56c Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Tue, 21 Mar 2023 14:46:52 +0100 Subject: [PATCH 47/69] [HttpClient] Add hint about `timeout` and `max_duration` options --- src/Symfony/Contracts/HttpClient/HttpClientInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Contracts/HttpClient/HttpClientInterface.php b/src/Symfony/Contracts/HttpClient/HttpClientInterface.php index 158c1a7d066c8..9c96629b9ac02 100644 --- a/src/Symfony/Contracts/HttpClient/HttpClientInterface.php +++ b/src/Symfony/Contracts/HttpClient/HttpClientInterface.php @@ -54,8 +54,8 @@ interface HttpClientInterface 'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution 'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored 'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached - 'timeout' => null, // float - the idle timeout - defaults to ini_get('default_socket_timeout') - 'max_duration' => 0, // float - the maximum execution time for the request+response as a whole; + 'timeout' => null, // float - the idle timeout (in seconds) - defaults to ini_get('default_socket_timeout') + 'max_duration' => 0, // float - the maximum execution time (in seconds) for the request+response as a whole; // a value lower than or equal to 0 means it is unlimited 'bindto' => '0', // string - the interface or the local socket to bind to 'verify_peer' => true, // see https://php.net/context.ssl for the following options From a27bd88c3daf13b22dc25abe8ac58e92b8326050 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 24 Mar 2023 16:15:12 +0100 Subject: [PATCH 48/69] [HttpClient] Fix not calling the on progress callback when canceling a MockResponse --- .../HttpClient/Response/MockResponse.php | 4 ++++ .../HttpClient/Tests/MockHttpClientTest.php | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/Symfony/Component/HttpClient/Response/MockResponse.php b/src/Symfony/Component/HttpClient/Response/MockResponse.php index 6420aa05de79a..82b2cc172f0aa 100644 --- a/src/Symfony/Component/HttpClient/Response/MockResponse.php +++ b/src/Symfony/Component/HttpClient/Response/MockResponse.php @@ -110,6 +110,10 @@ public function cancel(): void } catch (TransportException $e) { // ignore errors when canceling } + + $onProgress = $this->requestOptions['on_progress'] ?? static function () {}; + $dlSize = isset($this->headers['content-encoding']) || 'HEAD' === $this->info['http_method'] || \in_array($this->info['http_code'], [204, 304], true) ? 0 : (int) ($this->headers['content-length'][0] ?? 0); + $onProgress($this->offset, $dlSize, $this->info); } /** diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index 8c697b4ee22c2..8d8b6af6227fb 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -506,4 +506,25 @@ public function testResetsRequestCount() $client->reset(); $this->assertSame(0, $client->getRequestsCount()); } + + public function testCancellingMockResponseExecutesOnProgressWithUpdatedInfo() + { + $client = new MockHttpClient(new MockResponse(['foo', 'bar', 'ccc'])); + $canceled = false; + $response = $client->request('GET', 'https://example.com', [ + 'on_progress' => static function (int $dlNow, int $dlSize, array $info) use (&$canceled): void { + $canceled = $info['canceled']; + }, + ]); + + foreach ($client->stream($response) as $response => $chunk) { + if ('bar' === $chunk->getContent()) { + $response->cancel(); + + break; + } + } + + $this->assertTrue($canceled); + } } From 8d2a02d1395c070cba608d0ddbc4acae032c9475 Mon Sep 17 00:00:00 2001 From: Matthieu Lempereur Date: Thu, 23 Mar 2023 10:06:45 +0100 Subject: [PATCH 49/69] [Notifier] Add bridge documentation --- .../Notifier/Bridge/Discord/README.md | 52 ++++++ .../Notifier/Bridge/MicrosoftTeams/README.md | 81 +++++++++ .../Component/Notifier/Bridge/Slack/README.md | 171 ++++++++++++++++++ .../Notifier/Bridge/Telegram/README.md | 33 ++++ 4 files changed, 337 insertions(+) diff --git a/src/Symfony/Component/Notifier/Bridge/Discord/README.md b/src/Symfony/Component/Notifier/Bridge/Discord/README.md index baa6279ac7796..97fc260708e96 100644 --- a/src/Symfony/Component/Notifier/Bridge/Discord/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Discord/README.md @@ -14,6 +14,58 @@ where: - `TOKEN` the secure token of the webhook (returned for Incoming Webhooks) - `ID` the id of the webhook +Adding Interactions to a Message +-------------------------------- + +With a Discord message, you can use the `DiscordOptions` class to add some +interactive options called Embed `elements`. + +```php +use Symfony\Component\Notifier\Bridge\Discord\DiscordOptions; +use Symfony\Component\Notifier\Bridge\Discord\Embeds\DiscordEmbed; +use Symfony\Component\Notifier\Bridge\Discord\Embeds\DiscordFieldEmbedObject; +use Symfony\Component\Notifier\Bridge\Discord\Embeds\DiscordFooterEmbedObject; +use Symfony\Component\Notifier\Bridge\Discord\Embeds\DiscordMediaEmbedObject; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage(''); + +// Create Discord Embed +$discordOptions = (new DiscordOptions()) + ->username('connor bot') + ->addEmbed((new DiscordEmbed()) + ->color(2021216) + ->title('New song added!') + ->thumbnail((new DiscordMediaEmbedObject()) + ->url('https://i.scdn.co/image/ab67616d0000b2735eb27502aa5cb1b4c9db426b')) + ->addField((new DiscordFieldEmbedObject()) + ->name('Track') + ->value('[Common Ground](https://open.spotify.com/track/36TYfGWUhIRlVjM8TxGUK6)') + ->inline(true) + ) + ->addField((new DiscordFieldEmbedObject()) + ->name('Artist') + ->value('Alasdair Fraser') + ->inline(true) + ) + ->addField((new DiscordFieldEmbedObject()) + ->name('Album') + ->value('Dawn Dance') + ->inline(true) + ) + ->footer((new DiscordFooterEmbedObject()) + ->text('Added ...') + ->iconUrl('https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Spotify_logo_without_text.svg/200px-Spotify_logo_without_text.svg.png') + ) + ) +; + + // Add the custom options to the chat message and send the message + $chatMessage->options($discordOptions); + + $chatter->send($chatMessage); +``` + Resources --------- diff --git a/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/README.md b/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/README.md index 5fab523c50e0a..8899b9b213f33 100644 --- a/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/README.md +++ b/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/README.md @@ -14,6 +14,87 @@ MICROSOFT_TEAMS_DSN=microsoftteams://default/PATH where: - `PATH` has the following format: `webhookb2/{uuid}@{uuid}/IncomingWebhook/{id}/{uuid}` +Adding text to a Message +------------------------ + +With a Microsoft Teams, you can use the `ChatMessage` class:: + +```php +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsTransport; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = (new ChatMessage('Contribute To Symfony'))->transport('microsoftteams'); +$chatter->send($chatMessage); +``` + +Adding Interactions to a Message +-------------------------------- + +With a Microsoft Teams Message, you can use the `MicrosoftTeamsOptions` class +to add [MessageCard options](https://docs.microsoft.com/en-us/outlook/actionable-messages/message-card-reference). + +```php +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Action\ActionCard; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Action\HttpPostAction; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Action\Input\DateInput; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Action\Input\TextInput; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsOptions; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsTransport; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Section\Field\Fact; +use Symfony\Component\Notifier\Bridge\MicrosoftTeams\Section\Section; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage(''); + +// Action elements +$input = new TextInput(); +$input->id('input_title'); +$input->isMultiline(true)->maxLength(5)->title('In a few words, why would you like to participate?'); + +$inputDate = new DateInput(); +$inputDate->title('Proposed date')->id('input_date'); + +// Create Microsoft Teams MessageCard +$microsoftTeamsOptions = (new MicrosoftTeamsOptions()) + ->title('Symfony Online Meeting') + ->text('Symfony Online Meeting are the events where the best developers meet to share experiences...') + ->summary('Summary') + ->themeColor('#F4D35E') + ->section((new Section()) + ->title('Talk about Symfony 5.3 - would you like to join? Please give a shout!') + ->fact((new Fact()) + ->name('Presenter') + ->value('Fabien Potencier') + ) + ->fact((new Fact()) + ->name('Speaker') + ->value('Patricia Smith') + ) + ->fact((new Fact()) + ->name('Duration') + ->value('90 min') + ) + ->fact((new Fact()) + ->name('Date') + ->value('TBA') + ) + ) + ->action((new ActionCard()) + ->name('ActionCard') + ->input($input) + ->input($inputDate) + ->action((new HttpPostAction()) + ->name('Add comment') + ->target('http://target') + ) + ) +; + +// Add the custom options to the chat message and send the message +$chatMessage->options($microsoftTeamsOptions); +$chatter->send($chatMessage); +``` + Resources --------- diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/README.md b/src/Symfony/Component/Notifier/Bridge/Slack/README.md index 3f7cda1c4e62d..b4062fe460da3 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Slack/README.md @@ -26,6 +26,177 @@ SLACK_DSN=slack://xoxb-......@default?channel=#my-channel-name SLACK_DSN=slack://xoxb-......@default?channel=fabien ``` +Adding Interactions to a Message +-------------------------------- + +With a Slack message, you can use the `SlackOptions` class to add some +interactive options called [Block elements](https://api.slack.com/reference/block-kit/block-elements). + +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackActionsBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackDividerBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackImageBlockElement; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Contribute To Symfony'); + +// Create Slack Actions Block and add some buttons +$contributeToSymfonyBlocks = (new SlackActionsBlock()) + ->button( + 'Improve Documentation', + 'https://symfony.com/doc/current/contributing/documentation/standards.html', + 'primary' + ) + ->button( + 'Report bugs', + 'https://symfony.com/doc/current/contributing/code/bugs.html', + 'danger' + ); + +$slackOptions = (new SlackOptions()) + ->block((new SlackSectionBlock()) + ->text('The Symfony Community') + ->accessory( + new SlackImageBlockElement( + 'https://symfony.com/favicons/apple-touch-icon.png', + 'Symfony' + ) + ) + ) + ->block(new SlackDividerBlock()) + ->block($contributeToSymfonyBlocks); + +// Add the custom options to the chat message and send the message +$chatMessage->options($slackOptions); + +$chatter->send($chatMessage); +``` + +Adding Fields and Values to a Message +------------------------------------- + +To add fields and values to your message you can use the `field()` method. + +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackDividerBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Symfony Feature'); + +$options = (new SlackOptions()) + ->block((new SlackSectionBlock())->text('My message')) + ->block(new SlackDividerBlock()) + ->block( + (new SlackSectionBlock()) + ->field('*Max Rating*') + ->field('5.0') + ->field('*Min Rating*') + ->field('1.0') + ); + +// Add the custom options to the chat message and send the message +$chatMessage->options($options); + +$chatter->send($chatMessage); +``` + +Adding a Header to a Message +---------------------------- + +To add a header to your message use the `SlackHeaderBlock` class. + +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackDividerBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackHeaderBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Symfony Feature'); + +$options = (new SlackOptions()) + ->block((new SlackHeaderBlock('My Header'))) + ->block((new SlackSectionBlock())->text('My message')) + ->block(new SlackDividerBlock()) + ->block( + (new SlackSectionBlock()) + ->field('*Max Rating*') + ->field('5.0') + ->field('*Min Rating*') + ->field('1.0') + ); + +// Add the custom options to the chat message and send the message +$chatMessage->options($options); + +$chatter->send($chatMessage); +``` + +Adding a Footer to a Message +---------------------------- + +To add a header to your message use the `SlackContextBlock` class. + +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackContextBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackDividerBlock; +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Symfony Feature'); + +$contextBlock = (new SlackContextBlock()) + ->text('My Context') + ->image('https://symfony.com/logos/symfony_white_03.png', 'Symfony Logo') +; + +$options = (new SlackOptions()) + ->block((new SlackSectionBlock())->text('My message')) + ->block(new SlackDividerBlock()) + ->block( + (new SlackSectionBlock()) + ->field('*Max Rating*') + ->field('5.0') + ->field('*Min Rating*') + ->field('1.0') + ) + ->block($contextBlock) +; + +// Add the custom options to the chat message and send the message +$chatMessage->options($options); + +$chatter->send($chatMessage); +``` + +Sending a Message as a Reply +---------------------------- + +To send your slack message as a reply in a thread use the `threadTs()` method. + +```php +use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Symfony Feature'); + +$options = (new SlackOptions()) + ->block((new SlackSectionBlock())->text('My reply')) + ->threadTs('1621592155.003100') +; + +// Add the custom options to the chat message and send the message +$chatMessage->options($options); + +$chatter->send($chatMessage); +``` + Resources --------- diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/README.md b/src/Symfony/Component/Notifier/Bridge/Telegram/README.md index 47b8c7b267573..3277630a9613f 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/README.md @@ -14,6 +14,39 @@ where: - `TOKEN` is your Telegram token - `CHAT_ID` is your Telegram chat id +Adding Interactions to a Message +-------------------------------- + +With a Telegram message, you can use the `TelegramOptions` class to add +[message options](https://core.telegram.org/bots/api). + +```php +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\Button\InlineKeyboardButton; +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\InlineKeyboardMarkup; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage(''); + +// Create Telegram options +$telegramOptions = (new TelegramOptions()) + ->chatId('@symfonynotifierdev') + ->parseMode('MarkdownV2') + ->disableWebPagePreview(true) + ->disableNotification(true) + ->replyMarkup((new InlineKeyboardMarkup()) + ->inlineKeyboard([ + (new InlineKeyboardButton('Visit symfony.com')) + ->url('https://symfony.com/'), + ]) + ); + +// Add the custom options to the chat message and send the message +$chatMessage->options($telegramOptions); + +$chatter->send($chatMessage); +``` + Resources --------- From f995db42c09cc623f02a039c9f49aaf0a966e359 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 3 Feb 2023 10:25:44 +0100 Subject: [PATCH 50/69] [VarDumper] Disable links for IntelliJ platform --- .../Formatter/OutputFormatterStyle.php | 3 +- .../Tests/Formatter/OutputFormatterTest.php | 45 +++++++++++++++++-- .../Component/VarDumper/Dumper/CliDumper.php | 3 +- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php b/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php index 0fb36ac632575..8370ba0587a79 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php @@ -96,7 +96,8 @@ public function apply(string $text) { if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); } if (null !== $this->href && $this->handlesHrefGracefully) { diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 84eb8d87f1fd9..203f5a3caf0ab 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -245,8 +245,14 @@ public function testFormatterHasStyles() /** * @dataProvider provideDecoratedAndNonDecoratedOutput */ - public function testNotDecoratedFormatter(string $input, string $expectedNonDecoratedOutput, string $expectedDecoratedOutput, string $terminalEmulator = 'foo') - { + public function testNotDecoratedFormatterOnJediTermEmulator( + string $input, + string $expectedNonDecoratedOutput, + string $expectedDecoratedOutput, + bool $shouldBeJediTerm = false + ) { + $terminalEmulator = $shouldBeJediTerm ? 'JetBrains-JediTerm' : 'Unknown'; + $prevTerminalEmulator = getenv('TERMINAL_EMULATOR'); putenv('TERMINAL_EMULATOR='.$terminalEmulator); @@ -258,6 +264,39 @@ public function testNotDecoratedFormatter(string $input, string $expectedNonDeco } } + /** + * @dataProvider provideDecoratedAndNonDecoratedOutput + */ + public function testNotDecoratedFormatterOnIDEALikeEnvironment( + string $input, + string $expectedNonDecoratedOutput, + string $expectedDecoratedOutput, + bool $expectsIDEALikeTerminal = false + ) { + // Backup previous env variable + $previousValue = $_SERVER['IDEA_INITIAL_DIRECTORY'] ?? null; + $hasPreviousValue = \array_key_exists('IDEA_INITIAL_DIRECTORY', $_SERVER); + + if ($expectsIDEALikeTerminal) { + $_SERVER['IDEA_INITIAL_DIRECTORY'] = __DIR__; + } elseif ($hasPreviousValue) { + // Forcibly remove the variable because the test runner may contain it + unset($_SERVER['IDEA_INITIAL_DIRECTORY']); + } + + try { + $this->assertEquals($expectedDecoratedOutput, (new OutputFormatter(true))->format($input)); + $this->assertEquals($expectedNonDecoratedOutput, (new OutputFormatter(false))->format($input)); + } finally { + // Rollback previous env state + if ($hasPreviousValue) { + $_SERVER['IDEA_INITIAL_DIRECTORY'] = $previousValue; + } else { + unset($_SERVER['IDEA_INITIAL_DIRECTORY']); + } + } + } + public static function provideDecoratedAndNonDecoratedOutput() { return [ @@ -268,7 +307,7 @@ public static function provideDecoratedAndNonDecoratedOutput() ['some text with inline style', 'some text with inline style', "\033[31msome text with inline style\033[39m"], ['some URL', 'some URL', "\033]8;;idea://open/?file=/path/SomeFile.php&line=12\033\\some URL\033]8;;\033\\"], ['>some URL with \', 'some URL with ', "\033]8;;https://example.com/\033\\some URL with \033]8;;\033\\"], - ['some URL', 'some URL', 'some URL', 'JetBrains-JediTerm'], + ['some URL', 'some URL', 'some URL', true], ]; } diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index e061c8d779fcc..b5d9ac3366bc8 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -448,7 +448,8 @@ protected function style(string $style, string $value, array $attr = []) if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); } if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { From 1dbf13e43b87883091caf0c5dd2b271ddd484842 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Feb 2023 16:02:53 +0100 Subject: [PATCH 51/69] [FrameworkBundle] Improve documentation about translation:extract --sort option The `--sort` option only works with `--dump-messages` (i.e. not with `--force`). It took me some time to realize that, and the documentation didn't help me since it was showing an example that didn't work. Contribute to https://github.com/symfony/symfony/issues/37918 --- .../FrameworkBundle/Command/TranslationUpdateCommand.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index f0e1dc8870aa6..7adc0b4bb5568 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -93,7 +93,7 @@ protected function configure() new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version (deprecated)'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically', 'asc'), + new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically (only works with --dump-messages)', 'asc'), new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setDescription(self::$defaultDescription) @@ -123,7 +123,6 @@ protected function configure() You can dump a tree-like structure using the yaml format with --as-tree flag: php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle - php %command.full_name% --force --format=yaml --sort=asc --as-tree=3 fr EOF ) From 1ddc90c21ebc0f39447826f224c5bce8af4f0956 Mon Sep 17 00:00:00 2001 From: MrYamous Date: Sat, 25 Mar 2023 16:01:13 +0100 Subject: [PATCH 52/69] update documentation for telegram bridge notifier --- .../Notifier/Bridge/Telegram/README.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/README.md b/src/Symfony/Component/Notifier/Bridge/Telegram/README.md index 47b8c7b267573..a142a59dd7fe3 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/README.md @@ -14,6 +14,86 @@ where: - `TOKEN` is your Telegram token - `CHAT_ID` is your Telegram chat id +Adding Interactions to a Message +-------------------------------- + +With a Telegram message, you can use the `TelegramOptions` class to add +[message options](https://core.telegram.org/bots/api). + +```php +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\Button\InlineKeyboardButton; +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\InlineKeyboardMarkup; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage(''); + +// Create Telegram options +$telegramOptions = (new TelegramOptions()) + ->chatId('@symfonynotifierdev') + ->parseMode('MarkdownV2') + ->disableWebPagePreview(true) + ->disableNotification(true) + ->replyMarkup((new InlineKeyboardMarkup()) + ->inlineKeyboard([ + (new InlineKeyboardButton('Visit symfony.com')) + ->url('https://symfony.com/'), + ]) + ); + +// Add the custom options to the chat message and send the message +$chatMessage->options($telegramOptions); + +$chatter->send($chatMessage); +``` + +Updating Messages +----------------- + +The `TelegramOptions::edit()` method was introduced in Symfony 6.2. + +When working with interactive callback buttons, you can use the `TelegramOptions` +to reference a previous message to edit. + +```php +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\Button\InlineKeyboardButton; +use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\InlineKeyboardMarkup; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Are you really sure?'); +$telegramOptions = (new TelegramOptions()) + ->chatId($chatId) + ->edit($messageId) // extracted from callback payload or SentMessage + ->replyMarkup((new InlineKeyboardMarkup()) + ->inlineKeyboard([ + (new InlineKeyboardButton('Absolutely'))->callbackData('yes'), + ]) + ); +``` + +Answering Callback Queries +-------------------------- + +The `TelegramOptions::answerCallbackQuery()` method was introduced in Symfony 6.3. + +When sending message with inline keyboard buttons with callback data, you can use +`TelegramOptions` to [answer callback queries](https://core.telegram.org/bots/api#answercallbackquery). + +```php +use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions; +use Symfony\Component\Notifier\Message\ChatMessage; + +$chatMessage = new ChatMessage('Thank you!'); +$telegramOptions = (new TelegramOptions()) + ->chatId($chatId) + ->answerCallbackQuery( + callbackQueryId: '12345', // extracted from callback + showAlert: true, + cacheTime: 1, + ); +``` + Resources --------- From 178abbf36ee4036143f80b5096f45ae2f81d869a Mon Sep 17 00:00:00 2001 From: Mathieu Santostefano Date: Mon, 27 Mar 2023 17:40:43 +0200 Subject: [PATCH 53/69] TranslatorBag::diff now iterates over catalogue domains instead of operation domains --- .../Command/TranslationPushCommandTest.php | 46 +++++++++++++++++++ .../Translation/Tests/TranslatorBagTest.php | 28 +++++++++++ .../Component/Translation/TranslatorBag.php | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Tests/Command/TranslationPushCommandTest.php b/src/Symfony/Component/Translation/Tests/Command/TranslationPushCommandTest.php index b174c5c0cfaa4..2c7f576c37091 100644 --- a/src/Symfony/Component/Translation/Tests/Command/TranslationPushCommandTest.php +++ b/src/Symfony/Component/Translation/Tests/Command/TranslationPushCommandTest.php @@ -89,6 +89,52 @@ public function testPushNewMessages() $this->assertStringContainsString('[OK] New local translations has been sent to "null" (for "en, fr" locale(s), and "messages" domain(s)).', trim($tester->getDisplay())); } + public function testPushNewIntlIcuMessages() + { + $arrayLoader = new ArrayLoader(); + $xliffLoader = new XliffFileLoader(); + $locales = ['en', 'fr']; + $domains = ['messages']; + + // Simulate existing messages on Provider + $providerReadTranslatorBag = new TranslatorBag(); + $providerReadTranslatorBag->addCatalogue($arrayLoader->load(['note' => 'NOTE'], 'en')); + $providerReadTranslatorBag->addCatalogue($arrayLoader->load(['note' => 'NOTE'], 'fr')); + + $provider = $this->createMock(ProviderInterface::class); + $provider->expects($this->once()) + ->method('read') + ->with($domains, $locales) + ->willReturn($providerReadTranslatorBag); + + // Create local files, with a new message + $filenameEn = $this->createFile([ + 'note' => 'NOTE', + 'new.foo' => 'newFooIntlIcu', + ], 'en', 'messages+intl-icu.%locale%.xlf'); + $filenameFr = $this->createFile([ + 'note' => 'NOTE', + 'new.foo' => 'nouveauFooIntlIcu', + ], 'fr', 'messages+intl-icu.%locale%.xlf'); + $localTranslatorBag = new TranslatorBag(); + $localTranslatorBag->addCatalogue($xliffLoader->load($filenameEn, 'en')); + $localTranslatorBag->addCatalogue($xliffLoader->load($filenameFr, 'fr')); + + $provider->expects($this->once()) + ->method('write') + ->with($localTranslatorBag->diff($providerReadTranslatorBag)); + + $provider->expects($this->once()) + ->method('__toString') + ->willReturn('null://default'); + + $tester = $this->createCommandTester($provider, $locales, $domains); + + $tester->execute(['--locales' => ['en', 'fr'], '--domains' => ['messages']]); + + $this->assertStringContainsString('[OK] New local translations has been sent to "null" (for "en, fr" locale(s), and "messages" domain(s)).', trim($tester->getDisplay())); + } + public function testPushForceMessages() { $xliffLoader = new XliffFileLoader(); diff --git a/src/Symfony/Component/Translation/Tests/TranslatorBagTest.php b/src/Symfony/Component/Translation/Tests/TranslatorBagTest.php index 58b8fa02bdc1b..102f2e443bb2f 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorBagTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorBagTest.php @@ -66,6 +66,34 @@ public function testDiff() ], $this->getAllMessagesFromTranslatorBag($bagResult)); } + public function testDiffWithIntlDomain() + { + $catalogueA = new MessageCatalogue('en', [ + 'domain1+intl-icu' => ['foo' => 'foo', 'bar' => 'bar'], + 'domain2' => ['baz' => 'baz', 'qux' => 'qux'], + ]); + + $bagA = new TranslatorBag(); + $bagA->addCatalogue($catalogueA); + + $catalogueB = new MessageCatalogue('en', [ + 'domain1' => ['foo' => 'foo'], + 'domain2' => ['baz' => 'baz', 'corge' => 'corge'], + ]); + + $bagB = new TranslatorBag(); + $bagB->addCatalogue($catalogueB); + + $bagResult = $bagA->diff($bagB); + + $this->assertEquals([ + 'en' => [ + 'domain1' => ['bar' => 'bar'], + 'domain2' => ['qux' => 'qux'], + ], + ], $this->getAllMessagesFromTranslatorBag($bagResult)); + } + public function testIntersect() { $catalogueA = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo', 'bar' => 'bar'], 'domain2' => ['baz' => 'baz', 'qux' => 'qux']]); diff --git a/src/Symfony/Component/Translation/TranslatorBag.php b/src/Symfony/Component/Translation/TranslatorBag.php index 555a9e8147fd2..6a4df3c3ceaa3 100644 --- a/src/Symfony/Component/Translation/TranslatorBag.php +++ b/src/Symfony/Component/Translation/TranslatorBag.php @@ -70,7 +70,7 @@ public function diff(TranslatorBagInterface $diffBag): self $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH); $newCatalogue = new MessageCatalogue($locale); - foreach ($operation->getDomains() as $domain) { + foreach ($catalogue->getDomains() as $domain) { $newCatalogue->add($operation->getNewMessages($domain), $domain); } From 290c88e29d549f7ec14c4ae9398c58bcdf53b912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rokas=20Mikalk=C4=97nas?= Date: Tue, 28 Mar 2023 12:32:52 +0300 Subject: [PATCH 54/69] [FrameworkBundle] Add missing monolog channel tag for messenger services --- .../Bundle/FrameworkBundle/Resources/config/messenger.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 813d503000de4..b5d257cbb2b20 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -140,6 +140,7 @@ ->args([ service('logger')->ignoreOnInvalid(), ]) + ->tag('monolog.logger', ['channel' => 'messenger']) ->set('messenger.transport.beanstalkd.factory', BeanstalkdTransportFactory::class) @@ -197,6 +198,7 @@ service('logger')->ignoreOnInvalid(), ]) ->tag('kernel.event_subscriber') + ->tag('monolog.logger', ['channel' => 'messenger']) ->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class) ->tag('kernel.event_subscriber') From be88fd00f80283464d6edf14ed04c9e9b6a8ff70 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 28 Mar 2023 16:39:01 +0200 Subject: [PATCH 55/69] [Cache] Fix storing binary keys when using pgsql --- .../Cache/Adapter/DoctrineDbalAdapter.php | 16 ++++++++++++++++ .../Component/Cache/Adapter/PdoAdapter.php | 16 ++++++++++++++++ .../Cache/Traits/AbstractAdapterTrait.php | 5 ++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php index 73f0ea6bcc480..16a0691cb2b42 100644 --- a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php @@ -334,6 +334,22 @@ protected function doSave(array $values, int $lifetime) return $failed; } + /** + * @internal + */ + protected function getId($key) + { + if ('pgsql' !== $this->platformName ??= $this->getPlatformName()) { + return parent::getId($key); + } + + if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { + $key = rawurlencode($key); + } + + return parent::getId($key); + } + private function getPlatformName(): string { if (isset($this->platformName)) { diff --git a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php index 5d107244312e7..34a0c12190700 100644 --- a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php @@ -559,6 +559,22 @@ protected function doSave(array $values, int $lifetime) return $failed; } + /** + * @internal + */ + protected function getId($key) + { + if ('pgsql' !== $this->driver ?? ($this->getConnection() ? $this->driver : null)) { + return parent::getId($key); + } + + if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { + $key = rawurlencode($key); + } + + return parent::getId($key); + } + private function getConnection(): \PDO { if (null === $this->conn) { diff --git a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php index c1a850877ff3d..32d78b1858cff 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php @@ -365,7 +365,10 @@ private function generateItems(iterable $items, array &$keys): \Generator } } - private function getId($key) + /** + * @internal + */ + protected function getId($key) { if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { $this->ids = []; From 71baeabc3096cb881f9e965a69ee7cc199e55228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rokas=20Mikalk=C4=97nas?= Date: Tue, 28 Mar 2023 18:04:16 +0300 Subject: [PATCH 56/69] [FrameworkBundle] Fix services usages output for text descriptor --- .../FrameworkBundle/Console/Descriptor/TextDescriptor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 4217a43b15414..e589f7b3400a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -361,7 +361,7 @@ protected function describeContainerDefinition(Definition $definition, array $op } $inEdges = null !== $builder && isset($options['id']) ? $this->getServiceEdges($builder, $options['id']) : []; - $tableRows[] = ['Usages', $inEdges ? implode(', ', $inEdges) : 'none']; + $tableRows[] = ['Usages', $inEdges ? implode(\PHP_EOL, $inEdges) : 'none']; $options['output']->table($tableHeaders, $tableRows); } From fd957a98bbdc11cb09ab8de1cb4fa36e95a1e79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 22 Mar 2023 11:10:23 +0100 Subject: [PATCH 57/69] [Console] Add missing ZSH mention in DumpCompletionCommand help --- .../Component/Console/Command/DumpCompletionCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Command/DumpCompletionCommand.php b/src/Symfony/Component/Console/Command/DumpCompletionCommand.php index 1ad1c0e7b6bf7..6a322c92954a6 100644 --- a/src/Symfony/Component/Console/Command/DumpCompletionCommand.php +++ b/src/Symfony/Component/Console/Command/DumpCompletionCommand.php @@ -52,10 +52,12 @@ protected function configure() default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"], }; + $supportedShells = implode(', ', $this->getSupportedShells()); + $this ->setHelp(<<%command.name% command dumps the shell completion script required -to use shell autocompletion (currently, bash and fish completion is supported). +to use shell autocompletion (currently, {$supportedShells} completion are supported). Static installation ------------------- From 7e5fe59c6d1c1c9651dcfb45212db99150f3faa1 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 29 Mar 2023 16:01:08 -0400 Subject: [PATCH 58/69] [Cache] Removing null coalescing assignment operator on 5.4 --- src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php index 16a0691cb2b42..700ad95b94abc 100644 --- a/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php @@ -339,7 +339,7 @@ protected function doSave(array $values, int $lifetime) */ protected function getId($key) { - if ('pgsql' !== $this->platformName ??= $this->getPlatformName()) { + if ('pgsql' !== $this->getPlatformName()) { return parent::getId($key); } From cf3d67ec88d5858d9f385bf75be6fca664e1edef Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Mar 2023 09:30:16 +0200 Subject: [PATCH 59/69] [DependencyInjection] Filter "container.excluded" services when using `findTaggedServiceIds()` --- .../Component/DependencyInjection/ContainerBuilder.php | 2 +- .../DependencyInjection/Tests/ContainerBuilderTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 4ac916b18f638..4fa6fca71ca75 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1212,7 +1212,7 @@ public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false $this->usedTags[] = $name; $tags = []; foreach ($this->getDefinitions() as $id => $definition) { - if ($definition->hasTag($name)) { + if ($definition->hasTag($name) && !$definition->hasTag('container.excluded')) { if ($throwOnAbstract && $definition->isAbstract()) { throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name)); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 042baf6084c52..c87de498a12ab 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -928,6 +928,11 @@ public function testfindTaggedServiceIds() ->addTag('bar', ['bar' => 'bar']) ->addTag('foo', ['foofoo' => 'foofoo']) ; + $builder + ->register('bar', 'Bar\FooClass') + ->addTag('foo') + ->addTag('container.excluded') + ; $this->assertEquals([ 'foo' => [ ['foo' => 'foo'], From cb71df8718655788f62f572ba88bd7983d8c54eb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Mar 2023 09:37:32 +0200 Subject: [PATCH 60/69] fix merge --- src/Symfony/Component/Cache/Adapter/PdoAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php index f897a0bfc2b5d..baee284a6bf28 100644 --- a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php @@ -341,7 +341,7 @@ protected function doSave(array $values, int $lifetime): array|bool */ protected function getId($key) { - if ('pgsql' !== $this->driver ?? ($this->getConnection() ? $this->driver : null)) { + if ('pgsql' !== $this->driver ??= ($this->getConnection() ? $this->driver : null)) { return parent::getId($key); } From f60218c2519c82df82cd8633197daf0bc528247b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 28 Mar 2023 17:33:18 +0200 Subject: [PATCH 61/69] [FrameworkBundle] Fix auto-discovering validator constraints --- .../Command/DebugAutowiringCommand.php | 3 +++ .../Resources/config/validator.php | 24 +++++++++---------- .../Bundle/FrameworkBundle/composer.json | 6 ++--- .../DependencyInjection/TranslatorPass.php | 8 ++++--- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php index 8e5395c7a4c01..7ac33243bb0c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php @@ -100,6 +100,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $previousId = '-'; $serviceIdsNb = 0; foreach ($serviceIds as $serviceId) { + if ($builder->hasDefinition($serviceId) && $builder->getDefinition($serviceId)->hasTag('container.excluded')) { + continue; + } $text = []; $resolvedServiceId = $serviceId; if (!str_starts_with($serviceId, $previousId)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php index c397e73d42505..63c6e928bfbe8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php @@ -28,6 +28,8 @@ $container->parameters() ->set('validator.mapping.cache.file', param('kernel.cache_dir').'/validation.php'); + $validatorsDir = \dirname((new \ReflectionClass(WhenValidator::class))->getFileName()); + $container->services() ->set('validator', ValidatorInterface::class) ->factory([service('validator.builder'), 'getValidator']) @@ -65,11 +67,15 @@ abstract_arg('Constraint validators locator'), ]) + ->load('Symfony\Component\Validator\Constraints\\', $validatorsDir.'/*Validator.php') + ->exclude($validatorsDir.'/ExpressionLanguageSyntaxValidator.php') + ->abstract() + ->tag('container.excluded') + ->tag('validator.constraint_validator') + ->set('validator.expression', ExpressionValidator::class) ->args([service('validator.expression_language')->nullOnInvalid()]) - ->tag('validator.constraint_validator', [ - 'alias' => 'validator.expression', - ]) + ->tag('validator.constraint_validator') ->set('validator.expression_language', ExpressionLanguage::class) ->args([service('cache.validator_expression_language')->nullOnInvalid()]) @@ -82,9 +88,7 @@ ->args([ abstract_arg('Default mode'), ]) - ->tag('validator.constraint_validator', [ - 'alias' => EmailValidator::class, - ]) + ->tag('validator.constraint_validator') ->set('validator.not_compromised_password', NotCompromisedPasswordValidator::class) ->args([ @@ -92,15 +96,11 @@ param('kernel.charset'), false, ]) - ->tag('validator.constraint_validator', [ - 'alias' => NotCompromisedPasswordValidator::class, - ]) + ->tag('validator.constraint_validator') ->set('validator.when', WhenValidator::class) ->args([service('validator.expression_language')->nullOnInvalid()]) - ->tag('validator.constraint_validator', [ - 'alias' => WhenValidator::class, - ]) + ->tag('validator.constraint_validator') ->set('validator.property_info_loader', PropertyInfoLoader::class) ->args([ diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index c7d3685f85088..4fc22ab7122bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -21,7 +21,7 @@ "ext-xml": "*", "symfony/cache": "^5.4|^6.0", "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.2", + "symfony/dependency-injection": "^6.2.8", "symfony/deprecation-contracts": "^2.1|^3", "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", @@ -58,7 +58,7 @@ "symfony/serializer": "^6.1", "symfony/stopwatch": "^5.4|^6.0", "symfony/string": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", + "symfony/translation": "^6.2.8", "symfony/twig-bundle": "^5.4|^6.0", "symfony/validator": "^5.4|^6.0", "symfony/workflow": "^5.4|^6.0", @@ -91,7 +91,7 @@ "symfony/security-csrf": "<5.4", "symfony/security-core": "<5.4", "symfony/stopwatch": "<5.4", - "symfony/translation": "<5.4", + "symfony/translation": "<6.2.8", "symfony/twig-bridge": "<5.4", "symfony/twig-bundle": "<5.4", "symfony/validator": "<5.4", diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php index b060171caebdd..3fb3f1f7beb62 100644 --- a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php @@ -53,10 +53,12 @@ public function process(ContainerBuilder $container) $constraintVisitorDefinition = $container->getDefinition('translation.extractor.visitor.constraint'); $constraintClassNames = []; - foreach ($container->findTaggedServiceIds('validator.constraint_validator', true) as $id => $attributes) { - $serviceDefinition = $container->getDefinition($id); + foreach ($container->getDefinitions() as $definition) { + if (!$definition->hasTag('validator.constraint_validator')) { + continue; + } // Resolve constraint validator FQCN even if defined as %foo.validator.class% parameter - $className = $container->getParameterBag()->resolveValue($serviceDefinition->getClass()); + $className = $container->getParameterBag()->resolveValue($definition->getClass()); // Extraction of the constraint class name from the Constraint Validator FQCN $constraintClassNames[] = str_replace('Validator', '', substr(strrchr($className, '\\'), 1)); } From 97b928e81587a679f2af1e08b37e38ac63b641a4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Mar 2023 15:35:57 +0200 Subject: [PATCH 62/69] [DependencyInjection] Fix setting the class of auto-discovery services --- .../Component/DependencyInjection/Loader/FileLoader.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index 6cb1e6ffdb4e1..f8a33182e748d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -138,6 +138,7 @@ public function registerClasses(Definition $prototype, string $namespace, string continue; } + $definition->setClass($class); foreach (class_implements($class, false) as $interface) { $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? false : $class; } @@ -253,7 +254,7 @@ private function findClasses(string $namespace, string $pattern, array $excludeP foreach ($excludePaths as $path => $_) { $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, str_ends_with($path, '.php') ? -4 : null)), '\\'); if (!$this->container->has($class)) { - $this->container->register($class) + $this->container->register($class, $class) ->setAbstract(true) ->addTag('container.excluded', $attributes); } From 1773dff5ce7c19867f2580ce9ec51886e6934483 Mon Sep 17 00:00:00 2001 From: Bastien Jaillot Date: Mon, 13 Mar 2023 21:59:14 +0100 Subject: [PATCH 63/69] [FrameworkBundle] enable metadata cache when annotation is disabled --- .../DependencyInjection/FrameworkExtension.php | 6 +++--- .../serializer_mapping_without_annotations.php | 14 ++++++++++++++ .../serializer_mapping_without_annotations.xml | 16 ++++++++++++++++ .../serializer_mapping_without_annotations.yml | 8 ++++++++ .../FrameworkExtensionTestCase.php | 10 ++++++++-- 5 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping_without_annotations.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping_without_annotations.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping_without_annotations.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 00412e5c68051..949890b44dff5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1777,9 +1777,6 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild private function registerSerializerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) { $loader->load('serializer.php'); - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); - } $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); @@ -1805,6 +1802,9 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { throw new \LogicException('"enable_annotations" on the serializer cannot be set as the PHP version is lower than 8 and Annotations support is disabled. Consider upgrading PHP.'); } + if ($container->getParameter('kernel.debug')) { + $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); + } $annotationLoader = new Definition( 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping_without_annotations.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping_without_annotations.php new file mode 100644 index 0000000000000..4126fd90008bd --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping_without_annotations.php @@ -0,0 +1,14 @@ +loadFromExtension('framework', [ + 'serializer' => [ + 'enable_annotations' => false, + 'mapping' => [ + 'paths' => [ + '%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files', + '%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml', + '%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml', + ], + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping_without_annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping_without_annotations.xml new file mode 100644 index 0000000000000..53c4b2f0260ee --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping_without_annotations.xml @@ -0,0 +1,16 @@ + + + + + + + + %kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files + %kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml + %kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping_without_annotations.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping_without_annotations.yml new file mode 100644 index 0000000000000..e7f5bc4b8ec98 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping_without_annotations.yml @@ -0,0 +1,8 @@ +framework: + serializer: + enable_annotations: false + mapping: + paths: + - "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files" + - "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml" + - "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index a1c67eef1874c..e1ac8463023c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1529,9 +1529,15 @@ public function testSerializerCacheActivated() $this->assertEquals(new Reference('serializer.mapping.cache.symfony'), $cache); } - public function testSerializerCacheNotActivatedDebug() + public function testSerializerCacheUsedWithoutAnnotationsAndMappingFiles() { - $container = $this->createContainerFromFile('serializer_enabled', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]); + $container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]); + $this->assertTrue($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); + } + + public function testSerializerCacheNotActivatedWithAnnotations() + { + $container = $this->createContainerFromFile('serializer_mapping', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]); $this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); } From c1f844acc69fe5e6c1f9cda38763b19e14458205 Mon Sep 17 00:00:00 2001 From: Vladimir Melnik Date: Mon, 6 Mar 2023 17:01:54 +0100 Subject: [PATCH 64/69] [Serializer] Preserve array keys while denormalize variadic parameters --- .../Normalizer/AbstractNormalizer.php | 4 +-- .../Normalizer/AbstractNormalizerTest.php | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 6805a29935d9c..6253045f3e884 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -362,8 +362,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex } $variadicParameters = []; - foreach ($data[$paramName] as $parameterData) { - $variadicParameters[] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $context, $format); + foreach ($data[$paramName] as $parameterKey => $parameterData) { + $variadicParameters[$parameterKey] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $context, $format); } $params = array_merge($params, $variadicParameters); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php index 822b21dd5e411..33f44430591f8 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php @@ -201,6 +201,36 @@ public function testObjectWithVariadicConstructorTypedArguments(AbstractNormaliz } } + /** + * @dataProvider getNormalizer + */ + public function testVariadicSerializationWithPreservingKeys(AbstractNormalizer $normalizer) + { + $d1 = new Dummy(); + $d1->foo = 'Foo'; + $d1->bar = 'Bar'; + $d1->baz = 'Baz'; + $d1->qux = 'Quz'; + $d2 = new Dummy(); + $d2->foo = 'FOO'; + $d2->bar = 'BAR'; + $d2->baz = 'BAZ'; + $d2->qux = 'QUZ'; + $arr = ['d1' => $d1, 'd2' => $d2]; + $obj = new VariadicConstructorTypedArgsDummy(...$arr); + + $serializer = new Serializer([$normalizer], [new JsonEncoder()]); + $normalizer->setSerializer($serializer); + $this->assertEquals( + '{"foo":{"d1":{"foo":"Foo","bar":"Bar","baz":"Baz","qux":"Quz"},"d2":{"foo":"FOO","bar":"BAR","baz":"BAZ","qux":"QUZ"}}}', + $data = $serializer->serialize($obj, 'json') + ); + + $dummy = $normalizer->denormalize(json_decode($data, true), VariadicConstructorTypedArgsDummy::class); + $this->assertInstanceOf(VariadicConstructorTypedArgsDummy::class, $dummy); + $this->assertEquals($arr, $dummy->getFoo()); + } + public static function getNormalizer() { $extractor = new PhpDocExtractor(); From d82ec41d1879a95e0ffddb0337e4da356d4b0746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20B=C3=B6nner?= Date: Thu, 23 Feb 2023 10:01:28 +0100 Subject: [PATCH 65/69] [Serializer] Fix serializedpath for non scalar types --- .../Normalizer/AbstractObjectNormalizer.php | 11 ++++---- .../AbstractObjectNormalizerTest.php | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 7c4c5fb41bd49..1feff46ad3d56 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -198,14 +198,15 @@ public function normalize(mixed $object, string $format = null, array $context = $attributeValue = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext); - if (null !== $attributeValue && !\is_scalar($attributeValue)) { - $stack[$attribute] = $attributeValue; - } - - $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata); + $stack[$attribute] = $attributeValue; } foreach ($stack as $attribute => $attributeValue) { + if (null === $attributeValue || \is_scalar($attributeValue)) { + $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $context, $attributesMetadata, $classMetadata); + continue; + } + if (!$this->serializer instanceof NormalizerInterface) { throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer.', $attribute)); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 4cc6686586e89..9a319f7ef0b8a 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -542,6 +542,21 @@ public function testDenormalizeUsesContextAttributeForPropertiesInConstructorWit $this->assertSame($obj->propertyWithSerializedName->format('Y-m-d'), $obj->propertyWithoutSerializedName->format('Y-m-d')); } + + public function testNormalizeUsesContextAttributeForPropertiesInConstructorWithSerializedPath() + { + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); + + $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]); + $normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory), null, $extractor); + $serializer = new Serializer([new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'd-m-Y']), $normalizer]); + + $obj = new ObjectDummyWithContextAttributeAndSerializedPath(new \DateTimeImmutable('22-02-2023')); + + $data = $serializer->normalize($obj); + + $this->assertSame(['property' => ['with_path' => '22-02-2023']], $data); + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -643,6 +658,16 @@ class DuplicateKeyNestedDummy public $notquux; } +class ObjectDummyWithContextAttributeAndSerializedPath +{ + public function __construct( + #[Context([DateTimeNormalizer::FORMAT_KEY => 'm-d-Y'])] + #[SerializedPath('[property][with_path]')] + public \DateTimeImmutable $propertyWithPath, + ) { + } +} + class AbstractObjectNormalizerWithMetadata extends AbstractObjectNormalizer { public function __construct() From 7d987b756f08822b167c66ca16f9061e100479aa Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 31 Mar 2023 11:21:17 +0200 Subject: [PATCH 66/69] Fix test --- .../Serializer/Tests/Normalizer/AbstractNormalizerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php index 33f44430591f8..d9e65ec2f6cd0 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php @@ -202,6 +202,8 @@ public function testObjectWithVariadicConstructorTypedArguments(AbstractNormaliz } /** + * @requires PHP 8 + * * @dataProvider getNormalizer */ public function testVariadicSerializationWithPreservingKeys(AbstractNormalizer $normalizer) From 85167dafbc71fc7d96bf5779f0abaf93e77c5666 Mon Sep 17 00:00:00 2001 From: Thorry84 Date: Mon, 27 Mar 2023 17:45:10 +0200 Subject: [PATCH 67/69] [Form] CollectionType apply prototypeOptions to ResizeFormListener new fields --- .../Core/EventListener/ResizeFormListener.php | 6 +++-- .../Extension/Core/Type/CollectionType.php | 4 +++- .../Core/Type/CollectionTypeTest.php | 23 +++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index a524e15574d4e..f68d5b6d2c9c5 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -26,18 +26,20 @@ class ResizeFormListener implements EventSubscriberInterface { protected $type; protected $options; + protected $prototypeOptions; protected $allowAdd; protected $allowDelete; private \Closure|bool $deleteEmpty; - public function __construct(string $type, array $options = [], bool $allowAdd = false, bool $allowDelete = false, bool|callable $deleteEmpty = false) + public function __construct(string $type, array $options = [], bool $allowAdd = false, bool $allowDelete = false, bool|callable $deleteEmpty = false, array $prototypeOptions = null) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; $this->deleteEmpty = \is_bool($deleteEmpty) ? $deleteEmpty : $deleteEmpty(...); + $this->prototypeOptions = $prototypeOptions ?? $options; } public static function getSubscribedEvents(): array @@ -96,7 +98,7 @@ public function preSubmit(FormEvent $event) if (!$form->has($name)) { $form->add($name, $this->type, array_replace([ 'property_path' => '['.$name.']', - ], $this->options)); + ], $this->prototypeOptions)); } } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php b/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php index c310441cc7121..f93c36abbbdc3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php @@ -23,6 +23,7 @@ class CollectionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { + $prototypeOptions = null; if ($options['allow_add'] && $options['prototype']) { $prototypeOptions = array_replace([ 'required' => $options['required'], @@ -42,7 +43,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['entry_options'], $options['allow_add'], $options['allow_delete'], - $options['delete_empty'] + $options['delete_empty'], + $prototypeOptions ); $builder->addEventSubscriber($resizeListener); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php index c7e10307b2029..81626110481b1 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -447,6 +447,29 @@ public function testPrototypeOptionsOverrideEntryOptions() $this->assertSame('foo', $form->createView()->vars['prototype']->vars['help']); } + public function testPrototypeOptionsAppliedToNewFields() + { + $form = $this->factory->create(static::TESTED_TYPE, ['first'], [ + 'allow_add' => true, + 'prototype' => true, + 'entry_type' => TextTypeTest::TESTED_TYPE, + 'entry_options' => [ + 'disabled' => true, + ], + 'prototype_options' => [ + 'disabled' => false, + ], + ]); + + $form->submit(['first_changed', 'second']); + + $this->assertTrue($form->has('0')); + $this->assertTrue($form->has('1')); + $this->assertSame('first', $form[0]->getData()); + $this->assertSame('second', $form[1]->getData()); + $this->assertSame(['first', 'second'], $form->getData()); + } + public function testEntriesBlockPrefixes() { $collectionView = $this->factory->createNamed('fields', static::TESTED_TYPE, [''], [ From dc40e7fff939bf6af2f633028b25ec4f8b17f6af Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 31 Mar 2023 14:00:04 +0200 Subject: [PATCH 68/69] Update CHANGELOG for 6.2.8 --- CHANGELOG-6.2.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/CHANGELOG-6.2.md b/CHANGELOG-6.2.md index e9ac6bc6784f1..3dcd15ef1ab8b 100644 --- a/CHANGELOG-6.2.md +++ b/CHANGELOG-6.2.md @@ -7,6 +7,41 @@ in 6.2 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/v6.2.0...v6.2.1 +* 6.2.8 (2023-03-31) + + * bug #49835 [Form] CollectionType apply prototypeOptions to ResizeFormListener new fields (Thorry84) + * bug #49849 [FrameworkBundle] Fix services usages output for text descriptor (rmikalkenas) + * bug #49525 [Serializer] Fix serialized path for non-scalar values (boenner) + * bug #49618 [Serializer] Preserve array keys while denormalize variadic parameters (melya) + * bug #49401 [TwigBridge] Fix raw content rendering in HTML notification emails (1ed) + * bug #49679 [FrameworkBundle] enable metadata cache when annotation is disabled (bastnic) + * bug #49796 [HttpClient] Fix not calling the on progress callback when canceling a MockResponse (fancyweb) + * bug #49850 [FrameworkBundle] Fix auto-discovering validator constraints (nicolas-grekas) + * bug #49867 [DependencyInjection] Filter "container.excluded" services when using `findTaggedServiceIds()` (nicolas-grekas) + * bug #49833 [Translation] TranslatorBag::diff now iterates over catalogue domains instead of operation domains (welcoMattic) + * bug #49848 [Cache] Fix storing binary keys when using pgsql (nicolas-grekas) + * bug #49765 [Console] Add missing ZSH mention in DumpCompletionCommand help (lyrixx) + * bug #49843 [FrameworkBundle] Add missing monolog channel tag for messenger services (rmikalkenas) + * bug #49745 [FrameworkBundle] Fix wiring session.handler when handler_id is null (nicolas-grekas) + * bug #49189 [FrameworkBundle] Improve documentation about translation:extract --sort option (marien-probesys) + * bug #49274 [VarDumper] Disable links for IntelliJ platform (SerafimArts) + * bug #49682 [FrameworkBundle] Workflow - Fix LogicException about a wrong configuration of "enabled" node (adpauly) + * bug #49758 [HttpFoundation] Use separate caches for IpUtils checkIp4 and checkIp6 (danielburger1337) + * bug #49722 [HttpClient] Encode and decode curly brackets {} (pbowyer) + * bug #49720 [Serializer] GetSetMethodNormalizer::supportss should not check ignored methods (nikophil) + * bug #49681 [String] Correct inflection of 'codes' and 'names' (GwendolenLynch) + * bug #49697 [Validator] Update BIC validator IBAN mappings (maxbeckers) + * bug #49706 Stop stopwatch events in case of exception (MatTheCat) + * bug #49657 [HttpKernel] Change limit argument from string to integer for Profiler (Aliance) + * bug #49674 [FrameworkBundle] Rename limiter’s `strategy` to `policy` in XSD (MatTheCat) + * bug #49673 [VarDumper] Fixed dumping of CutStub (lyrixx) + * bug #49604 [Mailer] STDOUT blocks infinitely under Windows when STDERR is filled (TemaYud) + * bug #49651 [DependencyInjection] Fix support binary values in parameters. (vtsykun) + * bug #49548 [Messenger] Fix `TransportNamesStamp` deserialization (tucksaun) + * bug #49580 [HttpClient] Fix encoding "+" in URLs (nicolas-grekas) + * bug #49541 [Security] Remove ``@internal`` tag on `TraceableAuthenticator::getAuthenticator()` (florentdestremau) + * bug #49578 [DependencyInjection] Fix dumping array of enums parameters (fancyweb) + * 6.2.7 (2023-02-28) * bug #49526 [Security] Migrate the session on login only when the user changes (nicolas-grekas) From 70f99945b0e0af8b6575cb23499edfef2625e4e3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 31 Mar 2023 14:00:10 +0200 Subject: [PATCH 69/69] Update VERSION for 6.2.8 --- 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 20031c5d1167d..1b0c6224b00ee 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -75,12 +75,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.2.8-DEV'; + public const VERSION = '6.2.8'; public const VERSION_ID = 60208; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 2; public const RELEASE_VERSION = 8; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '07/2023'; public const END_OF_LIFE = '07/2023';