diff --git a/.appveyor.yml b/.appveyor.yml index e0d8c17dc1f56..1a91d001f0bee 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,7 @@ install: - php composer.phar global require --no-progress --no-scripts --no-plugins symfony/flex - git config --global user.email "" - git config --global user.name "Symfony" - - FOR /F "tokens=* USEBACKQ" %%F IN (`bash -c "grep branch-version composer.json | grep -o '[0-9.]*'"`) DO (SET SYMFONY_VERSION=%%F) + - FOR /F "tokens=* USEBACKQ" %%F IN (`bash -c "grep branch-version composer.json | grep -o '[0-9.x]*'"`) DO (SET SYMFONY_VERSION=%%F) - php .github/build-packages.php "HEAD^" %SYMFONY_VERSION% src\Symfony\Bridge\PhpUnit src\Symfony\Contracts - SET "SYMFONY_REQUIRE=>=%SYMFONY_VERSION%" - SET COMPOSER_ROOT_VERSION=%SYMFONY_VERSION%.x-dev diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index df9db03fa8bca..c113ccbf96f1b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | 5.x for features / 3.4, 4.4 or 5.1 for bug fixes +| Branch? | 5.x for features / 4.4 or 5.1 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1163e61a554fa..52531183458b8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -114,7 +114,7 @@ jobs: run: | COMPOSER_HOME="$(composer config home)" ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" - echo "COMPOSER_ROOT_VERSION=$(grep branch-version composer.json | grep -o '[0-9.]*').x-dev" >> $GITHUB_ENV + echo "COMPOSER_ROOT_VERSION=$(grep branch-version composer.json | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV - name: Determine composer cache directory id: composer-cache diff --git a/.php_cs.dist b/.php_cs.dist index 8b691441a3e36..84883ff9bf8b4 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -15,6 +15,7 @@ return PhpCsFixer\Config::create() 'protected_to_private' => false, 'native_constant_invocation' => true, 'combine_nested_dirname' => true, + 'list_syntax' => ['syntax' => 'short'], ]) ->setRiskyAllowed(true) ->setFinder( diff --git a/.travis.yml b/.travis.yml index d1f90d9babcfe..8d284a7a121bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,11 +28,11 @@ matrix: env: deps=high - php: 7.4 env: deps=low - - php: nightly + - php: 8.0snapshot services: [memcached] fast_finish: true allow_failures: - - php: nightly + - php: 8.0snapshot services: [memcached] cache: @@ -140,7 +140,7 @@ before_install: echo session.gc_probability = 0 >> $INI echo opcache.enable_cli = 1 >> $INI echo apc.enable_cli = 1 >> $INI - if [[ $PHP != nightly ]]; then + if [[ $PHP != 8.* ]]; then echo extension = memcached.so >> $INI fi done @@ -156,17 +156,17 @@ before_install: if ! php --ri sodium > /dev/null; then tfold ext.libsodium tpecl libsodium sodium.so $INI fi - if [[ $PHP = nightly ]]; then + if [[ $PHP = 8.* ]]; then tfold ext.memcached tpecl memcached-3.1.5 memcached.so $INI else tfold ext.mongodb tpecl mongodb-1.6.16 mongodb.so $INI tfold ext.zookeeper tpecl zookeeper-0.7.2 zookeeper.so $INI tfold ext.amqp tpecl amqp-1.10.2 amqp.so $INI - tfold ext.redis tpecl redis-5.2.2 redis.so $INI "no" fi tfold ext.apcu tpecl apcu-5.1.19 apcu.so $INI tfold ext.igbinary tpecl igbinary-3.1.6 igbinary.so $INI + tfold ext.redis tpecl redis-5.2.3 redis.so $INI "no" done - | @@ -199,7 +199,7 @@ install: git config --global user.email "" git config --global user.name "Symfony" - export SYMFONY_VERSION=$(grep branch-version composer.json | grep -o '[0-9.]*') + export SYMFONY_VERSION=$(grep branch-version composer.json | grep -o '[0-9.x]*') if [[ ! $deps ]]; then php .github/build-packages.php HEAD^ $SYMFONY_VERSION src/Symfony/Bridge/PhpUnit src/Symfony/Contracts @@ -234,7 +234,7 @@ install: - | # Set composer's platform to php 7.4 if we're on php 8. - if [[ $PHP = nightly ]]; then + if [[ $PHP = 8.* ]]; then composer config platform.php 7.4.99 export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 fi diff --git a/CHANGELOG-5.1.md b/CHANGELOG-5.1.md index 2787daf5a9f1d..0f8e3a5c324dd 100644 --- a/CHANGELOG-5.1.md +++ b/CHANGELOG-5.1.md @@ -7,6 +7,44 @@ in 5.1 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.1.0...v5.1.1 +* 5.1.8 (2020-10-28) + + * bug #38713 [DI] Fix Preloader exception when preloading a class with an unknown parent/interface (rgeraads) + * bug #38647 [HttpClient] relax auth bearer format requirements (xabbuh) + * bug #38699 [DependencyInjection] Preload classes with union types correctly (derrabus) + * bug #38669 [Serializer] fix decoding float XML attributes starting with 0 (Marcin Kruk) + * bug #38680 [PhpUnitBridge] Support new expect methods in test case polyfill (alcaeus) + * bug #38681 [PHPUnitBridge] Support PHPUnit 8 and PHPUnit 9 in constraint compatibility trait (alcaeus) + * bug #38686 [TwigBridge] Remove "transchoice" from the code base (nicolas-grekas) + * bug #38678 [String] fix before/after[Last]() returning the empty string instead of the original one on non-match (nicolas-grekas) + * bug #38679 [PhpUnitBridge] Add missing exporter function for PHPUnit 7 (alcaeus) + * bug #38659 [String] fix slicing in UnicodeString (nicolas-grekas) + * bug #38595 [TwigBridge] do not translate null placeholders or titles (xabbuh) + * bug #38635 [Cache] Use correct expiry in ChainAdapter (Nyholm) + * bug #38652 [Filesystem] Check if failed unlink was caused by permission denied (Nyholm) + * bug #38645 [PropertyAccess] forward the caught exception (xabbuh) + * bug #38612 [Messenger/Amqp] Allow setting option "login" in DSN (W0rma) + * bug #38618 [Messenger][Doctrine] Avoid early db access for pgsql detection (chalasr) + * bug #38604 [DoctrineBridge] indexBy does not refer to attributes, but to column names (xabbuh) + * bug #38606 [WebProfilerBundle] Hide debug toolbar in print view (jt2k) + * bug #38582 [DI] Fix Reflection file name with eval()\'d code (maxime-aknin) + * bug #38578 Add missing use statement (jderusse) + * bug #38516 [HttpFoundation] Fix Range Requests (BattleRattle) + * bug #38553 [Lock] Reset Key lifetime time before we acquire it (Nyholm) + * bug #38551 Remove content-type check on toArray methods (jderusse) + * bug #38546 [String] fix "is too large" ValueError on PHP 8 (nicolas-grekas) + * bug #38544 [DI] fix dumping env vars (nicolas-grekas) + * bug #38533 [TwigBridge] Fix preload hint and remove "unlinked class class@anonymous" warning (burned42) + * bug #38530 [HttpClient] fix reading the body after a ClientException (nicolas-grekas) + * bug #38510 [PropertyInfo] Support for the mixed type (derrabus) + * bug #38493 [HttpClient] Fix CurlHttpClient memory leak (HypeMC) + * bug #38456 [Cache] skip igbinary < 3.1.6 (nicolas-grekas) + * bug #38392 [Ldap] Bypass the use of `ldap_control_paged_result` on PHP >= 7.3 (lucasaba) + * bug #38444 [PhpUnitBridge] fix running parallel tests with phpunit 9 (nicolas-grekas) + * bug #38446 [PropertyInfo] Extract from default value doesn't set collection boolean (Korbeil) + * bug #38442 [VarDumper] fix truncating big arrays (nicolas-grekas) + * bug #38433 [Mime] Fix serialization of RawMessage (gilbertsoft) + * 5.1.7 (2020-10-04) * bug #38396 Handle consecutive supports() calls in the RememberMeAuthenticator (wouterj) diff --git a/CHANGELOG-5.2.md b/CHANGELOG-5.2.md index 0b7a3974cf757..4708969f2be28 100644 --- a/CHANGELOG-5.2.md +++ b/CHANGELOG-5.2.md @@ -7,6 +7,40 @@ in 5.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/v5.2.0...v5.2.1 +* 5.2.0-RC1 (2020-11-10) + + * bug #39004 [Messenger] Fix JSON deserialization of ErrorDetailsStamp and normalization of FlattenException::$statusText (Jean85) + * bug #38628 [DoctrineBridge] indexBy could reference to association columns (juanmiguelbesada) + * bug #39021 [DependencyInjection] Optimize circular collection by removing flattening (jderusse) + * bug #39031 [Ldap] Fix pagination (jderusse) + * bug #39038 [DoctrineBridge] also reset id readers (xabbuh) + * feature #39032 [Validator] Allow load mappings from attributes without doctrine/annotations (derrabus) + * feature #39022 [FrameworkBundle] Allow to use attribute-based configuration of routing/serializer without doctrine/annotations (derrabus) + * bug #39002 [Validator] Override the default option of the choice constraint (benji07) + * bug #39026 [Messenger] Fix DBAL deprecations in PostgreSqlConnection (chalasr) + * bug #39025 [DoctrineBridge] Fix DBAL deprecations in middlewares (derrabus) + * bug #38991 [Console] Fix ANSI when stdErr is not a tty (jderusse) + * bug #38980 [DependencyInjection] Fix circular reference with Factory + Lazy Iterrator (jderusse) + * bug #38986 [DoctrineBridge] accept converting Uid-as-strings to db-values (nicolas-grekas) + * feature #38850 [Messenger] Do not call getQueueUrl when the url is known in AmazonSqs transport (jderusse) + * feature #38940 [Messenger] Improve formatting of exception in failed message (Jeroen Noten) + * feature #38954 [HttpFundation][FrameworkBundle] Deprecate the HEADER_X_FORWARDED_ALL constant (jderusse) + * bug #38977 [HttpClient] Check status code before decoding content in TraceableResponse (chalasr) + * bug #38971 [PhpUnitBridge] fix replaying skipped tests (nicolas-grekas) + * bug #38910 [HttpKernel] Fix session initialized several times (jderusse) + * bug #38882 [DependencyInjection] Improve performances in CircualReference detection (jderusse) + * bug #38950 [Process] Dont test TTY if there is no TTY support (Nyholm) + * bug #38921 [PHPUnitBridge] Fixed crash on Windows with PHP 8 (villfa) + * feature #38919 [Console] Make error message more verbose (Nyholm) + * bug #38869 [SecurityBundle] inject only compatible token storage implementations for usage tracking (xabbuh) + * feature #38859 [HttpFoundation] Deprecate not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` (nicolas-grekas) + * bug #38894 [HttpKernel] Remove Symfony 3 compatibility code (derrabus) + * bug #38888 remove reflection-docblock from mime requirements (garak) + * bug #38895 [PhpUnitBridge] Fix wrong check for exporter in ConstraintTrait (alcaeus) + * bug #38879 [Cache] Fixed expiry could be int in ChainAdapter due to race conditions (phamviet) + * bug #38867 [FrameworkBundle] Fixing TranslationUpdateCommand failure when using "--no-backup" (liarco) + * bug #38856 [Cache] Add missing use statement (fabpot) + * 5.2.0-BETA3 (2020-10-28) * bug #38845 [Console] Register signal handling only for commands implemeting SignalableCommandInterface (lyrixx) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f3217f25a966c..5d3ae522834d7 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -22,18 +22,18 @@ Symfony is the result of the work of many people who made the code better - Jakub Zalas (jakubzalas) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) + - Alexander M. Turek (derrabus) - Wouter de Jong (wouterj) - Yonel Ceruto (yonelceruto) - - Alexander M. Turek (derrabus) - - Hugo Hamon (hhamon) - Thomas Calvet (fancyweb) + - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) - Samuel ROZE (sroze) - Romain Neutron (romain) - Pascal Borreli (pborreli) + - Jérémy DERUSSÉ (jderusse) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - - Jérémy DERUSSÉ (jderusse) - Jules Pietri (heah) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) @@ -42,12 +42,13 @@ Symfony is the result of the work of many people who made the code better - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Eriksen Costa (eriksencosta) - Tobias Nyholm (tobias) + - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Lynn van der Berg (kjarli) + - Jan Schädlich (jschaedl) - Matthias Pigulla (mpdude) - Diego Saint Esteben (dosten) - Pierre du Plessis (pierredup) @@ -55,28 +56,27 @@ Symfony is the result of the work of many people who made the code better - William Durand (couac) - Valentin Udaltsov (vudaltsov) - ornicar - - Jan Schädlich (jschaedl) - Dany Maillard (maidmaid) - Francis Besset (francisbesset) - stealth35 (stealth35) - Alexander Mols (asm89) + - Kevin Bond (kbond) - Konstantin Myakshin (koc) - Grégoire Paris (greg0ire) - Bulat Shakirzyanov (avalanche123) - - Kevin Bond (kbond) - Saša Stamenković (umpirsky) - Peter Rehm (rpet) - Gabriel Ostrolucký (gadelat) + - Titouan Galopin (tgalopin) - David Maicher (dmaicher) - Gábor Egyed (1ed) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - - Titouan Galopin (tgalopin) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) + - Mathieu Piot (mpiot) - Vladimir Reznichenko (kalessil) - Bilal Amarni (bamarni) - - Mathieu Piot (mpiot) - Florin Patan (florinpatan) - Jáchym Toušek (enumag) - Andrej Hudec (pulzarraider) @@ -86,13 +86,13 @@ Symfony is the result of the work of many people who made the code better - Charles Sarrazin (csarrazi) - Christian Raue - Douglas Greenshields (shieldo) + - Laurent VOULLEMIER (lvo) - Arnout Boks (aboks) + - Graham Campbell (graham) - Jérôme Tamarelle (gromnan) - - Laurent VOULLEMIER (lvo) - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Graham Campbell (graham) - David Buchmann (dbu) - Dariusz Ruminski - Fran Moreno (franmomu) @@ -100,11 +100,11 @@ Symfony is the result of the work of many people who made the code better - Brandon Turner - Luis Cordova (cordoval) - Daniel Holmes (dholmes) + - Alex Pott - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - John Wards (johnwards) - - Alex Pott - Antoine Hérault (herzult) - Paráda József (paradajozsef) - Arnaud Le Blanc (arnaud-lb) @@ -119,18 +119,19 @@ Symfony is the result of the work of many people who made the code better - marc.weistroff - Tomáš Votruba (tomas_votruba) - Peter Kokot (maastermedia) + - Lars Strojny (lstrojny) - lenar - Alexander Schwenn (xelaris) - Włodzimierz Gajda (gajdaw) + - Alexander Schranz (alexander-schranz) + - Oskar Stark (oskarstark) - Adrien Brault (adrienbrault) - - Lars Strojny (lstrojny) - Massimiliano Arione (garak) - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) - Teoh Han Hui (teohhanhui) - Przemysław Bogusz (przemyslaw-bogusz) - Colin Frei - - Oskar Stark (oskarstark) - Javier Spagnoletti (phansys) - Joshua Thijssen - Daniel Wehner (dawehner) @@ -138,7 +139,6 @@ Symfony is the result of the work of many people who made the code better - excelwebzone - Gordon Franke (gimler) - Joel Wurtz (brouznouf) - - Alexander Schranz (alexander-schranz) - Fabien Pennequin (fabienpennequin) - Julien Falque (julienfalque) - Théo FIDRY (theofidry) @@ -175,6 +175,7 @@ Symfony is the result of the work of many people who made the code better - Rafael Dohms (rdohms) - jwdeitch - Ahmed TAILOULOUTE (ahmedtai) + - Andreas Braun - Mikael Pajunen - Arman Hosseini (arman) - Niels Keurentjes (curry684) @@ -209,6 +210,7 @@ Symfony is the result of the work of many people who made the code better - Marek Štípek (maryo) - Filippo Tessarotto (slamdunk) - Daniel Espendiller + - Maxime Helias (maxhelias) - Possum - Dorian Villet (gnutix) - Michaël Perrin (michael.perrin) @@ -228,9 +230,9 @@ Symfony is the result of the work of many people who made the code better - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) - Jan Rosier (rosier) - - Andreas Braun - Mathieu Lemoine (lemoinem) - Rémon van de Kamp (rpkamp) + - HypeMC - Christian Schmidt - Andreas Hucks (meandmymonkey) - Tom Van Looy (tvlooy) @@ -246,7 +248,6 @@ Symfony is the result of the work of many people who made the code better - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) - apetitpa - - Maxime Helias (maxhelias) - Matthieu Bontemps (mbontemps) - apetitpa - Pierre Minnieur (pminnieur) @@ -255,6 +256,7 @@ Symfony is the result of the work of many people who made the code better - Dominique Bongiraud - Hidde Wieringa (hiddewie) - Jeremy Livingston (jeremylivingston) + - Olivier Dolbeau (odolbeau) - Michael Lee (zerustech) - Dmitrii Poddubnyi (karser) - Matthieu Auger (matthieuauger) @@ -288,7 +290,6 @@ Symfony is the result of the work of many people who made the code better - Marco Pivetta (ocramius) - Antonio Pauletich (x-coder264) - Jeroen Spee (jeroens) - - Olivier Dolbeau (odolbeau) - Rob Frawley 2nd (robfrawley) - julien pauli (jpauli) - Lorenz Schori @@ -304,6 +305,7 @@ Symfony is the result of the work of many people who made the code better - Elnur Abdurrakhimov (elnur) - Manuel Reinhard (sprain) - Danny Berger (dpb587) + - zairig imad (zairigimad) - Antonio J. García Lagar (ajgarlag) - Adam Prager (padam87) - Benoît Burnichon (bburnichon) @@ -338,11 +340,13 @@ Symfony is the result of the work of many people who made the code better - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - jdhoek + - Michael Käfer (michael_kaefer) - Bob den Otter (bopp) - Thomas Schulz (king2500) - Frank de Jonge (frenkynet) - Nikita Konstantinov - Wodor Wodorski + - Timo Bakx (timobakx) - Joe Bennett (kralos) - Thomas Lallement (raziel057) - soyuka @@ -370,8 +374,8 @@ Symfony is the result of the work of many people who made the code better - Simon Mönch (sm) - Christian Schmidt - Patrick Landolt (scube) - - HypeMC - MatTheCat + - Bohan Yang (brentybh) - Vilius Grigaliūnas - David Badura (davidbadura) - Chad Sikorra (chadsikorra) @@ -379,6 +383,7 @@ Symfony is the result of the work of many people who made the code better - Chris Smith (cs278) - Thomas Bisignani (toma) - Florian Klein (docteurklein) + - Timothée Barray (tyx) - Benjamin Leveque (benji07) - Manuel Kiessling (manuelkiessling) - Alexey Kopytko (sanmai) @@ -412,7 +417,6 @@ Symfony is the result of the work of many people who made the code better - Romain Pierre (romain-pierre) - Julien Galenski (ruian) - Thomas Landauer (thomas-landauer) - - Michael Käfer (michael_kaefer) - Bongiraud Dominique - janschoenherr - Emanuele Gaspari (inmarelibero) @@ -423,6 +427,8 @@ Symfony is the result of the work of many people who made the code better - Sebastien Morel (plopix) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) + - ivan + - Karoly Gossler (connorhu) - Ahmed Raafat - Philippe Segatori - Gennady Telegin (gtelegin) @@ -432,6 +438,7 @@ Symfony is the result of the work of many people who made the code better - Matthew Lewinski (lewinski) - Magnus Nordlander (magnusnordlander) - Thomas Royer (cydonia7) + - Nicolas Philippe (nikophil) - Nicolas LEFEVRE (nicoweb) - alquerci - Oleg Andreyev @@ -441,12 +448,13 @@ Symfony is the result of the work of many people who made the code better - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) + - Romaric Drigon (romaricdrigon) - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Dmytro Borysovskyi (dmytr0) - Tomasz Kowalczyk (thunderer) + - Sylvain Fabre (sylfabre) - Artur Eshenbrener - - Timo Bakx (timobakx) - Harm van Tilborg (hvt) - Thomas Perez (scullwm) - Felix Labrecque @@ -498,7 +506,6 @@ Symfony is the result of the work of many people who made the code better - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer - - Timothée Barray (tyx) - Shein Alexey - Romain Gautier (mykiwi) - Joe Lencioni @@ -540,9 +547,12 @@ Symfony is the result of the work of many people who made the code better - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) - Webnet team (webnet) + - Ben Ramsey (ramsey) + - Nate Wiebe (natewiebe13) - Marcin Szepczynski (czepol) - Mohammad Emran Hasan (phpfour) - Farhad Safarov + - Dmitriy Mamontov (mamontovdmitriy) - Jan Schumann - Niklas Fiekas - Markus Bachmann (baachi) @@ -554,6 +564,7 @@ Symfony is the result of the work of many people who made the code better - Mihai Stancu - Ivan Nikolaev (destillat) - Gildas Quéméner (gquemener) + - Baptiste Leduc (korbeil) - Laurent Masforné (heisenberg) - Claude Khedhiri (ck-developer) - Desjardins Jérôme (jewome62) @@ -563,22 +574,25 @@ Symfony is the result of the work of many people who made the code better - Toni Rudolf (toooni) - Asmir Mustafic (goetas) - DerManoMann - - Nicolas Philippe (nikophil) - vagrant - Aurimas Niekis (gcds) - EdgarPE + - Bob van de Vijver (bobvandevijver) - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) - - Sylvain Fabre (sylfabre) - Martijn Cuppens - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) - Artem Lopata - Judicaël RUFFIEUX (axanagor) - Chris Sedlmayr (catchamonkey) + - Indra Gunawan (indragunawan) - Kamil Kokot (pamil) - Seb Koelen - Christoph Mewes (xrstf) + - Andrew M-Y (andr) + - Krasimir Bosilkov (kbosilkov) + - Marcin Michalski (marcinmichalski) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Dirk Pahl (dirkaholic) @@ -590,10 +604,11 @@ Symfony is the result of the work of many people who made the code better - Tobias Weichart - Tarmo Leppänen (tarlepp) - Marcin Sikoń (marphi) - - Bohan Yang (brentybh) + - M. Vondano - Dominik Zogg (dominik.zogg) - Marek Pietrzak - Luc Vieillescazes (iamluc) + - Lukáš Holeczy (holicz) - franek (franek) - Raulnet - Marco Petersen (ocrampete16) @@ -659,6 +674,7 @@ Symfony is the result of the work of many people who made the code better - Leevi Graham (leevigraham) - Anthony Ferrara - Ioan Negulescu + - Greg ORIOL - Jakub Škvára (jskvara) - Andrew Udvare (audvare) - alexpods @@ -668,7 +684,6 @@ Symfony is the result of the work of many people who made the code better - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) - Almog Baku (almogbaku) - - Karoly Gossler (connorhu) - Scott Arciszewski - Xavier HAUSHERR - Norbert Orzechowicz (norzechowicz) @@ -735,22 +750,18 @@ Symfony is the result of the work of many people who made the code better - Julien Montel (julienmgel) - Mátyás Somfai (smatyas) - Bastien DURAND (deamon) - - Ben Ramsey (ramsey) - Simon DELICATA - Artem Henvald (artemgenvald) - Dmitry Simushev - alcaeus - Thomas Talbot (ioni) - - Nate Wiebe (natewiebe13) - Fred Cox - vitaliytv - - ivan - Philippe Segatori - Dalibor Karlović (dkarlovi) - Andrey Sevastianov - Sebastian Blum - Alexis Lefebvre - - Dmitriy Mamontov (mamontovdmitriy) - aubx - Julien Turby - Marvin Butkereit @@ -761,7 +772,6 @@ Symfony is the result of the work of many people who made the code better - Max Rath (drak3) - marie - Stéphane Escandell (sescandell) - - Baptiste Leduc (korbeil) - Konstantin S. M. Möllers (ksmmoellers) - James Johnston - Noémi Salaün (noemi-salaun) @@ -779,7 +789,6 @@ Symfony is the result of the work of many people who made the code better - Christophe Villeger (seragan) - Matthias Krauser (mkrauser) - Julien Fredon - - Bob van de Vijver (bobvandevijver) - Xavier Leune (xleune) - Stefan Gehrig (sgehrig) - Hany el-Kerdany @@ -795,7 +804,6 @@ Symfony is the result of the work of many people who made the code better - Geoffrey Brier (geoffrey-brier) - Alexandre Parent - Vladimir Tsykun - - Romaric Drigon (romaricdrigon) - Dustin Dobervich (dustin10) - dantleech - Philipp Kolesnikov @@ -804,7 +812,9 @@ Symfony is the result of the work of many people who made the code better - Carlos Pereira De Amorim (epitre) - zenmate - Michal Trojanowski + - Lescot Edouard (idetox) - David Fuhr + - Rodrigo Aguilera - Mathias STRASSER (roukmoute) - Max Grigorian (maxakawizard) - Rostyslav Kinash @@ -822,13 +832,13 @@ Symfony is the result of the work of many people who made the code better - Xavier Briand (xavierbriand) - Ke WANG (yktd26) - Ivo Bathke (ivoba) + - David Molineus - Strate - Anton A. Sumin - Israel J. Carberry - Miquel Rodríguez Telep (mrtorrent) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - - M. Vondano - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Shaun Simmons (simshaun) @@ -909,6 +919,7 @@ Symfony is the result of the work of many people who made the code better - Davide Borsatto (davide.borsatto) - Julien DIDIER (juliendidier) - Dominik Ritter (dritter) + - Andreas Leathley (iquito) - Sebastian Grodzicki (sgrodzicki) - Mohamed Gamal - Jeroen van den Enden (stoefke) @@ -922,6 +933,7 @@ Symfony is the result of the work of many people who made the code better - Carson Full - Sergey Yastrebov - Trent Steel (trsteel88) + - Steve Grunwell - Yuen-Chi Lian - Tarjei Huse (tarjei) - Besnik Br @@ -949,10 +961,10 @@ Symfony is the result of the work of many people who made the code better - Casper Valdemar Poulsen - Josiah (josiah) - Guillaume Verstraete (versgui) - - Greg ORIOL - Joschi Kuphal - John Bohn (jbohn) - Marc Morera (mmoreram) + - Jason Tan - BENOIT POLASZEK (bpolaszek) - Julien Pauli - Mathieu Rochette (mathroc) @@ -1026,7 +1038,6 @@ Symfony is the result of the work of many people who made the code better - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) - Neil Ferreira - - Indra Gunawan (indragunawan) - Julie Hourcade (juliehde) - Dmitry Parnas (parnas) - Paul LE CORRE @@ -1034,6 +1045,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Gorgan - Tony Malzhacker - Mathieu MARCHOIS + - Tavo Nieves J - Cyril Quintin (cyqui) - Gerard van Helden (drm) - flack (flack) @@ -1098,6 +1110,7 @@ Symfony is the result of the work of many people who made the code better - Johnson Page (jwpage) - Ruben Gonzalez (rubenruateltek) - Michael Roterman (wtfzdotnet) + - Dieter - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) @@ -1133,6 +1146,7 @@ Symfony is the result of the work of many people who made the code better - Erik Saunier (snickers) - Thiago Cordeiro (thiagocordeiro) - Rootie + - Bernd Stellwag - Alireza Mirsepassi (alirezamirsepassi) - Daniel Alejandro Castro Arellano (lexcast) - sensio @@ -1157,6 +1171,7 @@ Symfony is the result of the work of many people who made the code better - Christian Jul Jensen - Alexandre GESLIN (alexandregeslin) - The Whole Life to Learn + - Pierre Tondereau - Alex Vo (votanlean) - Mikkel Paulson - ergiegonzaga @@ -1204,6 +1219,7 @@ Symfony is the result of the work of many people who made the code better - Luciano Mammino (loige) - fabios - Sander Coolen (scoolen) + - Laurent Clouet - Nicolas Le Goff (nlegoff) - Ben Oman - Chris de Kok @@ -1213,21 +1229,22 @@ Symfony is the result of the work of many people who made the code better - Guillaume (guill) - Igor Timoshenko (igor.timoshenko) - Manuele Menozzi - - zairig imad (zairigimad) - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) - Benoit Mallo - - Lescot Edouard (idetox) - Danilo Silva - Giuseppe Campanelli + - Valentin - pizzaminded - Arnaud PETITPAS (apetitpa) - Ken Stanley - Zachary Tong (polyfractal) - linh + - Guilherme Augusto Henschel - Mario Blažek (marioblazek) - Ashura - Hryhorii Hrebiniuk + - Eric Krona - johnstevenson - hamza - dantleech @@ -1238,6 +1255,7 @@ Symfony is the result of the work of many people who made the code better - Stanislav Kocanda - DerManoMann - Damien Fayet (rainst0rm) + - Ippei SUmida (ippey_s) - MatTheCat - Guillaume Royer - Artem (digi) @@ -1247,6 +1265,7 @@ Symfony is the result of the work of many people who made the code better - Pierrick VIGNAND (pierrick) - Vadim Tyukov (vatson) - Arman + - Adamo Crespi (aerendir) - David Wolter (davewww) - Sortex - chispita @@ -1322,12 +1341,15 @@ Symfony is the result of the work of many people who made the code better - Nikita Konstantinov - Martijn Evers - Philipp Fritsche + - tarlepp + - Luca Saba (lucasaba) - Benjamin Paap (benjaminpaap) - Claus Due (namelesscoder) - Christian - Alexandru Patranescu - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) + - Quentin Moreau (sheitak) - Mikkel Paulson - Michał Strzelecki - hugofonseca (fonsecas72) @@ -1420,13 +1442,13 @@ Symfony is the result of the work of many people who made the code better - Arun Philip - Rémi Leclerc - Jan Vernarsky + - Jonas Hünig - Amine Yakoubi - Eduardo García Sanz (coma) - Sergio (deverad) - Makdessi Alex - James Gilliland - fduch (fduch) - - David Molineus - Stuart Fyfe - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) @@ -1532,6 +1554,7 @@ Symfony is the result of the work of many people who made the code better - pthompson - Malaney J. Hill - Alexandre Pavy + - Adiel Cristo (arcristo) - Christian Flach (cmfcmf) - Cédric Girard (enk_) - Lars Ambrosius Wallenborn (larsborn) @@ -1547,6 +1570,7 @@ Symfony is the result of the work of many people who made the code better - Javier Espinosa - Anton Kroshilin - Dawid Sajdak + - Norman Soetbeer - Ludek Stepan - Aaron Stephens (astephens) - Craig Menning (cmenning) @@ -1557,7 +1581,6 @@ Symfony is the result of the work of many people who made the code better - Marc J. Schmidt (marcjs) - František Maša - Sebastian Schwarz - - Jason Tan - Marco Jantke - Saem Ghani - Clément LEFEBVRE @@ -1622,6 +1645,7 @@ Symfony is the result of the work of many people who made the code better - JL - Ilya Biryukov - Kim Laï Trinh + - Johan de Ruijter - Jason Desrosiers - m.chwedziak - Andreas Frömer @@ -1694,6 +1718,7 @@ Symfony is the result of the work of many people who made the code better - Mara Blaga - Rick Prent - skalpa + - Kai - Martin Eckhardt - Bartłomiej Zając - Pieter Jordaan @@ -1702,6 +1727,7 @@ Symfony is the result of the work of many people who made the code better - Michael Dowling (mtdowling) - Karlos Presumido (oneko) - Tony Vermeiren (tony) + - Jos Elstgeest - Thomas Counsell - BilgeXA - r1pp3rj4ck @@ -1746,6 +1772,7 @@ Symfony is the result of the work of many people who made the code better - Pablo Ogando Ferreira - Thomas Ploch - Simon Neidhold + - Ben Hakim - Valentin VALCIU - Jeremiah VALERIE - Julien Menth @@ -1773,6 +1800,7 @@ Symfony is the result of the work of many people who made the code better - Flavian (2much) - Gautier Deuette - mike + - Gilbertsoft - tadas - Kirk Madera - Keith Maika @@ -1792,6 +1820,7 @@ Symfony is the result of the work of many people who made the code better - Zdeněk Drahoš - Dan Harper - moldcraft + - Marcin Kruk - Antoine Bellion (abellion) - Ramon Kleiss (akathos) - Antonio Peric-Mazar (antonioperic) @@ -1853,6 +1882,7 @@ Symfony is the result of the work of many people who made the code better - Wing - Thomas Bibb - kick-the-bucket + - Joni Halme - Matt Farmer - catch - siganushka @@ -2216,6 +2246,7 @@ Symfony is the result of the work of many people who made the code better - Gyula Szucs - Tomas Liubinas - Alex + - Thomas P - Jan Hort - Klaas Naaijkens - Daniel González Cerviño @@ -2275,6 +2306,7 @@ Symfony is the result of the work of many people who made the code better - Vladimir Chernyshev (volch) - Wim Godden (wimg) - Yorkie Chadwick (yorkie76) + - Maxime Aknin (3m1x4m) - GuillaumeVerdon - Philipp Keck - Angel Fernando Quiroz Campos @@ -2383,7 +2415,6 @@ Symfony is the result of the work of many people who made the code better - Jack Wright - MrNicodemuz - Anonymous User - - Dieter - Paweł Tomulik - Eric J. Duran - Alexandru Bucur @@ -2546,6 +2577,7 @@ Symfony is the result of the work of many people who made the code better - Damián Nohales (eagleoneraptor) - Jordane VASPARD (elementaire) - Elliot Anderson (elliot) + - Erwan Nader (ernadoo) - Fabien D. (fabd) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) @@ -2619,6 +2651,7 @@ Symfony is the result of the work of many people who made the code better - Volker (skydiablo) - Success Go (successgo) - Julien Sanchez (sumbobyboys) + - Stephan Vierkant (svierkant) - Guillermo Gisinger (t3chn0r) - Markus Tacker (tacker) - Tom Newby (tomnewbyau) @@ -2645,6 +2678,7 @@ Symfony is the result of the work of many people who made the code better - simpson - Antoine Leblanc - drublic + - Andre Johnson - MaPePeR - Andreas Streichardt - Alexandre Segura diff --git a/UPGRADE-5.2.md b/UPGRADE-5.2.md index cd3c523d7644b..e62963fe2d50b 100644 --- a/UPGRADE-5.2.md +++ b/UPGRADE-5.2.md @@ -39,6 +39,12 @@ Form $builder->setDataMapper(new DataMapper(new PropertyPathAccessor())); ``` +HttpFoundation +-------------- + + * Deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. + * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead. + Lock ---- @@ -120,6 +126,36 @@ Validator * Deprecated the `NumberConstraintTrait` trait. + * Deprecated setting a Doctrine annotation reader via `ValidatorBuilder::enableAnnotationMapping()` + + Before: + + ```php + $builder->enableAnnotationMapping($reader); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->setDoctrineAnnotationReader($reader); + ``` + + * Deprecated creating a Doctrine annotation reader via `ValidatorBuilder::enableAnnotationMapping()` + + Before: + + ```php + $builder->enableAnnotationMapping(); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader(); + ``` + Security -------- diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 2ee58d9ce8f78..6e84d2c0dee2f 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -66,6 +66,8 @@ HttpFoundation * Removed `Response::create()`, `JsonResponse::create()`, `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use `__construct()` instead) + * Not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` throws an `InvalidArgumentException`; wrap your filter in a closure instead. + * Removed the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead. HttpKernel ---------- @@ -187,6 +189,36 @@ Validator * Removed the `NumberConstraintTrait` trait. +* `ValidatorBuilder::enableAnnotationMapping()` does not accept a Doctrine annotation reader anymore. + + Before: + + ```php + $builder->enableAnnotationMapping($reader); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->setDoctrineAnnotationReader($reader); + ``` + +* `ValidatorBuilder::enableAnnotationMapping()` won't automatically setup a Doctrine annotation reader anymore. + + Before: + + ```php + $builder->enableAnnotationMapping(); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader(); + ``` + Yaml ---- diff --git a/composer.json b/composer.json index c82f76928a98e..3034f796f7084 100644 --- a/composer.json +++ b/composer.json @@ -117,7 +117,6 @@ "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.10|^3.0", "doctrine/orm": "~2.4,>=2.4.5", - "doctrine/reflection": "~1.0", "doctrine/doctrine-bundle": "^2.0", "guzzlehttp/promises": "^1.3.1", "masterminds/html5": "^2.6", @@ -176,6 +175,6 @@ ], "minimum-stability": "dev", "extra": { - "branch-version": "5.2" + "branch-version": "5.x" } } diff --git a/phpunit b/phpunit index 71915eecb2b34..03bf63b0aae99 100755 --- a/phpunit +++ b/phpunit @@ -8,17 +8,12 @@ if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) { exit(1); } if (!getenv('SYMFONY_PHPUNIT_VERSION')) { - if (\PHP_VERSION_ID >= 70200) { - if (false === getenv('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT') && false !== strpos(@file_get_contents(__DIR__.'/src/Symfony/Component/HttpKernel/Kernel.php'), 'const MAJOR_VERSION = 3;')) { - putenv('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1'); - } - if (\PHP_VERSION_ID < 70300) { - putenv('SYMFONY_PHPUNIT_VERSION=8.5'); - } else { - putenv('SYMFONY_PHPUNIT_VERSION=9.4'); - } - } elseif (\PHP_VERSION_ID >= 70000) { - putenv('SYMFONY_PHPUNIT_VERSION=6.5'); + if (\PHP_VERSION_ID < 70200) { + putenv('SYMFONY_PHPUNIT_VERSION=7.5'); + } elseif (\PHP_VERSION_ID < 70300) { + putenv('SYMFONY_PHPUNIT_VERSION=8.5'); + } else { + putenv('SYMFONY_PHPUNIT_VERSION=9.4'); } } if (!getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php index 67bf68da01596..8e292cf36b8d7 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php @@ -191,7 +191,7 @@ private function sanitizeQuery(string $connectionName, array $query): array } } - list($query['params'][$j], $explainable, $runnable) = $this->sanitizeParam($param, $e); + [$query['params'][$j], $explainable, $runnable] = $this->sanitizeParam($param, $e); if (!$explainable) { $query['explainable'] = false; } @@ -227,7 +227,7 @@ private function sanitizeParam($var, ?\Throwable $error): array $a = []; $explainable = $runnable = true; foreach ($var as $k => $v) { - list($value, $e, $r) = $this->sanitizeParam($v, null); + [$value, $e, $r] = $this->sanitizeParam($v, null); $explainable = $explainable && $e; $runnable = $runnable && $r; $a[$k] = $value; diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index c1bbde27aa9c6..d2c8343ddb3c1 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -65,7 +65,7 @@ private function addTaggedSubscribers(ContainerBuilder $container) $taggedSubscribers = $this->findAndSortTags($subscriberTag, $container); foreach ($taggedSubscribers as $taggedSubscriber) { - list($id, $tag) = $taggedSubscriber; + [$id, $tag] = $taggedSubscriber; $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); foreach ($connections as $con) { if (!isset($this->connections[$con])) { @@ -84,7 +84,7 @@ private function addTaggedListeners(ContainerBuilder $container) $listenerRefs = []; foreach ($taggedListeners as $taggedListener) { - list($id, $tag) = $taggedListener; + [$id, $tag] = $taggedListener; if (!isset($tag['event'])) { throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); } diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index fd8b013185a69..d222659e5c080 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -42,7 +42,7 @@ public function guessType(string $class, string $property) return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); } - list($metadata, $name) = $ret; + [$metadata, $name] = $ret; if ($metadata->hasAssociation($property)) { $multiple = $metadata->isCollectionValuedAssociation($property); diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index bccb1a9ebdc3e..21b78bada3019 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -244,6 +244,7 @@ public function getParent() public function reset() { + $this->idReaders = []; $this->entityLoaders = []; } diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php index 3ec525d2cfd41..c6b219aa795ab 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Doctrine\Messenger; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Middleware\StackInterface; @@ -38,8 +39,8 @@ private function pingConnection(EntityManagerInterface $entityManager) $connection = $entityManager->getConnection(); try { - $connection->query($connection->getDatabasePlatform()->getDummySelectSQL()); - } catch (DBALException $e) { + $connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL()); + } catch (DBALException | Exception $e) { $connection->close(); $connection->connect(); } diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index ec8057ccb2b05..69d58e701dd57 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -89,10 +89,24 @@ public function getTypes(string $class, string $property, array $context = []) $associationMapping = $metadata->getAssociationMapping($property); if (isset($associationMapping['indexBy'])) { - $indexColumn = $associationMapping['indexBy']; /** @var ClassMetadataInfo $subMetadata */ $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); - $typeOfField = $subMetadata->getTypeOfField($subMetadata->getFieldForColumn($indexColumn)); + + // Check if indexBy value is a property + $fieldName = $associationMapping['indexBy']; + if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { + $fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']); + //Not a property, maybe a column name? + if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { + //Maybe the column name is the association join column? + $associationMapping = $subMetadata->getAssociationMapping($fieldName); + + /** @var ClassMetadataInfo $subMetadata */ + $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName); + $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); + } + } if (!$collectionKeyType = $this->getPhpType($typeOfField)) { return null; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php index 89aa779301350..33e6a6fd87235 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php @@ -24,7 +24,7 @@ */ class EntityTypePerformanceTest extends FormPerformanceTestCase { - const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; + private const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; /** * @var \Doctrine\ORM\EntityManager diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index ca9ab318d3f48..cc15da57ee6e8 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -39,14 +39,14 @@ class EntityTypeTest extends BaseTypeTest { const TESTED_TYPE = 'Symfony\Bridge\Doctrine\Form\Type\EntityType'; - const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; - const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; - const SINGLE_IDENT_NO_TO_STRING_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity'; - const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; - const SINGLE_ASSOC_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleAssociationToIntIdEntity'; - const SINGLE_STRING_CASTABLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringCastableIdEntity'; - const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; - const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity'; + private const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; + private const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; + private const SINGLE_IDENT_NO_TO_STRING_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity'; + private const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; + private const SINGLE_ASSOC_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleAssociationToIntIdEntity'; + private const SINGLE_STRING_CASTABLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringCastableIdEntity'; + private const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; + private const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity'; /** * @var EntityManager diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php index e491558a2addf..f99a48527c442 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware; @@ -49,7 +50,7 @@ public function testMiddlewarePingOk() { $this->connection->expects($this->once()) ->method('getDatabasePlatform') - ->will($this->throwException(new DBALException())); + ->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException())); $this->connection->expects($this->once()) ->method('close') @@ -68,7 +69,7 @@ public function testMiddlewarePingResetEntityManager() { $this->connection->expects($this->once()) ->method('getDatabasePlatform') - ->will($this->throwException(new DBALException())); + ->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException())); $this->entityManager->expects($this->once()) ->method('isOpen') diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 38ede592d9fe8..881b6b607e9d2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -64,10 +64,13 @@ public function testGetProperties() $expected = array_merge($expected, [ 'foo', 'bar', + 'indexedRguid', 'indexedBar', 'indexedFoo', + 'indexedBaz', 'indexedByDt', 'indexedByCustomType', + 'indexedBuz', ]); $this->assertEquals( @@ -143,6 +146,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], + ['indexedRguid', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + 'Doctrine\Common\Collections\Collection', + true, + new Type(Type::BUILTIN_TYPE_STRING), + new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') + )]], ['indexedBar', [new Type( Type::BUILTIN_TYPE_OBJECT, false, @@ -159,6 +170,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], + ['indexedBaz', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + Collection::class, + true, + new Type(Type::BUILTIN_TYPE_INT), + new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) + )]], ['simpleArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]], ['customFoo', null], ['notMapped', null], @@ -171,6 +190,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) )]], ['indexedByCustomType', null], + ['indexedBuz', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + Collection::class, + true, + new Type(Type::BUILTIN_TYPE_STRING), + new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) + )]], ['json', null], ]; diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 178ec9d0485d6..b7c5bffe6c7e4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -41,6 +41,11 @@ class DoctrineDummy */ public $bar; + /** + * @ManyToMany(targetEntity="DoctrineRelation", indexBy="rguid") + */ + protected $indexedRguid; + /** * @ManyToMany(targetEntity="DoctrineRelation", indexBy="rguid_column") */ @@ -51,6 +56,11 @@ class DoctrineDummy */ protected $indexedFoo; + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="baz", indexBy="baz_id") + */ + protected $indexedBaz; + /** * @Column(type="guid") */ @@ -123,6 +133,11 @@ class DoctrineDummy */ private $indexedByCustomType; + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="buzField", indexBy="buzField") + */ + protected $indexedBuz; + /** * @Column(type="json", nullable=true) */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php index e8f2b454cfa95..1131666483d22 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php @@ -23,7 +23,7 @@ class DoctrineFooType extends Type /** * Type name. */ - const NAME = 'foo'; + private const NAME = 'foo'; /** * {@inheritdoc} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php index e480ca9d777ba..d6d9af6d70c38 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php @@ -40,6 +40,11 @@ class DoctrineRelation */ protected $foo; + /** + * @ManyToOne(targetEntity="DoctrineDummy") + */ + protected $baz; + /** * @Column(type="datetime") */ @@ -49,4 +54,10 @@ class DoctrineRelation * @Column(type="foo") */ private $customType; + + /** + * @Column(type="guid", name="different_than_field") + * @ManyToOne(targetEntity="DoctrineDummy", inversedBy="indexedBuz") + */ + protected $buzField; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php index 8ea165b49769a..4141dfa55e540 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php @@ -52,11 +52,12 @@ public function testUlidConvertsToDatabaseValue() $this->assertEquals($expected, $actual); } - public function testNotSupportedStringUlidConversionToDatabaseValue() + public function testStringUlidConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $expected = Ulid::fromString(self::DUMMY_ULID)->toBinary(); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); - $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $this->assertEquals($expected, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php index 43715bb2324a1..f3969bcb4c725 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php @@ -68,11 +68,14 @@ public function testUlidInterfaceConvertsToDatabaseValue() $this->assertEquals('foo', $actual); } - public function testNotSupportedUlidStringConversionToDatabaseValue() + public function testUlidStringConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $ulid = Ulid::fromString(self::DUMMY_ULID); - $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $expected = $ulid->toRfc4122(); + + $this->assertEquals($expected, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php index 7d38606cf9054..b44a52578c5d2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php @@ -52,11 +52,21 @@ public function testUuidConvertsToDatabaseValue() $this->assertEquals($expected, $actual); } - public function testNotSupportedStringUuidConversionToDatabaseValue() + public function testStringUuidConvertsToDatabaseValue() + { + $uuid = self::DUMMY_UUID; + + $expected = uuid_parse(self::DUMMY_UUID); + $actual = $this->type->convertToDatabaseValue($uuid, $this->platform); + + $this->assertEquals($expected, $actual); + } + + public function testInvalidUuidConversionForDatabaseValue() { $this->expectException(ConversionException::class); - $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); + $this->type->convertToDatabaseValue('abcdefg', $this->platform); } public function testNullConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php index c5c6658dad7bd..da775ca81573c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php @@ -68,11 +68,11 @@ public function testUuidInterfaceConvertsToDatabaseValue() $this->assertEquals('foo', $actual); } - public function testNotSupportedUuidStringConversionToDatabaseValue() + public function testUuidStringConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); - $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); + $this->assertEquals(self::DUMMY_UUID, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php index bd9791bc65a96..2c9c3815654ba 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php @@ -28,7 +28,7 @@ public function testAttributeWithDefaultProperty() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame(['email'], $constraint->fields); self::assertTrue($constraint->ignoreNull); self::assertSame('doctrine.orm.validator.unique', $constraint->validatedBy()); @@ -42,7 +42,7 @@ public function testAttributeWithCustomizedService() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame(['isbn'], $constraint->fields); self::assertSame('my_own_validator', $constraint->validatedBy()); self::assertSame('my_own_entity_manager', $constraint->em); @@ -57,7 +57,7 @@ public function testAttributeWithGroupsAndPaylod() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame('uuid', $constraint->fields); self::assertSame('id', $constraint->errorPath); self::assertSame('some attached data', $constraint->payload); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 8507df94bf11c..7880ea92fede5 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -40,7 +40,7 @@ */ class UniqueEntityValidatorTest extends ConstraintValidatorTestCase { - const EM_NAME = 'foo'; + private const EM_NAME = 'foo'; /** * @var ObjectManager @@ -114,17 +114,8 @@ protected function createEntityManagerMock($repositoryMock) ->method('hasField') ->willReturn(true) ; - $reflParser = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionParser') - ->disableOriginalConstructor() - ->getMock() - ; - $refl = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionProperty') - ->setConstructorArgs([$reflParser, 'property-name']) - ->setMethods(['getValue']) - ->getMock() - ; + $refl = $this->createMock(\ReflectionProperty::class); $refl - ->expects($this->any()) ->method('getValue') ->willReturn(true) ; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 35a90044f7bab..31129a8c615d0 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -46,7 +46,8 @@ protected function setUp(): void public function testLoadClassMetadata() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{^Symfony\\\\Bridge\\\\Doctrine\\\\Tests\\\\Fixtures\\\\DoctrineLoader}')) ->getValidator() ; @@ -151,7 +152,8 @@ public function testLoadClassMetadata() public function testFieldMappingsConfiguration() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addXmlMappings([__DIR__.'/../Resources/validator/BaseUser.xml']) ->addLoader( new DoctrineLoader( @@ -192,7 +194,8 @@ public function regexpProvider() public function testClassNoAutoMapping() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{.*}')) ->getValidator(); diff --git a/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php b/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php index 9321d148ce3be..1dbb70abf556a 100644 --- a/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php +++ b/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php @@ -61,11 +61,19 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str return $value->toBinary(); } - if (null === $value) { + if (null === $value || '' === $value) { return null; } - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', AbstractUid::class]); + if (!\is_string($value)) { + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]); + } + + try { + return $this->getUidClass()::fromString($value)->toBinary(); + } catch (\InvalidArgumentException $e) { + throw ConversionException::conversionFailed($value, $this->getName()); + } } /** diff --git a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php index a14eb853e3868..4b57bc6b852f6 100644 --- a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php +++ b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php @@ -61,11 +61,19 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str return $value->toRfc4122(); } - if (null === $value) { + if (null === $value || '' === $value) { return null; } - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', AbstractUid::class]); + if (!\is_string($value)) { + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]); + } + + try { + return $this->getUidClass()::fromString($value)->toRfc4122(); + } catch (\InvalidArgumentException $e) { + throw ConversionException::conversionFailed($value, $this->getName()); + } } /** diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 78bc96de12ee2..48be4f9215efa 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -48,8 +48,7 @@ "doctrine/collections": "~1.0", "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.10|^3.0", - "doctrine/orm": "^2.6.3", - "doctrine/reflection": "~1.0" + "doctrine/orm": "^2.6.3" }, "conflict": { "doctrine/dbal": "<2.10", diff --git a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php index f170c526b8f74..f3d2fd8f024bb 100644 --- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php @@ -75,7 +75,7 @@ public function testGetLogsWithDebugProcessor2() $logger->info('test'); $this->assertCount(1, $logger->getLogs()); - list($record) = $logger->getLogs(); + [$record] = $logger->getLogs(); $this->assertEquals('test', $record['message']); $this->assertEquals(Logger::INFO, $record['priority']); diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php index 321bd7a8eed32..628facbb21277 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php @@ -22,7 +22,7 @@ class WebProcessorTest extends TestCase { public function testUsesRequestServerData() { - list($event, $server) = $this->createRequestEvent(); + [$event, $server] = $this->createRequestEvent(); $processor = new WebProcessor(); $processor->onKernelRequest($event); @@ -38,8 +38,8 @@ public function testUsesRequestServerData() public function testUseRequestClientIp() { - Request::setTrustedProxies(['192.168.0.1'], Request::HEADER_X_FORWARDED_ALL); - list($event, $server) = $this->createRequestEvent(['X_FORWARDED_FOR' => '192.168.0.2']); + Request::setTrustedProxies(['192.168.0.1'], Request::HEADER_X_FORWARDED_FOR); + [$event, $server] = $this->createRequestEvent(['X_FORWARDED_FOR' => '192.168.0.2']); $processor = new WebProcessor(); $processor->onKernelRequest($event); @@ -61,7 +61,7 @@ public function testCanBeConstructedWithExtraFields() $this->markTestSkipped('WebProcessor of the installed Monolog version does not support $extraFields parameter'); } - list($event, $server) = $this->createRequestEvent(); + [$event, $server] = $this->createRequestEvent(); $processor = new WebProcessor(['url', 'referrer']); $processor->onKernelRequest($event); diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php index 1e625e463a1e8..b132f473c547e 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php @@ -45,7 +45,7 @@ protected function additionalFailureDescription($other): string protected function exporter(): Exporter { - if (null !== $this->exporter) { + if (null === $this->exporter) { $this->exporter = new Exporter(); } diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 693883ed78762..6238fc0281209 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -123,7 +123,7 @@ public function startTestSuite($suite) $suiteName = $suite->getName(); foreach ($suite->tests() as $test) { - if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (!($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { continue; } if (null === Test::getPreserveGlobalStateSettings(\get_class($test), $test->getName(false))) { @@ -158,7 +158,7 @@ public function startTestSuite($suite) $testSuites = [$suite]; for ($i = 0; isset($testSuites[$i]); ++$i) { foreach ($testSuites[$i]->tests() as $test) { - if ($test instanceof TestSuite) { + if ($test instanceof \PHPUnit_Framework_TestSuite || $test instanceof TestSuite) { if (!class_exists($test->getName(), false)) { $testSuites[] = $test; continue; @@ -174,12 +174,19 @@ public function startTestSuite($suite) } } } elseif (2 === $this->state) { + $suites = [$suite]; $skipped = []; - foreach ($suite->tests() as $test) { - if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase) - || isset($this->wasSkipped[$suiteName]['*']) - || isset($this->wasSkipped[$suiteName][$test->getName()])) { - $skipped[] = $test; + while ($s = array_shift($suites)) { + foreach ($s->tests() as $test) { + if ($test instanceof \PHPUnit_Framework_TestSuite || $test instanceof TestSuite) { + $suites[] = $test; + continue; + } + if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) + && isset($this->wasSkipped[\get_class($test)][$test->getName()]) + ) { + $skipped[] = $test; + } } } $suite->setTests($skipped); @@ -189,21 +196,13 @@ public function startTestSuite($suite) public function addSkippedTest($test, \Exception $e, $time) { if (0 < $this->state) { - if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase) { - $class = \get_class($test); - $method = $test->getName(); - } else { - $class = $test->getName(); - $method = '*'; - } - - $this->isSkipped[$class][$method] = 1; + $this->isSkipped[\get_class($test)][$test->getName()] = 1; } } public function startTest($test) { - if (-2 < $this->state && ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (-2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { // This event is triggered before the test is re-run in isolation if ($this->willBeIsolated($test)) { $this->runsInSeparateProcess = tempnam(sys_get_temp_dir(), 'deprec'); @@ -313,7 +312,7 @@ public function endTest($test, $time) self::$expectedDeprecations = self::$gatheredDeprecations = []; self::$previousErrorHandler = null; } - if (!$this->runsInSeparateProcess && -2 < $this->state && ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (!$this->runsInSeparateProcess && -2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { if (\in_array('time-sensitive', $groups, true)) { ClockMock::withClockMock(false); } diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index f507af9085e44..e0a8d2f381c4a 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -238,7 +238,7 @@ } $prevRoot = getenv('COMPOSER_ROOT_VERSION'); putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); - $q = '\\' === \DIRECTORY_SEPARATOR ? '"' : ''; + $q = '\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 80000 ? '"' : ''; // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS $exit = proc_close(proc_open("$q$COMPOSER install --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index a9772a2b87342..cd7642911ab87 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -11,9 +11,10 @@ namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper; +use ProxyManager\Exception\ExceptionInterface; use ProxyManager\Generator\ClassGenerator; +use ProxyManager\Generator\MethodGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; -use ProxyManager\Version; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; @@ -83,7 +84,7 @@ public function getProxyCode(Definition $definition): string $code = $this->classGenerator->generate($this->generateProxyClass($definition)); $code = preg_replace('/^(class [^ ]++ extends )([^\\\\])/', '$1\\\\$2', $code); - if (version_compare(self::getProxyManagerVersion(), '2.2', '<')) { + if (!method_exists(MethodGenerator::class, 'fromReflectionWithoutBodyAndDocBlock')) { // proxy-manager < 2.2 $code = preg_replace( '/((?:\$(?:this|initializer|instance)->)?(?:publicProperties|initializer|valueHolder))[0-9a-f]++/', '${1}'.$this->getIdentifierSuffix($definition), @@ -91,22 +92,13 @@ public function getProxyCode(Definition $definition): string ); } - if (version_compare(self::getProxyManagerVersion(), '2.5', '<')) { + if (!is_subclass_of(ExceptionInterface::class, 'Throwable')) { // proxy-manager < 2.5 $code = preg_replace('/ \\\\Closure::bind\(function ((?:& )?\(\$instance(?:, \$value)?\))/', ' \Closure::bind(static function \1', $code); } return $code; } - private static function getProxyManagerVersion(): string - { - if (!class_exists(Version::class)) { - return '0.0.1'; - } - - return \defined(Version::class.'::VERSION') ? Version::VERSION : Version::getVersion(); - } - /** * Produces the proxy class name for the given definition. */ diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 974a38a9c3dca..8962a41dd366e 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -147,7 +147,7 @@ private function displayPathsText(SymfonyStyle $io, string $name) $shortnames[] = str_replace('\\', '/', $file->getRelativePathname()); } - list($namespace, $shortname) = $this->parseTemplateName($name); + [$namespace, $shortname] = $this->parseTemplateName($name); $alternatives = $this->findAlternatives($shortname, $shortnames); if (FilesystemLoader::MAIN_NAMESPACE !== $namespace) { $alternatives = array_map(function ($shortname) use ($namespace) { @@ -452,7 +452,7 @@ private function error(SymfonyStyle $io, string $message, array $alternatives = private function findTemplateFiles(string $name): array { - list($namespace, $shortname) = $this->parseTemplateName($name); + [$namespace, $shortname] = $this->parseTemplateName($name); $files = []; foreach ($this->getFilesystemLoaders() as $loader) { diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 0ff70eccd6886..7acf75fb9c17a 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -66,7 +66,7 @@ public function abbrClass(string $class): string public function abbrMethod(string $method): string { if (false !== strpos($method, '::')) { - list($class, $method) = explode('::', $method, 2); + [$class, $method] = explode('::', $method, 2); $result = sprintf('%s::%s()', $this->abbrClass($class), $method); } elseif ('Closure' === $method) { $result = sprintf('%1$s', $method); diff --git a/src/Symfony/Bridge/Twig/Node/TransNode.php b/src/Symfony/Bridge/Twig/Node/TransNode.php index da2b85d1c2861..8a126ba569172 100644 --- a/src/Symfony/Bridge/Twig/Node/TransNode.php +++ b/src/Symfony/Bridge/Twig/Node/TransNode.php @@ -52,7 +52,7 @@ public function compile(Compiler $compiler): void $defaults = $this->getNode('vars'); $vars = null; } - list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); + [$msg, $defaults] = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); $compiler ->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(') diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index dde9bada0961f..c4b5786744fb3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -18,7 +18,7 @@ CHANGELOG 5.1.0 ----- - + * Removed `--no-backup` option from `translation:update` command (broken since `5.0.0`) * Added link to source for controllers registered as named services * Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured) * Added the `framework.router.default_uri` configuration option to configure the default `RequestContext` diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 3eeefb4a94cad..9274d7e70baf6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -79,7 +79,6 @@ protected function configure() new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'), - new InputOption('no-backup', null, InputOption::VALUE_NONE, 'Should backup be disabled'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to update'), new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version', '1.2'), @@ -290,10 +289,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); } - if (true === $input->getOption('no-backup')) { - $this->writer->disableBackup(); - } - // save the files if (true === $input->getOption('force')) { $io->comment('Writing files...'); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 717495d053744..346047062201b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -92,13 +92,12 @@ public function getConfigTreeBuilder() ->arrayNode('trusted_headers') ->fixXmlConfig('trusted_header') ->performNoDeepMerging() - ->defaultValue(['x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix']) + ->defaultValue(['x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto']) ->beforeNormalization()->ifString()->then(function ($v) { return $v ? array_map('trim', explode(',', $v)) : []; })->end() ->enumPrototype() ->values([ 'forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', - 'x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix', ]) ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4c8284c350351..ea5e139e3fe64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -669,7 +669,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']); // Choose storage class based on the DSN - list($class) = explode(':', $config['dsn'], 2); + [$class] = explode(':', $config['dsn'], 2); if ('file' !== $class) { throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); } @@ -965,11 +965,11 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co ->replaceArgument(0, $config['default_uri']); } - if ($this->annotationsConfigEnabled) { + if (\PHP_VERSION_ID >= 80000 || $this->annotationsConfigEnabled) { $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) ->setPublic(false) ->addTag('routing.loader', ['priority' => -10]) - ->addArgument(new Reference('annotation_reader')); + ->addArgument(new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)); $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) ->setPublic(false) @@ -1303,11 +1303,14 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $definition->replaceArgument(0, $config['email_validation_mode']); if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { - throw new \LogicException('"enable_annotations" on the validator cannot be set as Annotations support is disabled.'); + if (!$this->annotationsConfigEnabled && \PHP_VERSION_ID < 80000) { + throw new \LogicException('"enable_annotations" on the validator cannot be set as Doctrine Annotations support is disabled.'); } - $validatorBuilder->addMethodCall('enableAnnotationMapping', [new Reference('annotation_reader')]); + $validatorBuilder->addMethodCall('enableAnnotationMapping', [true]); + if ($this->annotationsConfigEnabled) { + $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]); + } } if (\array_key_exists('static_method', $config) && $config['static_method']) { @@ -1564,13 +1567,13 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $serializerLoaders = []; if (isset($config['enable_annotations']) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { + if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { throw new \LogicException('"enable_annotations" on the serializer cannot be set as Annotations support is disabled.'); } $annotationLoader = new Definition( 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', - [new Reference('annotation_reader')] + [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] ); $annotationLoader->setPublic(false); @@ -2294,13 +2297,6 @@ private function resolveTrustedHeaders(array $headers): int case 'x-forwarded-host': $trustedHeaders |= Request::HEADER_X_FORWARDED_HOST; break; case 'x-forwarded-proto': $trustedHeaders |= Request::HEADER_X_FORWARDED_PROTO; break; case 'x-forwarded-port': $trustedHeaders |= Request::HEADER_X_FORWARDED_PORT; break; - case '!x-forwarded-host': $trustedHeaders &= ~Request::HEADER_X_FORWARDED_HOST; break; - case 'x-forwarded-all': - if (!\in_array('!x-forwarded-prefix', $headers)) { - throw new LogicException('When using "x-forwarded-all" in "framework.trusted_headers", "!x-forwarded-prefix" must be explicitly listed until support for X-Forwarded-Prefix is implemented.'); - } - $trustedHeaders |= Request::HEADER_X_FORWARDED_ALL; - break; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 120ce6c50b42c..c7838ff615360 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -15,6 +15,7 @@ use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory; use Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory; +use Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener; use Symfony\Component\Messenger\EventListener\DispatchPcntlSignalListener; use Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener; use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; @@ -157,6 +158,9 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) + ->set('messenger.failure.add_error_details_stamp_listener', AddErrorDetailsStampListener::class) + ->tag('kernel.event_subscriber') + ->set('messenger.failure.send_failed_message_to_failure_transport_listener', SendFailedMessageToFailureTransportListener::class) ->args([ abstract_arg('failure transport'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php index 92ef379b1b819..8a54680c0f557 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php @@ -26,7 +26,7 @@ public function testWarmUp() $validatorBuilder->addXmlMapping(__DIR__.'/../Fixtures/Validation/Resources/person.xml'); $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/author.yml'); $validatorBuilder->addMethodMapping('loadValidatorMetadata'); - $validatorBuilder->enableAnnotationMapping(); + $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader(); $file = sys_get_temp_dir().'/cache-validator.php'; @unlink($file); @@ -46,7 +46,7 @@ public function testWarmUpWithAnnotations() { $validatorBuilder = new ValidatorBuilder(); $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/categories.yml'); - $validatorBuilder->enableAnnotationMapping(); + $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader(); $file = sys_get_temp_dir().'/cache-validator-with-annotations.php'; @unlink($file); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 6bc6d958b79b4..8dd31fb7d0c25 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -341,9 +341,9 @@ protected static function getBundleDefaultConfig() 'secret' => 's3cr3t', 'trusted_hosts' => [], 'trusted_headers' => [ - 'x-forwarded-all', - '!x-forwarded-host', - '!x-forwarded-prefix', + 'x-forwarded-for', + 'x-forwarded-port', + 'x-forwarded-proto', ], 'csrf_protection' => [ 'enabled' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index fdb1d5a6014a5..b902d3b636a2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -870,7 +870,7 @@ public function testValidation() $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class); - $this->assertCount($annotations ? 7 : 6, $calls); + $this->assertCount($annotations ? 8 : 6, $calls); $this->assertSame('setConstraintValidatorFactory', $calls[0][0]); $this->assertEquals([new Reference('validator.validator_factory')], $calls[0][1]); $this->assertSame('setTranslator', $calls[1][0]); @@ -882,6 +882,7 @@ public function testValidation() $i = 3; if ($annotations) { $this->assertSame('enableAnnotationMapping', $calls[++$i][0]); + $this->assertSame('setDoctrineAnnotationReader', $calls[++$i][0]); } $this->assertSame('addMethodMapping', $calls[++$i][0]); $this->assertSame(['loadValidatorMetadata'], $calls[$i][1]); @@ -923,13 +924,14 @@ public function testValidationAnnotations() $calls = $container->getDefinition('validator.builder')->getMethodCalls(); - $this->assertCount(7, $calls); + $this->assertCount(8, $calls); $this->assertSame('enableAnnotationMapping', $calls[4][0]); - $this->assertEquals([new Reference('annotation_reader')], $calls[4][1]); - $this->assertSame('addMethodMapping', $calls[5][0]); - $this->assertSame(['loadValidatorMetadata'], $calls[5][1]); - $this->assertSame('setMappingCache', $calls[6][0]); - $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[6][1]); + $this->assertSame('setDoctrineAnnotationReader', $calls[5][0]); + $this->assertEquals([new Reference('annotation_reader')], $calls[5][1]); + $this->assertSame('addMethodMapping', $calls[6][0]); + $this->assertSame(['loadValidatorMetadata'], $calls[6][1]); + $this->assertSame('setMappingCache', $calls[7][0]); + $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[7][1]); // no cache this time } @@ -944,14 +946,15 @@ public function testValidationPaths() $calls = $container->getDefinition('validator.builder')->getMethodCalls(); - $this->assertCount(8, $calls); + $this->assertCount(9, $calls); $this->assertSame('addXmlMappings', $calls[3][0]); $this->assertSame('addYamlMappings', $calls[4][0]); $this->assertSame('enableAnnotationMapping', $calls[5][0]); - $this->assertSame('addMethodMapping', $calls[6][0]); - $this->assertSame(['loadValidatorMetadata'], $calls[6][1]); - $this->assertSame('setMappingCache', $calls[7][0]); - $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[7][1]); + $this->assertSame('setDoctrineAnnotationReader', $calls[6][0]); + $this->assertSame('addMethodMapping', $calls[7][0]); + $this->assertSame(['loadValidatorMetadata'], $calls[7][1]); + $this->assertSame('setMappingCache', $calls[8][0]); + $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[8][1]); $xmlMappings = $calls[3][1][0]; $this->assertCount(3, $xmlMappings); @@ -1004,11 +1007,12 @@ public function testValidationNoStaticMethod() $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class); - $this->assertCount($annotations ? 6 : 5, $calls); + $this->assertCount($annotations ? 7 : 5, $calls); $this->assertSame('addXmlMappings', $calls[3][0]); $i = 3; if ($annotations) { $this->assertSame('enableAnnotationMapping', $calls[++$i][0]); + $this->assertSame('setDoctrineAnnotationReader', $calls[++$i][0]); } $this->assertSame('setMappingCache', $calls[++$i][0]); $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[$i][1]); @@ -1232,7 +1236,7 @@ public function testSerializerMapping() $projectDir = $container->getParameter('kernel.project_dir'); $configDir = __DIR__.'/Fixtures/TestBundle/Resources/config'; $expectedLoaders = [ - new Definition(AnnotationLoader::class, [new Reference('annotation_reader')]), + new Definition(AnnotationLoader::class, [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)]), new Definition(XmlFileLoader::class, [$configDir.'/serialization.xml']), new Definition(YamlFileLoader::class, [$configDir.'/serialization.yml']), new Definition(YamlFileLoader::class, [$projectDir.'/config/serializer/foo.yml']), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php index 0d9464d7dfab4..168cd2d45a52a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php @@ -71,7 +71,7 @@ public function showFlashAction(Request $request) $session = $request->getSession(); if ($session->getFlashBag()->has('notice')) { - list($output) = $session->getFlashBag()->get('notice'); + [$output] = $session->getFlashBag()->get('notice'); } else { $output = 'No flash was set.'; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 8ae38fd392168..08c920fd951c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -155,7 +155,7 @@ protected function initialize() $this->addResourceFiles(); } foreach ($this->resources as $key => $params) { - list($format, $resource, $locale, $domain) = $params; + [$format, $resource, $locale, $domain] = $params; parent::addResource($format, $resource, $locale, $domain); } $this->resources = []; diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index b6dd28d614b39..5e3b3c102ef37 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -29,7 +29,7 @@ "symfony/polyfill-php80": "^1.15", "symfony/filesystem": "^4.4|^5.0", "symfony/finder": "^4.4|^5.0", - "symfony/routing": "^5.1" + "symfony/routing": "^5.2" }, "require-dev": { "doctrine/annotations": "~1.7", diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php index 94d5a184727e8..1cd90fe70af1a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php @@ -45,8 +45,12 @@ public function process(ContainerBuilder $container) $container->setAlias('security.token_storage', 'security.untracked_token_storage')->setPublic(true); $container->getDefinition('security.untracked_token_storage')->addTag('kernel.reset', ['method' => 'reset']); } elseif ($container->hasDefinition('security.context_listener')) { - $container->getDefinition('security.context_listener') - ->setArgument(6, [new Reference('security.token_storage'), 'enableUsageTracking']); + $tokenStorageClass = $container->getParameterBag()->resolveValue($container->findDefinition('security.token_storage')->getClass()); + + if (method_exists($tokenStorageClass, 'enableUsageTracking')) { + $container->getDefinition('security.context_listener') + ->setArgument(6, [new Reference('security.token_storage'), 'enableUsageTracking']); + } } } } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 6e3d806cd5551..4d0232d9217b2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -276,7 +276,7 @@ private function createFirewalls(array $config, ContainerBuilder $container) $configId = 'security.firewall.map.config.'.$name; - list($matcher, $listeners, $exceptionListener, $logoutListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId); + [$matcher, $listeners, $exceptionListener, $logoutListener] = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId); $contextId = 'security.firewall.map.context.'.$name; $isLazy = !$firewall['stateless'] && (!empty($firewall['anonymous']['lazy']) || $firewall['lazy']); @@ -460,7 +460,7 @@ private function createFirewall(ContainerBuilder $container, string $id, array $ // Authentication listeners $firewallAuthenticationProviders = []; - list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); + [$authListeners, $defaultEntryPoint] = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); if (!$this->authenticatorManagerEnabled) { $authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders); @@ -578,7 +578,7 @@ private function createAuthenticationListeners(ContainerBuilder $container, stri $entryPoints[$key] = $entryPoint; } } else { - list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); + [$provider, $listenerId, $defaultEntryPoint] = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); $listeners[] = new Reference($listenerId); $authenticationProviders[] = $provider; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php new file mode 100644 index 0000000000000..afdbf9afaf60f --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterTokenUsageTrackingPass; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage; +use Symfony\Component\Security\Http\Firewall\ContextListener; + +class RegisterTokenUsageTrackingPassTest extends TestCase +{ + public function testTokenStorageIsUntrackedIfSessionIsMissing() + { + $container = new ContainerBuilder(); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $this->assertTrue($container->hasAlias('security.token_storage')); + $this->assertEquals(new Alias('security.untracked_token_storage', true), $container->getAlias('security.token_storage')); + } + + public function testContextListenerIsNotModifiedIfTokenStorageDoesNotSupportUsageTracking() + { + $container = new ContainerBuilder(); + + $container->setParameter('security.token_storage.class', TokenStorage::class); + $container->register('session', Session::class); + $container->register('security.context_listener', ContextListener::class) + ->setArguments([ + new Reference('security.untracked_token_storage'), + [], + 'main', + new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('event_dispatcher', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('security.authentication.trust_resolver'), + ]); + $container->register('security.token_storage', '%security.token_storage.class%'); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $this->assertCount(6, $container->getDefinition('security.context_listener')->getArguments()); + } + + public function testContextListenerEnablesUsageTrackingIfSupportedByTokenStorage() + { + $container = new ContainerBuilder(); + + $container->setParameter('security.token_storage.class', UsageTrackingTokenStorage::class); + $container->register('session', Session::class); + $container->register('security.context_listener', ContextListener::class) + ->setArguments([ + new Reference('security.untracked_token_storage'), + [], + 'main', + new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('event_dispatcher', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('security.authentication.trust_resolver'), + ]); + $container->register('security.token_storage', '%security.token_storage.class%'); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $contextListener = $container->getDefinition('security.context_listener'); + + $this->assertCount(7, $container->getDefinition('security.context_listener')->getArguments()); + $this->assertEquals([new Reference('security.token_storage'), 'enableUsageTracking'], $contextListener->getArgument(6)); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index a7f56e9958785..f9d8094fbccd4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -235,7 +235,7 @@ public function testAccess() } $matcherIds = []; - foreach ($rules as list($matcherId, $attributes, $channel)) { + foreach ($rules as [$matcherId, $attributes, $channel]) { $requestMatcher = $container->getDefinition($matcherId); $this->assertArrayNotHasKey($matcherId, $matcherIds); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php index 364a9249224cb..4b1ddcf09c3e6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php @@ -19,7 +19,7 @@ class AbstractFactoryTest extends TestCase { public function testCreate() { - list($container, $authProviderId, $listenerId, $entryPointId) = $this->callFactory('foo', [ + [$container, $authProviderId, $listenerId, $entryPointId] = $this->callFactory('foo', [ 'use_forward' => true, 'failure_path' => '/foo', 'success_handler' => 'custom_success_handler', @@ -61,7 +61,7 @@ public function testDefaultFailureHandler($serviceId, $defaultHandlerInjection) $options['failure_handler'] = $serviceId; } - list($container) = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); + [$container] = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); $definition = $container->getDefinition('abstract_listener.foo'); $arguments = $definition->getArguments(); @@ -99,7 +99,7 @@ public function testDefaultSuccessHandler($serviceId, $defaultHandlerInjection) $options['success_handler'] = $serviceId; } - list($container) = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); + [$container] = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); $definition = $container->getDefinition('abstract_listener.foo'); $arguments = $definition->getArguments(); @@ -150,7 +150,7 @@ protected function callFactory($id, $config, $userProviderId, $defaultEntryPoint $container->register('custom_success_handler'); $container->register('custom_failure_handler'); - list($authProviderId, $listenerId, $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); + [$authProviderId, $listenerId, $entryPointId] = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); return [$container, $authProviderId, $listenerId, $entryPointId]; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php index 8215aaf9c90fb..7d6f5f6591278 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php @@ -104,7 +104,7 @@ public function testBasicCreate() 'authenticators' => ['authenticator123'], 'entry_point' => null, ]; - list($container, $entryPointId) = $this->executeCreate($config, null); + [$container, $entryPointId] = $this->executeCreate($config, null); $this->assertEquals('authenticator123', $entryPointId); $providerDefinition = $container->getDefinition('security.authentication.provider.guard.my_firewall'); @@ -127,7 +127,7 @@ public function testExistingDefaultEntryPointUsed() 'authenticators' => ['authenticator123'], 'entry_point' => null, ]; - list(, $entryPointId) = $this->executeCreate($config, 'some_default_entry_point'); + [, $entryPointId] = $this->executeCreate($config, 'some_default_entry_point'); $this->assertEquals('some_default_entry_point', $entryPointId); } @@ -160,7 +160,7 @@ public function testCreateWithEntryPoint() 'authenticators' => ['authenticator123', 'authenticatorABC'], 'entry_point' => 'authenticatorABC', ]; - list(, $entryPointId) = $this->executeCreate($config, null); + [, $entryPointId] = $this->executeCreate($config, null); $this->assertEquals('authenticatorABC', $entryPointId); } @@ -196,7 +196,7 @@ private function executeCreate(array $config, $defaultEntryPointId) $userProviderId = 'my_user_provider'; $factory = new GuardAuthenticationFactory(); - list(, , $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); + [, , $entryPointId] = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); return [$container, $entryPointId]; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php index f49cfa84c07e1..394e59cc4263e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php @@ -110,6 +110,7 @@ public function testFormLoginRedirectsToProtectedResourceAfterLogin(array $optio /** * @dataProvider provideInvalidCredentials + * @group time-sensitive */ public function testLoginThrottling($username, $password) { diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index fa590a54e908d..7e49cd4fde9b5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -23,7 +23,7 @@ class FirewallMapTest extends TestCase { - const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; + private const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; public function testGetListenersWithEmptyMap() { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index 30dd95e5c75eb..bb9daab006fce 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -72,7 +72,7 @@ public function getNames(Profile $profile) continue; } - list($name, $template) = $arguments; + [$name, $template] = $arguments; if (!$this->profiler->has($name) || !$profile->hasCollector($name)) { continue; diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index 79ca7943109ff..c24661de76ab5 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -133,7 +133,7 @@ public static function fromString(string $cookie, string $url = null) throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0])); } - list($name, $value) = explode('=', array_shift($parts), 2); + [$name, $value] = explode('=', array_shift($parts), 2); $values = [ 'name' => trim($name), diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index efca364ba7ce6..aef2a9a7deb57 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -74,7 +74,7 @@ static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifeti $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) { - $item->expiresAt(\DateTime::createFromFormat('U.u', $item->metadata[CacheItem::METADATA_EXPIRY])); + $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); } elseif (0 < $defaultLifetime) { $item->expiresAfter($defaultLifetime); } diff --git a/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php b/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php index 0fd272700198c..a0e8f4027181c 100644 --- a/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php @@ -134,7 +134,7 @@ private static function getOptions(string $options): array $optionsInArray = explode('&', $options); foreach ($optionsInArray as $option) { - list($key, $value) = explode('=', $option); + [$key, $value] = explode('=', $option); if (\in_array($key, static::VALID_DSN_OPTIONS, true)) { $results[$key] = $value; diff --git a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php index 038892eabc3ba..53ead840c4eee 100644 --- a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php @@ -123,7 +123,7 @@ public static function createConnection($servers, array $options = []) } $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[2])) { - list($username, $password) = explode(':', $m[2], 2) + [1 => null]; + [$username, $password] = explode(':', $m[2], 2) + [1 => null]; } return 'file:'.($m[1] ?? ''); diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 0abf787f44ddb..a8f8f3038a652 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -401,7 +401,7 @@ private function initialize() if (2 !== \count($values) || !isset($values[0], $values[1])) { $this->keys = $this->values = []; } else { - list($this->keys, $this->values) = $values; + [$this->keys, $this->values] = $values; } } diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index 9527fa63ffae9..faba3d8822a75 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -88,7 +88,7 @@ static function (CacheItemInterface $innerItem, array $item) { $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; } $innerItem->set($item["\0*\0value"]); - $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', 0 === $item["\0*\0expiry"] ? \PHP_INT_MAX : $item["\0*\0expiry"])) : null); + $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', 0 === $item["\0*\0expiry"] ? \PHP_INT_MAX : $item["\0*\0expiry"])) : null); }, null, CacheItem::class diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index 57c355eaa43a6..d7fe3ebc60b9e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -118,9 +118,9 @@ public function testGetMetadata() $metadata = $item->getMetadata(); $this->assertArrayHasKey(CacheItem::METADATA_CTIME, $metadata); - $this->assertEqualsWithDelta(1000, $metadata[CacheItem::METADATA_CTIME], 6); + $this->assertEqualsWithDelta(999, $metadata[CacheItem::METADATA_CTIME], 10); $this->assertArrayHasKey(CacheItem::METADATA_EXPIRY, $metadata); - $this->assertEqualsWithDelta(9.5 + time(), $metadata[CacheItem::METADATA_EXPIRY], 0.6); + $this->assertEqualsWithDelta(9 + time(), $metadata[CacheItem::METADATA_EXPIRY], 1); } public function testDefaultLifeTime() diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php index f1ee0d6c71dff..bf1ca393cecc7 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -156,7 +156,7 @@ public function save(CacheItemInterface $item): bool $this->keys[$key] = $id = \count($this->values); $this->data[$key] = $this->values[$id] = $item->get(); $this->warmUp($this->data); - list($this->keys, $this->values) = eval(substr(file_get_contents($this->file), 6)); + [$this->keys, $this->values] = eval(substr(file_get_contents($this->file), 6)); }, $this, PhpArrayAdapter::class))(); return true; diff --git a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php index de3dbfc7a8b3c..86c1aac489dd9 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php @@ -14,6 +14,7 @@ use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerAwareTrait; use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; /** * @author Nicolas Grekas
diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
index 468656e333fa3..34b8aa73a5fc1 100644
--- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
+++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
@@ -111,7 +111,7 @@ public static function createConnection($servers, array $options = [])
}
$params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) {
if (!empty($m[2])) {
- list($username, $password) = explode(':', $m[2], 2) + [1 => null];
+ [$username, $password] = explode(':', $m[2], 2) + [1 => null];
}
return 'file:'.($m[1] ?? '');
diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php
index 86e15b07b82de..317879aa494e2 100644
--- a/src/Symfony/Component/Cache/Traits/RedisTrait.php
+++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php
@@ -486,7 +486,7 @@ private function pipeline(\Closure $generator, $redis = null): \Generator
foreach ($connections as $h => $c) {
$connections[$h] = $c[0]->exec();
}
- foreach ($results as $k => list($h, $c)) {
+ foreach ($results as $k => [$h, $c]) {
$results[$k] = $connections[$h][$c];
}
} else {
diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php
index 1107fff232294..66291014ec92b 100644
--- a/src/Symfony/Component/Config/Definition/ArrayNode.php
+++ b/src/Symfony/Component/Config/Definition/ArrayNode.php
@@ -339,7 +339,7 @@ protected function normalizeValue($value)
*/
protected function remapXml(array $value)
{
- foreach ($this->xmlRemappings as list($singular, $plural)) {
+ foreach ($this->xmlRemappings as [$singular, $plural]) {
if (!isset($value[$singular])) {
continue;
}
diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php
index f686c53b5718f..ef60eff374dba 100644
--- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php
+++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php
@@ -53,7 +53,7 @@ private function writeNode(NodeInterface $node, int $depth = 0, bool $root = fal
});
if (\count($remapping)) {
- list($singular) = current($remapping);
+ [$singular] = current($remapping);
$rootName = $singular;
}
}
diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php
index 60896408a6059..91d1688d06c23 100644
--- a/src/Symfony/Component/Console/Helper/Table.php
+++ b/src/Symfony/Component/Console/Helper/Table.php
@@ -418,13 +418,13 @@ private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $tit
$crossings = $this->style->getCrossingChars();
if (self::SEPARATOR_MID === $type) {
- list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
} elseif (self::SEPARATOR_TOP === $type) {
- list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
} elseif (self::SEPARATOR_TOP_BOTTOM === $type) {
- list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
} else {
- list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
}
$markup = $leftChar;
diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php
index c93bda5a9bf0a..2171bdc968519 100644
--- a/src/Symfony/Component/Console/Input/ArgvInput.php
+++ b/src/Symfony/Component/Console/Input/ArgvInput.php
@@ -165,11 +165,25 @@ private function parseArgument(string $token)
// unexpected argument
} else {
$all = $this->definition->getArguments();
+ $symfonyCommandName = null;
+ if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) {
+ $symfonyCommandName = $this->arguments['command'] ?? null;
+ unset($all[$key]);
+ }
+
if (\count($all)) {
- throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
+ if ($symfonyCommandName) {
+ $message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all)));
+ } else {
+ $message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)));
+ }
+ } elseif ($symfonyCommandName) {
+ $message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token);
+ } else {
+ $message = sprintf('No arguments expected, got "%s".', $token);
}
- throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
+ throw new RuntimeException($message);
}
}
diff --git a/src/Symfony/Component/Console/Output/ConsoleOutput.php b/src/Symfony/Component/Console/Output/ConsoleOutput.php
index 96664f1508abb..2cda213a04b09 100644
--- a/src/Symfony/Component/Console/Output/ConsoleOutput.php
+++ b/src/Symfony/Component/Console/Output/ConsoleOutput.php
@@ -41,6 +41,13 @@ public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decor
{
parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
+ if (null === $formatter) {
+ // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
+ $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);
+
+ return;
+ }
+
$actualDecorated = $this->isDecorated();
$this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
diff --git a/src/Symfony/Component/Console/Tests/ColorTest.php b/src/Symfony/Component/Console/Tests/ColorTest.php
index 7fe008cae1c1d..571963cfce788 100644
--- a/src/Symfony/Component/Console/Tests/ColorTest.php
+++ b/src/Symfony/Component/Console/Tests/ColorTest.php
@@ -40,4 +40,20 @@ public function testTrueColors()
$color = new Color('#ffffff', '#000000');
$this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' '));
}
+
+ public function testDegradedTrueColors()
+ {
+ $colorterm = getenv('COLORTERM');
+ putenv('COLORTERM=');
+
+ try {
+ $color = new Color('#f00', '#ff0');
+ $this->assertSame("\033[31;43m \033[39;49m", $color->apply(' '));
+
+ $color = new Color('#c0392b', '#f1c40f');
+ $this->assertSame("\033[31;43m \033[39;49m", $color->apply(' '));
+ } finally {
+ putenv('COLORTERM='.$colorterm);
+ }
+ }
}
diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php
index 51cc6e5175396..57a561091e77a 100644
--- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php
+++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php
@@ -247,6 +247,16 @@ public function provideInvalidInput()
new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_NONE)]),
'The "-Щ" option does not exist.',
],
+ [
+ ['cli.php', 'acme:foo', 'bar'],
+ new InputDefinition([new InputArgument('command', InputArgument::REQUIRED)]),
+ 'No arguments expected for "acme:foo" command, got "bar"',
+ ],
+ [
+ ['cli.php', 'acme:foo', 'bar'],
+ new InputDefinition([new InputArgument('name', InputArgument::REQUIRED)]),
+ 'Too many arguments, expected arguments "name".',
+ ],
];
}
diff --git a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php
index db39a02b8a616..33a5371d6e4b9 100644
--- a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php
+++ b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php
@@ -18,11 +18,19 @@
class ConsoleOutputTest extends TestCase
{
- public function testConstructor()
+ public function testConstructorWithoutFormatter()
{
$output = new ConsoleOutput(Output::VERBOSITY_QUIET, true);
$this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
- $this->assertSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), '__construct() takes a formatter or null as the third argument');
+ $this->assertNotSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), 'ErrorOutput should use it own formatter');
+ }
+
+ public function testConstructorWithFormatter()
+ {
+ $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true, $formatter = new OutputFormatter());
+ $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
+ $this->assertSame($formatter, $output->getFormatter());
+ $this->assertSame($formatter, $output->getErrorOutput()->getFormatter(), 'Output and ErrorOutput should use the same provided formatter');
}
public function testSetFormatter()
@@ -31,6 +39,7 @@ public function testSetFormatter()
$outputFormatter = new OutputFormatter();
$output->setFormatter($outputFormatter);
$this->assertSame($outputFormatter, $output->getFormatter());
+ $this->assertSame($outputFormatter, $output->getErrorOutput()->getFormatter());
}
public function testSetVerbosity()
diff --git a/src/Symfony/Component/CssSelector/Parser/Parser.php b/src/Symfony/Component/CssSelector/Parser/Parser.php
index e8a46c062ce7f..a03f1527f144b 100644
--- a/src/Symfony/Component/CssSelector/Parser/Parser.php
+++ b/src/Symfony/Component/CssSelector/Parser/Parser.php
@@ -113,7 +113,7 @@ private function parseSelectorList(TokenStream $stream): array
private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
{
- list($result, $pseudoElement) = $this->parseSimpleSelector($stream);
+ [$result, $pseudoElement] = $this->parseSimpleSelector($stream);
while (true) {
$stream->skipWhitespace();
@@ -134,7 +134,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
$combinator = ' ';
}
- list($nextSelector, $pseudoElement) = $this->parseSimpleSelector($stream);
+ [$nextSelector, $pseudoElement] = $this->parseSimpleSelector($stream);
$result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector);
}
@@ -209,7 +209,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
throw SyntaxErrorException::nestedNot();
}
- list($argument, $argumentPseudoElement) = $this->parseSimpleSelector($stream, true);
+ [$argument, $argumentPseudoElement] = $this->parseSimpleSelector($stream, true);
$next = $stream->getNext();
if (null !== $argumentPseudoElement) {
diff --git a/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php b/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php
index 2b79aaafc9fcb..d3f7222a4d0ab 100644
--- a/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php
+++ b/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php
@@ -51,7 +51,7 @@ public function getFunctionTranslators(): array
public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr
{
try {
- list($a, $b) = Parser::parseSeries($function->getArguments());
+ [$a, $b] = Parser::parseSeries($function->getArguments());
} catch (SyntaxErrorException $e) {
throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e);
}
diff --git a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php
index 60059267beea4..f3535d68b0fe5 100644
--- a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php
+++ b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php
@@ -54,9 +54,9 @@ public function getValues(): array
public function setValues(array $values)
{
if (5 === \count($values)) {
- list($this->value, $this->identifier, $this->used, $this->type, $this->file) = $values;
+ [$this->value, $this->identifier, $this->used, $this->type, $this->file] = $values;
} else {
- list($this->value, $this->identifier, $this->used) = $values;
+ [$this->value, $this->identifier, $this->used] = $values;
}
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
index 76c954a987245..85478da5e9b16 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
@@ -127,7 +127,7 @@ protected function getConstructor(Definition $definition, bool $required)
}
if ($factory) {
- list($class, $method) = $factory;
+ [$class, $method] = $factory;
if ($class instanceof Reference) {
$class = $this->container->findDefinition((string) $class)->getClass();
} elseif ($class instanceof Definition) {
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
index ba10e92b1e7c3..d201b58b987aa 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
@@ -126,7 +126,7 @@ private function doProcessValue($value, bool $isRoot = false)
$this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot);
if ($constructor) {
- list(, $arguments) = array_shift($this->methodCalls);
+ [, $arguments] = array_shift($this->methodCalls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
@@ -152,7 +152,7 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot):
foreach ($this->methodCalls as $i => $call) {
$this->decoratedMethodIndex = $i;
- list($method, $arguments) = $call;
+ [$method, $arguments] = $call;
if ($method instanceof \ReflectionFunctionAbstract) {
$reflectionMethod = $method;
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php
index fc1027677d41c..5c255cfb60761 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php
@@ -38,7 +38,7 @@ protected function processValue($value, bool $isRoot = false)
$alreadyCalledMethods = [];
$withers = [];
- foreach ($value->getMethodCalls() as list($method)) {
+ foreach ($value->getMethodCalls() as [$method]) {
$alreadyCalledMethods[strtolower($method)] = true;
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php
index b15506d20b697..9313d7a6e616d 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php
@@ -46,9 +46,9 @@ public function process(ContainerBuilder $container)
}
$decoratingDefinitions = [];
- foreach ($definitions as list($id, $definition)) {
+ foreach ($definitions as [$id, $definition]) {
$decoratedService = $definition->getDecoratedService();
- list($inner, $renamedId) = $decoratedService;
+ [$inner, $renamedId] = $decoratedService;
$invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
$definition->setDecoratedService(null);
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
index b86c1b786477b..61e99d73becf9 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
@@ -41,11 +41,11 @@ public function process(ContainerBuilder $container)
try {
parent::process($container);
- foreach ($this->unusedBindings as list($key, $serviceId, $bindingType, $file)) {
+ foreach ($this->unusedBindings as [$key, $serviceId, $bindingType, $file]) {
$argumentType = $argumentName = $message = null;
if (false !== strpos($key, ' ')) {
- list($argumentType, $argumentName) = explode(' ', $key, 2);
+ [$argumentType, $argumentName] = explode(' ', $key, 2);
} elseif ('$' === $key[0]) {
$argumentName = $key;
} else {
@@ -117,7 +117,7 @@ protected function processValue($value, bool $isRoot = false)
$bindingNames = [];
foreach ($bindings as $key => $binding) {
- list($bindingValue, $bindingId, $used, $bindingType, $file) = $binding->getValues();
+ [$bindingValue, $bindingId, $used, $bindingType, $file] = $binding->getValues();
if ($used) {
$this->usedBindings[$bindingId] = true;
unset($this->unusedBindings[$bindingId]);
@@ -156,7 +156,7 @@ protected function processValue($value, bool $isRoot = false)
}
foreach ($calls as $i => $call) {
- list($method, $arguments) = $call;
+ [$method, $arguments] = $call;
if ($method instanceof \ReflectionFunctionAbstract) {
$reflectionMethod = $method;
@@ -210,7 +210,7 @@ protected function processValue($value, bool $isRoot = false)
}
if ($constructor) {
- list(, $arguments) = array_pop($calls);
+ [, $arguments] = array_pop($calls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
@@ -229,7 +229,7 @@ protected function processValue($value, bool $isRoot = false)
*/
private function getBindingValue(BoundArgument $binding)
{
- list($bindingValue, $bindingId) = $binding->getValues();
+ [$bindingValue, $bindingId] = $binding->getValues();
$this->usedBindings[$bindingId] = true;
unset($this->unusedBindings[$bindingId]);
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php
index fd3c5e4d1d9f1..c1c5748e8d601 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php
@@ -41,7 +41,7 @@ protected function processValue($value, bool $isRoot = false)
$calls[] = ['__construct', $value->getArguments()];
foreach ($calls as $i => $call) {
- list($method, $arguments) = $call;
+ [$method, $arguments] = $call;
$parameters = null;
$resolvedArguments = [];
@@ -107,7 +107,7 @@ protected function processValue($value, bool $isRoot = false)
}
}
- list(, $arguments) = array_pop($calls);
+ [, $arguments] = array_pop($calls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index ec82969d1bb4c..5267f6fbb9ba9 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -1167,7 +1167,7 @@ private function doResolveServices($value, array &$inlineServices = [], bool $is
return $this->resolveServices($reference);
};
} elseif ($value instanceof IteratorArgument) {
- $value = new RewindableGenerator(function () use ($value) {
+ $value = new RewindableGenerator(function () use ($value, &$inlineServices) {
foreach ($value->getValues() as $k => $v) {
foreach (self::getServiceConditionals($v) as $s) {
if (!$this->has($s)) {
@@ -1175,12 +1175,12 @@ private function doResolveServices($value, array &$inlineServices = [], bool $is
}
}
foreach (self::getInitializedConditionals($v) as $s) {
- if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
+ if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
continue 2;
}
}
- yield $k => $this->resolveServices($v);
+ yield $k => $this->doResolveServices($v, $inlineServices);
}
}, function () use ($value): int {
$count = 0;
@@ -1455,7 +1455,7 @@ public function removeBindings(string $id)
{
if ($this->hasDefinition($id)) {
foreach ($this->getDefinition($id)->getBindings() as $key => $binding) {
- list(, $bindingId) = $binding->getValues();
+ [, $bindingId] = $binding->getValues();
$this->removedBindingIds[(int) $bindingId] = true;
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 93b303ea2bf20..7b0ea433033f6 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -185,25 +185,7 @@ public function dump(array $options = [])
}
}
- (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
- $checkedNodes = [];
- $this->circularReferences = [];
- $this->singleUsePrivateIds = [];
- foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
- if (!$node->getValue() instanceof Definition) {
- continue;
- }
- if (!isset($checkedNodes[$id])) {
- $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes);
- }
- if ($this->isSingleUsePrivateNode($node)) {
- $this->singleUsePrivateIds[$id] = $id;
- }
- }
- $this->container->getCompiler()->getServiceReferenceGraph()->clear();
- $checkedNodes = [];
- $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences);
-
+ $this->analyzeReferences();
$this->docStar = $options['debug'] ? '*' : '';
if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) {
@@ -429,61 +411,65 @@ private function getProxyDumper(): ProxyDumper
return $this->proxyDumper;
}
- /**
- * @param ServiceReferenceGraphEdge[] $edges
- */
- private function analyzeCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$currentPath = [], bool $byConstructor = true)
+ private function analyzeReferences()
{
- $checkedNodes[$sourceId] = true;
- $currentPath[$sourceId] = $byConstructor;
-
- foreach ($edges as $edge) {
- $node = $edge->getDestNode();
- $id = $node->getId();
-
- if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) {
- // no-op
- } elseif (isset($currentPath[$id])) {
- $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
- } elseif (!isset($checkedNodes[$id])) {
- $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor());
- } elseif (isset($this->circularReferences[$id])) {
- $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
+ (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
+ $checkedNodes = [];
+ $this->circularReferences = [];
+ $this->singleUsePrivateIds = [];
+ foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
+ if (!$node->getValue() instanceof Definition) {
+ continue;
}
- }
- unset($currentPath[$sourceId]);
- }
-
- private function connectCircularReferences(string $sourceId, array &$currentPath, bool $byConstructor, array &$subPath = [])
- {
- $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor;
- foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) {
- if (isset($currentPath[$id])) {
- $this->addCircularReferences($id, $currentPath, $byConstructor);
- } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) {
- $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath);
+ if ($this->isSingleUsePrivateNode($node)) {
+ $this->singleUsePrivateIds[$id] = $id;
}
+
+ $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes);
}
- unset($currentPath[$sourceId], $subPath[$sourceId]);
+
+ $this->container->getCompiler()->getServiceReferenceGraph()->clear();
+ $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences);
}
- private function addCircularReferences(string $id, array $currentPath, bool $byConstructor)
+ private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array $path = [], bool $byConstructor = true): void
{
- $currentPath[$id] = $byConstructor;
- $circularRefs = [];
+ $path[$sourceId] = $byConstructor;
+ $checkedNodes[$sourceId] = true;
+ foreach ($edges as $edge) {
+ $node = $edge->getDestNode();
+ $id = $node->getId();
- foreach (array_reverse($currentPath) as $parentId => $v) {
- $byConstructor = $byConstructor && $v;
- $circularRefs[] = $parentId;
+ if (!($definition = $node->getValue()) instanceof Definition || $sourceId === $id || ($edge->isLazy() && ($this->proxyDumper ?? $this->getProxyDumper())->isProxyCandidate($definition)) || $edge->isWeak()) {
+ continue;
+ }
- if ($parentId === $id) {
- break;
+ if (isset($path[$id])) {
+ $loop = null;
+ $loopByConstructor = $edge->isReferencedByConstructor();
+ foreach ($path as $k => $pathByConstructor) {
+ if (null !== $loop) {
+ $loop[] = $k;
+ $loopByConstructor = $loopByConstructor && $pathByConstructor;
+ } elseif ($k === $id) {
+ $loop = [];
+ }
+ }
+ $this->addCircularReferences($id, $loop, $loopByConstructor);
+ } elseif (!isset($checkedNodes[$id])) {
+ $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $path, $edge->isReferencedByConstructor());
}
}
+ unset($path[$sourceId]);
+ }
- $currentId = $id;
- foreach ($circularRefs as $parentId) {
+ private function addCircularReferences(string $sourceId, array $currentPath, bool $byConstructor)
+ {
+ $currentId = $sourceId;
+ $currentPath = array_reverse($currentPath);
+ $currentPath[] = $currentId;
+ foreach ($currentPath as $parentId) {
if (empty($this->circularReferences[$parentId][$currentId])) {
$this->circularReferences[$parentId][$currentId] = $byConstructor;
}
@@ -597,7 +583,7 @@ private function addServiceInclude(string $cId, Definition $definition): string
}
}
- foreach ($this->serviceCalls as $id => list($callCount, $behavior)) {
+ foreach ($this->serviceCalls as $id => [$callCount, $behavior]) {
if ('service_container' !== $id && $id !== $cId
&& ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
&& $this->container->has($id)
@@ -950,7 +936,7 @@ private function addInlineReference(string $id, Definition $definition, string $
$targetId = (string) $this->container->getAlias($targetId);
}
- list($callCount, $behavior) = $this->serviceCalls[$targetId];
+ [$callCount, $behavior] = $this->serviceCalls[$targetId];
if ($id === $targetId) {
return $this->addInlineService($id, $definition, $definition);
@@ -1006,7 +992,7 @@ private function addInlineService(string $id, Definition $definition, Definition
$code = '';
if ($isSimpleInstance = $isRootInstance = null === $inlineDef) {
- foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) {
+ foreach ($this->serviceCalls as $targetId => [$callCount, $behavior, $byConstructor]) {
if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) {
$code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor);
}
@@ -1076,7 +1062,7 @@ private function addServices(array &$services = null): string
}
foreach ($definitions as $id => $definition) {
- if (!(list($file, $code) = $services[$id]) || null !== $file) {
+ if (!([$file, $code] = $services[$id]) || null !== $file) {
continue;
}
if ($definition->isPublic()) {
@@ -1094,7 +1080,7 @@ private function generateServiceFiles(array $services): iterable
$definitions = $this->container->getDefinitions();
ksort($definitions);
foreach ($definitions as $id => $definition) {
- if ((list($file, $code) = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) {
+ if (([$file, $code] = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) {
yield $file => [$code, $definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()];
}
}
@@ -1796,7 +1782,7 @@ private function dumpValue($value, bool $interpolate = true): string
return sprintf('new \%s($this->getService, [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n " : '', $serviceTypes, $serviceTypes ? "\n " : '');
}
} finally {
- list($this->definitionVariables, $this->referenceVariables) = $scope;
+ [$this->definitionVariables, $this->referenceVariables] = $scope;
}
} elseif ($value instanceof Definition) {
if ($value->hasErrors() && $e = $value->getErrors()) {
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
index f21571faf6f5e..408ed3c40dc61 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
@@ -118,7 +118,7 @@ private function addService(Definition $definition, ?string $id, \DOMElement $pa
$service->setAttribute('lazy', 'true');
}
if (null !== $decoratedService = $definition->getDecoratedService()) {
- list($decorated, $renamedId, $priority) = $decoratedService;
+ [$decorated, $renamedId, $priority] = $decoratedService;
$service->setAttribute('decorates', $decorated);
$decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
index fb9751f89bb10..61b4c5fa6ce7f 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
@@ -138,7 +138,7 @@ private function addService(string $id, Definition $definition): string
}
if (null !== $decoratedService = $definition->getDecoratedService()) {
- list($decorated, $renamedId, $priority) = $decoratedService;
+ [$decorated, $renamedId, $priority] = $decoratedService;
$code .= sprintf(" decorates: %s\n", $decorated);
if (null !== $renamedId) {
$code .= sprintf(" decoration_inner_name: %s\n", $renamedId);
diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
index 33b5a009f7b4c..e4620912cb874 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
@@ -430,7 +430,7 @@ private function processAnonymousServices(\DOMDocument $xml, string $file)
// resolve definitions
uksort($definitions, 'strnatcmp');
- foreach (array_reverse($definitions) as $id => list($domElement, $file)) {
+ foreach (array_reverse($definitions) as $id => [$domElement, $file]) {
if (null !== $definition = $this->parseDefinition($domElement, $file, new Definition())) {
$this->setDefinition($id, $definition);
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php
index 2504ff112cf86..c586e72c2acbc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php
@@ -67,7 +67,7 @@ public function testAliasParametersShouldBeResolved()
public function testBindingsShouldBeResolved()
{
- list($boundValue) = $this->container->getDefinition('foo')->getBindings()['$baz']->getValues();
+ [$boundValue] = $this->container->getDefinition('foo')->getBindings()['$baz']->getValues();
$this->assertSame($this->container->getParameterBag()->resolveValue('%env(BAZ)%'), $boundValue);
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
index 375187a9368fe..df6f06653edcb 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
@@ -1393,6 +1393,10 @@ public function testUninitializedReference()
public function testAlmostCircular($visibility)
{
$container = include __DIR__.'/Fixtures/containers/container_almost_circular.php';
+ $container->compile();
+
+ $logger = $container->get('monolog.logger');
+ $this->assertEquals(new \stdClass(), $logger->handler);
$foo = $container->get('foo');
$this->assertSame($foo, $foo->bar->foobar->foo);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
index b87a6b8a244f7..3b77b7ed6eb2d 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -1054,6 +1054,9 @@ public function testAlmostCircular($visibility)
$container = new $container();
+ $logger = $container->get('monolog.logger');
+ $this->assertEquals(new \stdClass(), $logger->handler);
+
$foo = $container->get('foo');
$this->assertSame($foo, $foo->bar->foobar->foo);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php
index a1f885399bd58..96c714493e8f3 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php
@@ -1,5 +1,6 @@
register('monolog.logger', 'stdClass')->setPublic(true)
+ ->setProperty('handler', new Reference('mailer.transport'));
+
+$container->register('mailer.transport', 'stdClass')->setPublic($public)
+ ->setFactory([new Reference('mailer.transport_factory'), 'create']);
+
+$container->register('mailer.transport_factory', FactoryCircular::class)->setPublic($public)
+ ->addArgument(new TaggedIteratorArgument('mailer.transport'));
+
+$container->register('mailer.transport_factory.amazon', 'stdClass')->setPublic($public)
+ ->addArgument(new Reference('monolog.logger_2'))
+ ->addTag('mailer.transport');
+
+$container->register('monolog.logger_2', 'stdClass')->setPublic($public)
+ ->setProperty('handler', new Reference('mailer.transport'));
+
// same visibility for deps
$container->register('foo', FooCircular::class)->setPublic(true)
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
index fee80ac779749..b22e8bcffc744 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
@@ -111,6 +111,23 @@ public function __construct($lazyValues, $lazyEmptyValues)
}
}
+class FactoryCircular
+{
+ public $services;
+
+ public function __construct($services)
+ {
+ $this->services = $services;
+ }
+
+ public function create()
+ {
+ foreach ($this->services as $service) {
+ return $service;
+ }
+ }
+}
+
class FoobarCircular
{
public function __construct(FooCircular $foo)
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php
index 60c60b3adfb45..8bc0146fb13f7 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php
@@ -36,6 +36,7 @@ public function __construct()
'manager' => 'getManagerService',
'manager2' => 'getManager2Service',
'manager3' => 'getManager3Service',
+ 'monolog.logger' => 'getMonolog_LoggerService',
'root' => 'getRootService',
'subscriber' => 'getSubscriberService',
];
@@ -77,7 +78,11 @@ public function getRemovedIds(): array
'level5' => true,
'level6' => true,
'logger2' => true,
+ 'mailer.transport' => true,
+ 'mailer.transport_factory' => true,
+ 'mailer.transport_factory.amazon' => true,
'manager4' => true,
+ 'monolog.logger_2' => true,
'multiuse1' => true,
'subscriber2' => true,
];
@@ -352,6 +357,20 @@ protected function getManager3Service($lazyLoad = true)
return $this->services['manager3'] = new \stdClass($b);
}
+ /**
+ * Gets the public 'monolog.logger' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMonolog_LoggerService()
+ {
+ $this->services['monolog.logger'] = $instance = new \stdClass();
+
+ $instance->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService());
+
+ return $instance;
+ }
+
/**
* Gets the public 'root' shared service.
*
@@ -416,6 +435,34 @@ protected function getLevel5Service()
return $instance;
}
+ /**
+ * Gets the private 'mailer.transport' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMailer_TransportService()
+ {
+ return $this->privates['mailer.transport'] = (new \FactoryCircular(new RewindableGenerator(function () {
+ yield 0 => ($this->privates['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService());
+ }, 1)))->create();
+ }
+
+ /**
+ * Gets the private 'mailer.transport_factory.amazon' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMailer_TransportFactory_AmazonService()
+ {
+ $a = new \stdClass();
+
+ $this->privates['mailer.transport_factory.amazon'] = $instance = new \stdClass($a);
+
+ $a->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService());
+
+ return $instance;
+ }
+
/**
* Gets the private 'manager4' shared service.
*
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php
index 4905ade2dd408..4540459203d00 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php
@@ -42,9 +42,14 @@ public function __construct()
'listener3' => 'getListener3Service',
'listener4' => 'getListener4Service',
'logger' => 'getLoggerService',
+ 'mailer.transport' => 'getMailer_TransportService',
+ 'mailer.transport_factory' => 'getMailer_TransportFactoryService',
+ 'mailer.transport_factory.amazon' => 'getMailer_TransportFactory_AmazonService',
'manager' => 'getManagerService',
'manager2' => 'getManager2Service',
'manager3' => 'getManager3Service',
+ 'monolog.logger' => 'getMonolog_LoggerService',
+ 'monolog.logger_2' => 'getMonolog_Logger2Service',
'root' => 'getRootService',
'subscriber' => 'getSubscriberService',
];
@@ -434,6 +439,50 @@ protected function getLoggerService()
return $instance;
}
+ /**
+ * Gets the public 'mailer.transport' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMailer_TransportService()
+ {
+ $a = ($this->services['mailer.transport_factory'] ?? $this->getMailer_TransportFactoryService());
+
+ if (isset($this->services['mailer.transport'])) {
+ return $this->services['mailer.transport'];
+ }
+
+ return $this->services['mailer.transport'] = $a->create();
+ }
+
+ /**
+ * Gets the public 'mailer.transport_factory' shared service.
+ *
+ * @return \FactoryCircular
+ */
+ protected function getMailer_TransportFactoryService()
+ {
+ return $this->services['mailer.transport_factory'] = new \FactoryCircular(new RewindableGenerator(function () {
+ yield 0 => ($this->services['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService());
+ }, 1));
+ }
+
+ /**
+ * Gets the public 'mailer.transport_factory.amazon' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMailer_TransportFactory_AmazonService()
+ {
+ $a = ($this->services['monolog.logger_2'] ?? $this->getMonolog_Logger2Service());
+
+ if (isset($this->services['mailer.transport_factory.amazon'])) {
+ return $this->services['mailer.transport_factory.amazon'];
+ }
+
+ return $this->services['mailer.transport_factory.amazon'] = new \stdClass($a);
+ }
+
/**
* Gets the public 'manager' shared service.
*
@@ -482,6 +531,34 @@ protected function getManager3Service($lazyLoad = true)
return $this->services['manager3'] = new \stdClass($a);
}
+ /**
+ * Gets the public 'monolog.logger' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMonolog_LoggerService()
+ {
+ $this->services['monolog.logger'] = $instance = new \stdClass();
+
+ $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService());
+
+ return $instance;
+ }
+
+ /**
+ * Gets the public 'monolog.logger_2' shared service.
+ *
+ * @return \stdClass
+ */
+ protected function getMonolog_Logger2Service()
+ {
+ $this->services['monolog.logger_2'] = $instance = new \stdClass();
+
+ $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService());
+
+ return $instance;
+ }
+
/**
* Gets the public 'root' shared service.
*
diff --git a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php
index 747db80d805e1..2c216cbe7f850 100644
--- a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php
+++ b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php
@@ -493,7 +493,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
$hasCall = $refl->hasMethod('__call');
$hasStaticCall = $refl->hasMethod('__callStatic');
foreach (self::$method[$use] as $method) {
- list($interface, $name, $static, $description) = $method;
+ [$interface, $name, $static, $description] = $method;
if ($static ? $hasStaticCall : $hasCall) {
continue;
}
@@ -555,12 +555,12 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
}
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
- list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
+ [$declaringClass, $message] = self::$finalMethods[$parent][$method->name];
$deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
}
if (isset(self::$internalMethods[$class][$method->name])) {
- list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
+ [$declaringClass, $message] = self::$internalMethods[$class][$method->name];
if (strncmp($ns, $declaringClass, $len)) {
$deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className);
}
@@ -600,7 +600,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
}
if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) {
- list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
+ [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
if ('void' === $normalizedType) {
$canAddReturnType = false;
@@ -668,7 +668,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
$definedParameters[$parameter->name] = true;
}
}
- foreach ($matches as list(, $parameterType, $parameterName)) {
+ foreach ($matches as [, $parameterType, $parameterName]) {
if (!isset($definedParameters[$parameterName])) {
$parameterType = trim($parameterType);
self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className);
@@ -939,10 +939,10 @@ private function patchMethod(\ReflectionMethod $method, string $returnType, stri
continue;
}
- list($namespace, $useOffset, $useMap) = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file);
+ [$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file);
if ('\\' !== $type[0]) {
- list($declaringNamespace, , $declaringUseMap) = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile);
+ [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile);
$p = strpos($type, '\\', 1);
$alias = $p ? substr($type, 0, $p) : $type;
diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php
index 11dce4897bc65..87d538eaf8f04 100644
--- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php
+++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php
@@ -177,7 +177,7 @@ public function getCalledListeners(Request $request = null)
$hash = $request ? spl_object_hash($request) : null;
$called = [];
foreach ($this->callStack as $listener) {
- list($eventName, $requestHash) = $this->callStack->getInfo();
+ [$eventName, $requestHash] = $this->callStack->getInfo();
if (null === $hash || $hash === $requestHash) {
$called[] = $listener->getInfo($eventName);
}
@@ -207,7 +207,7 @@ public function getNotCalledListeners(Request $request = null)
if (null !== $this->callStack) {
foreach ($this->callStack as $calledListener) {
- list(, $requestHash) = $this->callStack->getInfo();
+ [, $requestHash] = $this->callStack->getInfo();
if (null === $hash || $hash === $requestHash) {
$calledListeners[] = $calledListener->getWrappedListener();
diff --git a/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php
index ea9fe8c1b6cdc..173f4273eb2f4 100644
--- a/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php
+++ b/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php
@@ -19,10 +19,9 @@
class EventDispatcherTest extends TestCase
{
/* Some pseudo events */
- const preFoo = 'pre.foo';
- const postFoo = 'post.foo';
- const preBar = 'pre.bar';
- const postBar = 'post.bar';
+ private const preFoo = 'pre.foo';
+ private const postFoo = 'post.foo';
+ private const preBar = 'pre.bar';
/**
* @var EventDispatcher
diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php
index 5a3fb0a0efc17..6e3cc488b1ee3 100644
--- a/src/Symfony/Component/ExpressionLanguage/Lexer.php
+++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php
@@ -60,7 +60,7 @@ public function tokenize(string $expression)
throw new SyntaxError(sprintf('Unexpected "%s".', $expression[$cursor]), $cursor, $expression);
}
- list($expect, $cur) = array_pop($brackets);
+ [$expect, $cur] = array_pop($brackets);
if ($expression[$cursor] != strtr($expect, '([{', ')]}')) {
throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression);
}
@@ -92,7 +92,7 @@ public function tokenize(string $expression)
$tokens[] = new Token(Token::EOF_TYPE, null, $cursor + 1);
if (!empty($brackets)) {
- list($expect, $cur) = array_pop($brackets);
+ [$expect, $cur] = array_pop($brackets);
throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression);
}
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index aaf62d02674f8..d9609f5484c2d 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -454,8 +454,8 @@ public function makePathRelative(string $endPath, string $startPath)
return $result;
};
- list($endPath, $endDriveLetter) = $splitDriveLetter($endPath);
- list($startPath, $startDriveLetter) = $splitDriveLetter($startPath);
+ [$endPath, $endDriveLetter] = $splitDriveLetter($endPath);
+ [$startPath, $startDriveLetter] = $splitDriveLetter($startPath);
$startPathArr = $splitPath($startPath);
$endPathArr = $splitPath($endPath);
@@ -590,7 +590,7 @@ public function isAbsolutePath(string $file)
public function tempnam(string $dir, string $prefix/*, string $suffix = ''*/)
{
$suffix = \func_num_args() > 2 ? func_get_arg(2) : '';
- list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
+ [$scheme, $hierarchy] = $this->getSchemeAndHierarchy($dir);
// If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem
if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) {
diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php
index 5a47812bd3474..add8e7df596be 100644
--- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php
+++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php
@@ -35,9 +35,10 @@ public function testAccept($mode, $expected)
case SortableIterator::SORT_BY_ACCESSED_TIME:
touch(self::toAbsolute('.git'));
sleep(1);
- file_get_contents(self::toAbsolute('.bar'));
+ touch(self::toAbsolute('.bar'), time());
break;
case SortableIterator::SORT_BY_CHANGED_TIME:
+ sleep(1);
file_put_contents(self::toAbsolute('test.php'), 'foo');
sleep(1);
file_put_contents(self::toAbsolute('test.py'), 'foo');
diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
index 09c5d69a2e02e..be8af57828e05 100644
--- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
+++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php
@@ -151,7 +151,7 @@ private function getFileUploadError(int $errorCode)
$messageParameters = [];
if (\UPLOAD_ERR_INI_SIZE === $errorCode) {
- list($limitAsString, $suffix) = $this->factorizeSizes(0, self::getMaxFilesize());
+ [$limitAsString, $suffix] = $this->factorizeSizes(0, self::getMaxFilesize());
$messageTemplate = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
$messageParameters = [
'{{ limit }}' => $limitAsString,
diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php
index 53fbcb51963c2..8c92046ee3590 100644
--- a/src/Symfony/Component/Form/FormBuilder.php
+++ b/src/Symfony/Component/Form/FormBuilder.php
@@ -228,7 +228,7 @@ public function getIterator()
*/
private function resolveChild(string $name): FormBuilderInterface
{
- list($type, $options) = $this->unresolvedChildren[$name];
+ [$type, $options] = $this->unresolvedChildren[$name];
unset($this->unresolvedChildren[$name]);
diff --git a/src/Symfony/Component/Form/Resources/translations/validators.af.xlf b/src/Symfony/Component/Form/Resources/translations/validators.af.xlf
new file mode 100644
index 0000000000000..58cd939cf793f
--- /dev/null
+++ b/src/Symfony/Component/Form/Resources/translations/validators.af.xlf
@@ -0,0 +1,139 @@
+
+