diff --git a/.appveyor.yml b/.appveyor.yml index 09fa4fbc5954b..e536bf33d2201 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,7 +13,7 @@ init: - SET SYMFONY_DEPRECATIONS_HELPER=strict - SET ANSICON=121x90 (121x90) - SET SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1 - - SET SYMFONY_DEPRECATIONS_HELPER=max[indirect]=170 + - SET SYMFONY_DEPRECATIONS_HELPER=max[direct]=1 - REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f install: @@ -49,12 +49,10 @@ install: - IF NOT EXIST composer.phar (appveyor DownloadFile https://github.com/composer/composer/releases/download/2.0.0/composer.phar) - php composer.phar self-update --2 - copy /Y .github\composer-config.json %APPDATA%\Composer\config.json - - 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 ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -o '[0-9][0-9]*\.[0-9]'"`) DO (SET SYMFONY_VERSION=%%F) - php .github/build-packages.php HEAD^ %SYMFONY_VERSION% src\Symfony\Bridge\PhpUnit - - SET "SYMFONY_REQUIRE=>=%SYMFONY_VERSION%" - SET COMPOSER_ROOT_VERSION=%SYMFONY_VERSION%.x-dev - php composer.phar update --no-progress --ansi - php phpunit install diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 91fcd5ea0f79e..b6a13a19f76d1 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -157,6 +157,7 @@ jobs: - name: Run tests run: ./phpunit --group integration -v env: + SYMFONY_DEPRECATIONS_HELPER: max[direct]=1 # to be removed once DbalLogger is compatible with dbal 3.2+ REDIS_HOST: localhost REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005' REDIS_SENTINEL_HOSTS: 'localhost:26379' diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 09e0b1f25d6b0..42bc28c6622b7 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -62,6 +62,7 @@ jobs: echo COLUMNS=120 >> $GITHUB_ENV echo PHPUNIT="$(readlink -f ./phpunit) --exclude-group tty,benchmark,intl-data" >> $GITHUB_ENV echo COMPOSER_UP='composer update --no-progress --ansi' >> $GITHUB_ENV + echo SYMFONY_DEPRECATIONS_HELPER=max[direct]=1 >> $GITHUB_ENV # to be removed once DbalLogger is compatible with dbal 3.2+ SYMFONY_VERSIONS=$(git ls-remote -q --heads | cut -f2 | grep -o '/[1-9][0-9]*\.[0-9].*' | sort -V) SYMFONY_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+') diff --git a/CHANGELOG-6.0.md b/CHANGELOG-6.0.md index 0023f5b2f2c73..969f4134161ff 100644 --- a/CHANGELOG-6.0.md +++ b/CHANGELOG-6.0.md @@ -7,6 +7,27 @@ in 6.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.0.0...v6.0.1 +* 6.0.0-RC1 (2021-11-24) + + * security #cve-2021-41268 [SecurityBundle] Default signature_properties to the previous behavior (wouterj) + * security #cve-2021-41267 [HttpKernel] Fix missing extra trusted header in sub-request (jderusse) + * security #cve-2021-41270 [Serializer] Use single quote to escape formulas (jderusse) + * bug #44230 [Console] Add Suggestion class for more advanced completion suggestion (wouterj) + * bug #44232 [Cache] fix connecting to local Redis sockets (nicolas-grekas) + * bug #44204 [HttpClient] fix closing curl multi handle when destructing client (nicolas-grekas) + * bug #44208 [Process] exclude argv/argc from possible default env vars (nicolas-grekas) + * bug #44188 [VarExporter] fix exporting declared but unset properties when __sleep() is implemented (nicolas-grekas) + * bug #44176 [Console] Default ansi option to null (jderusse) + * bug #44179 [WebProfilerBundle] Fix JS error when toolbar is reloaded (jderusse) + * bug #44177 [SecurityBundle] Remove Guard (derrabus) + * bug #44172 [Security] Guard is incompatible with Symfony 6 (derrabus) + * bug #44119 [HttpClient][Mime] Add correct IDN flags for IDNA2008 compliance (j-bernard) + * bug #44139 [WebProfilerBundle] Prevent installation of incompatible mailer component versions (Anne-Julia Seitz) + * bug #43917 Allow autodetecting mapping type for any object (franmomu) + * bug #44130 [SecurityBundle] Remove outdated conditions based on authenticatorManagerEnabled (chalasr) + * bug #44131 [Yaml] properly parse quoted strings tagged with !!str (xabbuh) + * bug #42323 [TwigBridge] do not merge label classes into expanded choice labels (xabbuh) + * 6.0.0-BETA3 (2021-11-18) * feature #44125 Add a setter on DateTimeNormalizer to change the default context at runtime (Seldaek) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1ac10f641e698..92b9b528b9c50 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,9 +20,9 @@ The Symfony Connect username in parenthesis allows to get more information - Jordi Boggiano (seldaek) - Victor Berchet (victor) - Javier Eguiluz (javier.eguiluz) + - Thomas Calvet (fancyweb) - Ryan Weaver (weaverryan) - Roland Franssen (ro0) - - Thomas Calvet (fancyweb) - Jakub Zalas (jakubzalas) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) @@ -46,20 +46,21 @@ The Symfony Connect username in parenthesis allows to get more information - Jan Schädlich (jschaedl) - Igor Wiedler (igorw) - Eriksen Costa (eriksencosta) + - Kevin Bond (kbond) - Ener-Getick (energetick) - Sarah Khalil (saro0h) - - Kevin Bond (kbond) - Pierre du Plessis (pierredup) + - Vasilij Duško (staff) - Valentin Udaltsov (vudaltsov) - Iltar van der Berg (kjarli) - Jonathan Wage (jwage) - - Vasilij Duško (staff) - Matthias Pigulla (mpdude) - Diego Saint Esteben (dosten) - Grégoire Paris (greg0ire) - Alexandre Salomé (alexandresalome) - William Durand (couac) - ornicar + - Jérôme Tamarelle (gromnan) - Konstantin Myakshin (koc) - Dany Maillard (maidmaid) - Francis Besset (francisbesset) @@ -68,13 +69,12 @@ The Symfony Connect username in parenthesis allows to get more information - Titouan Galopin (tgalopin) - Laurent VOULLEMIER (lvo) - Vasilij Dusko | CREATION - - Jérôme Tamarelle (gromnan) - Bulat Shakirzyanov (avalanche123) - David Maicher (dmaicher) + - Gábor Egyed (1ed) - gadelat (gadelat) - Saša Stamenković (umpirsky) - Peter Rehm (rpet) - - Gábor Egyed (1ed) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - Diego Saint Esteben (dii3g0) @@ -82,10 +82,10 @@ The Symfony Connect username in parenthesis allows to get more information - Konstantin Kudryashov (everzet) - Vladimir Reznichenko (kalessil) - Bilal Amarni (bamarni) + - Antoine M (amakdessi) - Florin Patan (florinpatan) - Jáchym Toušek (enumag) - Alex Pott - - Antoine M (amakdessi) - Michel Weimerskirch (mweimerskirch) - Andrej Hudec (pulzarraider) - Christian Raue @@ -112,24 +112,25 @@ The Symfony Connect username in parenthesis allows to get more information - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Mathieu Santostefano (welcomattic) - John Wards (johnwards) - Tomas Norkūnas (norkunas) - Baptiste Clavié (talus) - Antoine Hérault (herzult) - Paráda József (paradajozsef) + - Alexandre Daubois (alexandre-daubois) - Vincent Langlet (deviling) + - HypeMC (hypemc) - Massimiliano Arione (garak) - Arnaud Le Blanc (arnaud-lb) - Przemysław Bogusz (przemyslaw-bogusz) + - Julien Falque (julienfalque) - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - Tomáš Votruba (tomas_votruba) - Mathias Arlaud (mtarld) - Tim Nagel (merk) - - Alexandre Daubois (alexandre-daubois) - - HypeMC (hypemc) - Chris Wilkinson (thewilkybarkid) - - Julien Falque (julienfalque) - Peter Kokot (maastermedia) - Lars Strojny (lstrojny) - Brice BERNARD (brikou) @@ -144,7 +145,6 @@ The Symfony Connect username in parenthesis allows to get more information - Adrien Brault (adrienbrault) - Yanick Witschi (toflar) - Jacob Dreesen (jdreesen) - - Mathieu Santostefano (welcomattic) - Malte Schlüter (maltemaltesich) - Joel Wurtz (brouznouf) - Théo FIDRY (theofidry) @@ -168,6 +168,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gary PEGEOT (gary-p) - Matthieu Napoli (mnapoli) - Ruud Kamphuis (ruudk) + - Ion Bazan (ionbazan) - Jannik Zschiesche (apfelbox) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) @@ -186,7 +187,6 @@ The Symfony Connect username in parenthesis allows to get more information - Hidenori Goto (hidenorigoto) - Jan Rosier (rosier) - Alessandro Chitolina (alekitto) - - Ion Bazan (ionbazan) - Albert Casademont (acasademont) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) @@ -202,6 +202,8 @@ The Symfony Connect username in parenthesis allows to get more information - George Mponos (gmponos) - jwdeitch - Jeroen Spee (jeroens) + - Jérôme Parmentier (lctrs) + - Marco Pivetta (ocramius) - Fabien Bourigault (fbourigault) - Joe Bennett (kralos) - Mikael Pajunen @@ -216,16 +218,16 @@ The Symfony Connect username in parenthesis allows to get more information - Thomas Rabaix (rande) - Chi-teck - Timo Bakx (timobakx) - - Marco Pivetta (ocramius) - Vincent Touzet (vincenttouzet) - Nate Wiebe (natewiebe13) - Rouven Weßling (realityking) - - Jérôme Parmentier (lctrs) + - Michael Babker (mbabker) - Ben Davies (bendavies) - Clemens Tolboom - Helmer Aaviksoo - Christopher Hertel (chertel) - Remon van de Kamp (rpkamp) + - Rokas Mikalkėnas (rokasm) - Filippo Tessarotto (slamdunk) - Hiromi Hishida (77web) - Michael Käfer (michael_kaefer) @@ -233,6 +235,7 @@ The Symfony Connect username in parenthesis allows to get more information - Michał Pipa (michal.pipa) - Dawid Nowak - Andreas Möller (localheinz) + - Roman Martinuk (a2a4) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba @@ -241,8 +244,9 @@ The Symfony Connect username in parenthesis allows to get more information - Samuel NELA (snela) - David Prévot - Hugo Monteiro (monteiro) + - Baptiste Leduc (korbeil) - Dmitrii Poddubnyi (karser) - - Michael Babker (mbabker) + - zairig imad (zairigimad) - Tien Vo (tienvx) - Timothée Barray (tyx) - James Halsall (jaitsu) @@ -270,11 +274,9 @@ The Symfony Connect username in parenthesis allows to get more information - Philippe Segatori - Thibaut Cheymol (tcheymol) - Sebastien Morel (plopix) - - Baptiste Leduc (korbeil) - mcfedr (mcfedr) - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) - - zairig imad (zairigimad) - Baptiste Lafontaine (magnetik) - Mathieu Lemoine (lemoinem) - Denis Brumann (dbrumann) @@ -287,13 +289,11 @@ The Symfony Connect username in parenthesis allows to get more information - Stadly - Stepan Anchugov (kix) - François Pluchino (francoispluchino) - - Rokas Mikalkėnas (rokasm) - bronze1man - sun (sun) - Larry Garfield (crell) - Edi Modrić (emodric) - Gocha Ossinkine (ossinkine) - - Roman Martinuk (a2a4) - Leo Feyer (leofeyer) - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) @@ -317,6 +317,7 @@ The Symfony Connect username in parenthesis allows to get more information - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) + - fd6130 (fdtvui) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Maciej Malarz (malarzm) @@ -330,6 +331,7 @@ The Symfony Connect username in parenthesis allows to get more information - Bastien Jaillot (bastnic) - Rui Marinho (ruimarinho) - Patrick Landolt (scube) + - Michał (bambucha15) - Eugene Wissner - Bohan Yang (brentybh) - Pascal Montoya @@ -362,7 +364,6 @@ The Symfony Connect username in parenthesis allows to get more information - Marcos Sánchez - Elnur Abdurrakhimov (elnur) - Manuel Reinhard (sprain) - - fd6130 (fdtvui) - Harm van Tilborg (hvt) - Danny Berger (dpb587) - Antonio J. García Lagar (ajgarlag) @@ -375,9 +376,9 @@ The Symfony Connect username in parenthesis allows to get more information - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA + - Sylvain Fabre (sylfabre) - Patrick McDougle (patrick-mcdougle) - Marc Weistroff (futurecat) - - Michał (bambucha15) - Alif Rachmawadi - Anton Chernikov (anton_ch1989) - Kristen Gilden (kgilden) @@ -387,6 +388,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sullivan SENECHAL (soullivaneuh) - Thomas Bisignani (toma) - Uwe Jäger (uwej711) + - Dāvis Zālītis (k0d3r1s) - Eugene Leonovich (rybakit) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) @@ -395,11 +397,13 @@ The Symfony Connect username in parenthesis allows to get more information - Jan Sorgalla (jsor) - Ray - Chekote + - Aleksandar Jakovljevic (ajakov) - Thomas Adam - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - jdhoek - Thomas Landauer (thomas-landauer) + - Jurica Vlahoviček (vjurica) - Bob den Otter (bopp) - Thomas Schulz (king2500) - Frank de Jonge (frenkynet) @@ -412,6 +416,7 @@ The Symfony Connect username in parenthesis allows to get more information - Dmitriy Mamontov (mamontovdmitriy) - Ben Ramsey (ramsey) - Laurent Masforné (heisenberg) + - Sergey (upyx) - Giorgio Premi - Guillaume (guill) - renanbr @@ -434,7 +439,6 @@ The Symfony Connect username in parenthesis allows to get more information - Soner Sayakci - Peter Kruithof (pkruithof) - Michael Holm (hollo) - - Sylvain Fabre (sylfabre) - Arjen van der Meijden - Markus Fasselt (digilist) - Damien Alexandre (damienalexandre) @@ -452,7 +456,6 @@ The Symfony Connect username in parenthesis allows to get more information - Chris Smith (cs278) - Florian Klein (docteurklein) - W0rma - - Dāvis Zālītis (k0d3r1s) - Manuel Kiessling (manuelkiessling) - Dimitri Gritsajuk (ottaviano) - Alexey Kopytko (sanmai) @@ -497,6 +500,7 @@ The Symfony Connect username in parenthesis allows to get more information - Berny Cantos (xphere81) - Andrii Bodnar - Thierry Thuon (lepiaf) + - Antonio Jose Cerezo (ajcerezo) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) - Loïc Frémont (loic425) @@ -507,9 +511,9 @@ The Symfony Connect username in parenthesis allows to get more information - Tri Pham (phamuyentri) - Urinbayev Shakhobiddin (shokhaa) - Gennady Telegin (gtelegin) - - Sergey (upyx) - Krystian Marcisz (simivar) - Toni Rudolf (toooni) + - Dalibor Karlović (dkarlovi) - Erin Millard - Artur Melo (restless) - Matthew Lewinski (lewinski) @@ -526,10 +530,12 @@ The Symfony Connect username in parenthesis allows to get more information - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) - Benjamin Cremer (bcremer) + - Hendrik Luup (hluup) - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Dmytro Borysovskyi (dmytr0) - Tomasz Kowalczyk (thunderer) + - Artem Lopata - Artur Eshenbrener - Thomas Perez (scullwm) - Yoann RENARD (yrenard) @@ -585,7 +591,6 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Beyer - Manuel Alejandro Paz Cetina - Shein Alexey - - Aleksandar Jakovljevic (ajakov) - Jacek Jędrzejewski (jacek.jedrzejewski) - Romain Gautier (mykiwi) - Stefan Kruppa @@ -611,7 +616,6 @@ The Symfony Connect username in parenthesis allows to get more information - Marc Morales Valldepérez (kuert) - Jean-Baptiste GOMOND (mjbgo) - Vadim Kharitonov (virtuozzz) - - Jurica Vlahoviček (vjurica) - Oscar Cubo Medina (ocubom) - Karel Souffriau - Christophe L. (christophelau) @@ -630,7 +634,6 @@ The Symfony Connect username in parenthesis allows to get more information - Alexandru Furculita (afurculita) - Valentin Jonovs (valentins-jonovs) - Bastien DURAND (deamon) - - Antonio Jose Cerezo (ajcerezo) - Jeanmonod David (jeanmonod) - Christin Gruber (christingruber) - Andrey Sevastianov @@ -640,11 +643,11 @@ The Symfony Connect username in parenthesis allows to get more information - Noémi Salaün (noemi-salaun) - Niklas Fiekas - Philippe Segatori - - Dalibor Karlović (dkarlovi) - Markus Bachmann (baachi) - Kévin THERAGE (kevin_therage) - Michel Hunziker - Gunnstein Lye (glye) + - scyzoryck - Matthias Krauser (mkrauser) - Erkhembayar Gantulga (erheme318) - Lorenzo Millucci (lmillucci) @@ -665,14 +668,12 @@ The Symfony Connect username in parenthesis allows to get more information - Stefan Gehrig (sgehrig) - vagrant - Aurimas Niekis (gcds) - - Hendrik Luup (hluup) - EdgarPE - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) - Martijn Cuppens - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) - - Artem Lopata - Chris Sedlmayr (catchamonkey) - Indra Gunawan (indragunawan) - Mathias STRASSER (roukmoute) @@ -703,6 +704,7 @@ The Symfony Connect username in parenthesis allows to get more information - Lukáš Holeczy (holicz) - Erik Saunier (snickers) - franek (franek) + - Jerzy (jlekowski) - Raulnet - Christian Wahler - Dries Vints @@ -770,6 +772,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alex Bacart - mcben - Jérôme Vieilledent (lolautruche) + - Roman Anasal - Maks Slesarenko - Filip Procházka (fprochazka) - mmoreram @@ -808,6 +811,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tom Klingenberg - Gábor Fási - DUPUCH (bdupuch) + - Dadang NH (dadangnh) - Nate (frickenate) - Joachim Løvgaard (loevgaard) - Stefan Kruppa @@ -832,8 +836,10 @@ The Symfony Connect username in parenthesis allows to get more information - Samuele Lilli (doncallisto) - Gawain Lynch (gawain) - Peter Bowyer (pbowyer) + - Wojciech Kania - mmokhi - NothingWeAre + - Andrii Dembitskyi - Ryan - Lctrs - Alexander Deruwe (aderuwe) @@ -857,6 +863,7 @@ The Symfony Connect username in parenthesis allows to get more information - Johnny Robeson (johnny) - Disquedur - Michiel Boeckaert (milio) + - Benjamin Morel - Dmitriy Derepko - Geoffrey Tran (geoff) - Pablo Lozano (arkadis) @@ -992,7 +999,6 @@ The Symfony Connect username in parenthesis allows to get more information - Timothée BARRAY - Nilmar Sanchez Muguercia - Ivo Bathke (ivoba) - - scyzoryck - Ippei SUmida (ippey_s) - David Molineus - Strate @@ -1010,6 +1016,7 @@ The Symfony Connect username in parenthesis allows to get more information - rtek - Benjamin Dos Santos - Jérémy Jarrié (gagnar) + - Adrien Jourdier - Tomas Javaisis - Ivan Grigoriev - Johann Saunier (prophet777) @@ -1019,6 +1026,7 @@ The Symfony Connect username in parenthesis allows to get more information - Michael Devery (mickadoo) - Antoine Corcy - Ahmed Ashraf (ahmedash95) + - Gert Wijnalda (cinamo) - Luca Saba (lucasaba) - maxime.perrimond - Sascha Grossenbacher @@ -1090,7 +1098,6 @@ The Symfony Connect username in parenthesis allows to get more information - Junaid Farooq (junaidfarooq) - Massimiliano Braglia (massimilianobraglia) - Frankie Wittevrongel - - Jerzy (jlekowski) - Richard Quadling - Raphaëll Roussel - Anton Kroshilin @@ -1240,6 +1247,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jake (jakesoft) - Flinsch - Quentin Dreyer + - Bahman Mehrdad (bahman) - Jordan de Laune (jdelaune) - Christopher Hall (mythmakr) - none (nelexa) @@ -1251,6 +1259,7 @@ The Symfony Connect username in parenthesis allows to get more information - Martin Parsiegla (spea) - Bernhard Rusch - bhavin (bhavin4u) + - Mario Ramundo (rammar) - Ivan - Quentin Schuler - Nico Haase @@ -1259,6 +1268,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sofiane HADDAG (sofhad) - frost-nzcr4 - Taylor Otwell + - Shahriar56 - Sami Mussbach - Dhananjay Goratela - Kien Nguyen @@ -1268,17 +1278,18 @@ The Symfony Connect username in parenthesis allows to get more information - Achilles Kaloeridis (achilles) - Adrien Wilmet (adrienfr) - Laurent Bassin (lbassin) + - Mouad ZIANI (mouadziani) - Tomasz Ignatiuk - andrey1s - Abhoryo - Fabian Vogler (fabian) + - Shakhobiddin - Korvin Szanto - Stéphan Kochen - Steven Dubois - Arjan Keeman - siganushka - Alaattin Kahramanlar (alaattin) - - Dadang NH (dadangnh) - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) - Neil Ferreira @@ -1287,6 +1298,7 @@ The Symfony Connect username in parenthesis allows to get more information - Paul LE CORRE - Loïc Beurlet - Sébastien COURJEAN + - Ana Raro - Daniel Gorgan - Ana Raro - Tony Malzhacker @@ -1295,9 +1307,9 @@ The Symfony Connect username in parenthesis allows to get more information - Cyril Quintin (cyqui) - Cyrille Bourgois (cyrilleb) - Gerard van Helden (drm) + - Ivan Sarastov (isarastov) - Johnny Peck (johnnypeck) - Jordi Sala Morales (jsala) - - Roman Anasal - Ivan Menshykov - David Romaní - Patrick Allaert @@ -1305,7 +1317,6 @@ The Symfony Connect username in parenthesis allows to get more information - Matt Robinson (inanimatt) - Aleksey Podskrebyshev - Calin Mihai Pristavu - - Andrii Dembitskyi - David Marín Carreño (davefx) - Fabien LUCAS (flucas2) - Ondrej Machulda (ondram) @@ -1328,6 +1339,7 @@ The Symfony Connect username in parenthesis allows to get more information - Derek ROTH - Ben Johnson - mweimerskirch + - Andrew Codispoti - Benjamin Franzke - baron (bastien) - Dmytro Boiko (eagle) @@ -1379,7 +1391,6 @@ The Symfony Connect username in parenthesis allows to get more information - Matthew Davis (mdavis1982) - Paulo Ribeiro (paulo) - Markus S. (staabm) - - Benjamin Morel - Maks - Knallcharge - Antoine LA @@ -1467,6 +1478,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mahmoud Mostafa (mahmoud) - Fractal Zombie - Ahmed Abdou + - Khoo Yong Jun - shreyadenny - Daniel Iwaniec - Pieter @@ -1500,6 +1512,7 @@ The Symfony Connect username in parenthesis allows to get more information - Amirreza Shafaat (amirrezashafaat) - Adoni Pavlakis (adoni) - Nicolas Le Goff (nlegoff) + - Alex Hofbauer (alexhofbauer) - Maarten Nusteling (nusje2000) - Ahmed EBEN HASSINE (famas23) - Ben Oman @@ -1777,6 +1790,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jorge Vahldick (jvahldick) - Frederic Godfrin - Paul Matthews + - aim8604 - Jakub Kisielewski - Vacheslav Silyutin - Aleksandr Dankovtsev @@ -1831,6 +1845,7 @@ The Symfony Connect username in parenthesis allows to get more information - Rubén Calvo (rubencm) - Abdul.Mohsen B. A. A - Swen van Zanten + - Agustin Gomes - Benoît Burnichon - pthompson - Malaney J. Hill @@ -1845,6 +1860,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sebastian Göttschkes (sgoettschkes) - Tatsuya Tsuruoka - Ross Tuck + - Oleksiy (alexndlm) - Kévin Gomez (kevin) - Mihai Nica (redecs) - Andrei Igna @@ -1935,7 +1951,9 @@ The Symfony Connect username in parenthesis allows to get more information - Lance McNearney - Volodymyr Kupriienko (greeflas) - Serhiy Lunak (slunak) + - Wojciech Błoszyk (wbloszyk) - Giorgio Premi + - abunch - Sergey Belyshkin - tamcy - Mikko Pesari @@ -1958,6 +1976,7 @@ The Symfony Connect username in parenthesis allows to get more information - Foxprodev - Max Summe - WedgeSama + - Dale.Nash - Felds Liscia - Chihiro Adachi (chihiro-adachi) - Raphaëll Roussel @@ -2030,6 +2049,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alexander Janssen (tnajanssen) - Thomas Chmielowiec (chmielot) - Jānis Lukss + - Julien BERNARD - Michael Zangerle - rkerner - Alex Silcock @@ -2177,6 +2197,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matt Farmer - catch - aetxebeste + - Juga Paazmaya - Alexandre Segura - afaricamp - Josef Cech @@ -2186,11 +2207,12 @@ The Symfony Connect username in parenthesis allows to get more information - Andrii Boiko - Harold Iedema - WaiSkats + - Morimoto Ryosuke - Ikhsan Agustian - Arnau González (arnaugm) - - Bahman Mehrdad (bahman) - Simon Bouland (bouland) - Jibé Barth (jibbarth) + - Jm Aribau (jmaribau) - Matthew Foster (mfoster) - Reyo Stallenberg (reyostallenberg) - Paul Seiffert (seiffert) @@ -2226,6 +2248,7 @@ The Symfony Connect username in parenthesis allows to get more information - Eric Schildkamp - Andreas - Markus + - agaktr - kernig - Thomas Chmielowiec - shdev @@ -2239,6 +2262,7 @@ The Symfony Connect username in parenthesis allows to get more information - Joe Springe - Mickael GOETZ - Maciej Schmidt + - botbotbot - Dennis Væversted - Timon van der Vorm - nuncanada @@ -2255,7 +2279,6 @@ The Symfony Connect username in parenthesis allows to get more information - Mathieu Dewet (mdewet) - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) - - Mario Ramundo (rammar) - Rémi Faivre (rfv) - Thierry Marianne (thierrymarianne) - Nick Stemerdink @@ -2263,6 +2286,7 @@ The Symfony Connect username in parenthesis allows to get more information - jjanvier - Julius Beckmann - Ruben Jansen + - Marc Biorklund - shreypuranik - loru88 - Thibaut Salanon @@ -2291,6 +2315,7 @@ The Symfony Connect username in parenthesis allows to get more information - Yuri Karaban - Johan - Thomas Rothe + - Edwin - Martin - nietonfir - Andriy @@ -2300,21 +2325,26 @@ The Symfony Connect username in parenthesis allows to get more information - Pavel.Batanov - avi123 - Pavel Prischepa + - qzylalala - alsar - downace - Aarón Nieves Fernández - Mike Meier + - Mikolaj Czajkowski - Kirill Saksin - Shiro - Reda DAOUDI - Koalabaerchen - michalmarcinkowski - Warwick + - Jesper Skytte - Chris - Farid Jalilov - Christiaan Wiesenekker - Florent Olivaud + - Sergey Panteleev - JakeFr + - Dmitry Hordinky - Oliver Klee - Simon Sargeant - efeen @@ -2329,20 +2359,22 @@ The Symfony Connect username in parenthesis allows to get more information - kshida - Michał Dąbrowski (defrag) - Aryel Tupinamba (dfkimera) + - Florian Wolfsjaeger (flowolf) - Hans Höchtl (hhoechtl) - Simone Fumagalli (hpatoio) - Brian Graham (incognito) - Kevin Vergauwen (innocenzo) - Alessio Baglio (ioalessio) + - Jawira Portugal (jawira) - Johannes Müller (johmue) - Jordi Llonch (jordillonch) - - Mouad ZIANI (mouadziani) - Nicholas Ruunu (nicholasruunu) - Jeroen van den Nieuwenhuisen (nieuwenhuisen) - Cyril Pascal (paxal) - Cédric Dugat (ph3nol) - Philip Dahlstrøm (phidah) - Milos Colakovic (project2481) + - Raphael de Almeida (raphaeldealmeida) - Rénald Casagraude (rcasagraude) - Robin Duval (robin-duval) - Grinbergs Reinis (shima5) @@ -2446,6 +2478,7 @@ The Symfony Connect username in parenthesis allows to get more information - Darryl Hein (xmmedia) - Sadicov Vladimir (xtech) - Kevin EMO (zarcox) + - Marcel Berteler - sdkawata - Andrzej - Alexander Zogheb @@ -2473,7 +2506,6 @@ The Symfony Connect username in parenthesis allows to get more information - adenkejawen - Florent SEVESTRE (aniki-taicho) - Ari Pringle (apringle) - - Gert Wijnalda (cinamo) - Dan Ordille (dordille) - Jan Eichhorn (exeu) - Grégory Pelletier (ip512) @@ -2493,16 +2525,13 @@ The Symfony Connect username in parenthesis allows to get more information - grifx - Robert Campbell - Matt Lehner - - Shakhobiddin - Helmut Januschka - Hein Zaw Htet™ - Ruben Kruiswijk - Cosmin-Romeo TANASE - - Ana Raro - Michael J - youssef saoubou - Joseph Maarek - - Ivan Sarastov - Alexander Menk - Alex Pods - hadriengem @@ -2517,6 +2546,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matthieu Prat - Grummfy - zors1 + - Peter Simoncic - Paul Le Corre - Noel Light-Hilary - Filipe Guerra @@ -2693,6 +2723,7 @@ The Symfony Connect username in parenthesis allows to get more information - temperatur - misterx - Cas + - arend - Vincent Godé - Dusan Kasan - Michael Steininger @@ -2739,7 +2770,6 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel Bannert - Karim Miladi - Michael Genereux - - Wojciech Kania - patrick-mcdougle - Dariusz Czech - Bruno Baguette @@ -2811,6 +2841,7 @@ The Symfony Connect username in parenthesis allows to get more information - Adam Klvač - Bruno Nogueira Nascimento Wowk - Tomanhez + - satalaondrej - jonmldr - Yevgen Kovalienia - Lebnik @@ -2871,6 +2902,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas - Sergio Santoro - tirnanog06 + - Andrejs Leonovs - phc - Дмитрий Пацура - Signor Pedro @@ -3037,6 +3069,7 @@ The Symfony Connect username in parenthesis allows to get more information - ddegentesh - DSeemiller - Jan Emrich + - Anne-Julia Seitz - Mark Topper - Xavier REN - Zander Baldwin diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 6d03fdbae3561..367eb12e29162 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -286,13 +286,15 @@ private function detectMappingType(string $directory, ContainerBuilder $containe $glob = new GlobResource($directory, '*', true); $container->addResource($glob); + $quotedMappingObjectName = preg_quote($this->getMappingObjectDefaultName(), '/'); + foreach ($glob as $file) { $content = file_get_contents($file); - if (preg_match('/^#\[.*Entity\b/m', $content)) { + if (preg_match('/^#\[.*'.$quotedMappingObjectName.'\b/m', $content)) { break; } - if (preg_match('/^ \* @.*Entity\b/m', $content)) { + if (preg_match('/^ \* @.*'.$quotedMappingObjectName.'\b/m', $content)) { $type = 'annotation'; break; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index e4f578bc207e7..774f1f0babf3c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -49,6 +49,10 @@ protected function setUp(): void ->willReturnCallback(function ($name) { return 'doctrine.orm.'.$name; }); + + $this->extension + ->method('getMappingObjectDefaultName') + ->willReturn('Entity'); } public function testFixManagersAutoMappingsWithTwoAutomappings() diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 86e7daa4e89ea..494e8835bb371 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -19,10 +19,10 @@ "php": ">=8.0.2", "doctrine/event-manager": "~1.0", "doctrine/persistence": "^2", - "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0" + "symfony/service-contracts": "^1.1|^2|^3" }, "require-dev": { "composer/package-versions-deprecated": "^1.8", diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index e73f8ca757d9d..1fd9424f683a9 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=8.0.2", "monolog/monolog": "^1.25.1|^2", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/http-kernel": "^5.4|^6.0" }, "require-dev": { diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index 7316abf0ddd12..34cbc76074acd 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -90,9 +90,6 @@ {%- if required -%} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} {%- endif -%} - {%- if parent_label_class is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|trim}) -%} - {%- endif -%} {%- if label is not same as(false) and label is empty -%} {%- if label_format is not empty -%} {%- set label = label_format|replace({ diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index fb440282861d8..0e80840541fa1 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -283,9 +283,6 @@ {%- if required -%} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} {%- endif -%} - {%- if parent_label_class is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|replace({'checkbox-inline': '', 'radio-inline': '', 'checkbox-custom': '', 'radio-custom': ''})|trim}) -%} - {%- endif -%} {%- if label is not same as(false) and label is empty -%} {%- if label_format is not empty -%} {%- set label = label_format|replace({ diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig index b02b94210d9be..f8c51b83dd8ed 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig @@ -253,9 +253,6 @@ {% if errors|length > 0 -%} {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %} {% endif %} - {% if parent_label_class is defined %} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ parent_label_class)|trim}) %} - {% endif %} {% if label is empty %} {%- if label_format is not empty -%} {% set label = label_format|replace({ diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 0b474b61be2ae..0765818346b6d 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/translation-contracts": "^1.1|^2.0|^3.0", + "symfony/translation-contracts": "^1.1|^2|^3", "twig/twig": "^2.13|^3.0.4" }, "require-dev": { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 866efbd4f7e89..18115870fa87e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -328,7 +328,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) $workflows = []; } - if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_marking', 'places', 'transitions']))) { + if (1 === \count($workflows) && isset($workflows['workflows']) && !array_is_list($workflows['workflows']) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_marking', 'places', 'transitions']))) { $workflows = $workflows['workflows']; } @@ -1251,7 +1251,7 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->ifString()->then(function ($v) { return ['default' => $v]; }) ->end() ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && array_keys($v) === range(0, \count($v) - 1); }) + ->ifTrue(function ($v) { return \is_array($v) && array_is_list($v); }) ->then(function ($v) { $resources = []; foreach ($v as $resource) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 96ae42c0ac18c..6b91858fde767 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -81,11 +81,9 @@ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\Lock\Lock; use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\PersistingStoreInterface; use Symfony\Component\Lock\Store\StoreFactory; -use Symfony\Component\Lock\StoreInterface; use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; @@ -1439,10 +1437,6 @@ 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 the PHP version is lower than 8 and Doctrine Annotations support is disabled. Consider upgrading PHP.'); - } - $validatorBuilder->addMethodCall('enableAnnotationMapping', [true]); if ($this->annotationsConfigEnabled) { $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]); @@ -1815,7 +1809,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $storeDefinitions = []; foreach ($resourceStores as $storeDsn) { $storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs); - $storeDefinition = new Definition(interface_exists(StoreInterface::class) ? StoreInterface::class : PersistingStoreInterface::class); + $storeDefinition = new Definition(PersistingStoreInterface::class); $storeDefinition->setFactory([StoreFactory::class, 'createStore']); $storeDefinition->setArguments([$storeDsn]); @@ -1838,12 +1832,6 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId)); $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition); - // Generate services for lock instances - $lockDefinition = new Definition(Lock::class); - $lockDefinition->setPublic(false); - $lockDefinition->setFactory([new Reference('lock.'.$resourceName.'.factory'), 'createLock']); - $lockDefinition->setArguments([$resourceName]); - // provide alias for default resource if ('default' === $resourceName) { $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/BaseBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/BaseBundle.php deleted file mode 100644 index 494a18dff0a14..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/BaseBundle.php +++ /dev/null @@ -1,18 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BaseBundle; - -use Symfony\Component\HttpKernel\Bundle\Bundle; - -class BaseBundle extends Bundle -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/base.format.engine b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/base.format.engine deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/controller/base.format.engine b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/controller/base.format.engine deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/this.is.a.template.format.engine b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/BaseBundle/Resources/views/this.is.a.template.format.engine deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 54cf9cc13307b..1d73dd97e57c0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -27,6 +27,7 @@ "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php81": "^1.22", "symfony/filesystem": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0" diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index b33136891809f..b2cd3fed196ba 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -154,6 +154,7 @@ public function addConfiguration(NodeDefinition $node) ->requiresAtLeastOneElement() ->info('An array of properties on your User that are used to sign the remember-me cookie. If any of these change, all existing cookies will become invalid.') ->example(['email', 'password']) + ->defaultValue(['password']) ->end() ->arrayNode('token_provider') ->beforeNormalization() diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 33285fc8f565d..ba479f2fbe832 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -4,8 +4,6 @@ {% block toolbar %} {% if collector.firewall %} - {% set color_code = collector.enabled and not collector.authenticatorManagerEnabled ? 'yellow' %} - {% set icon %} {{ include('@Security/Collector/icon.svg') }} {{ collector.user|default('n/a') }} @@ -85,7 +83,7 @@ {% endset %} - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: color_code }) }} + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }} {% endif %} {% endblock %} @@ -176,12 +174,6 @@ {{ include('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }} Stateless - {% if collector.authenticatorManagerEnabled == false %} -
- {{ include('@WebProfiler/Icon/' ~ (collector.firewall.allows_anonymous ? 'yes' : 'no') ~ '.svg') }} - Allows anonymous -
- {% endif %} {% if collector.firewall.security_enabled %} @@ -218,17 +210,10 @@ access_denied_url {{ collector.firewall.access_denied_url ?: '(none)' }} - {% if collector.authenticatorManagerEnabled %} - - authenticators - {{ collector.firewall.authenticators is empty ? '(none)' : profiler_dump(collector.firewall.authenticators, maxDepth=1) }} - - {% else %} - - listeners - {{ collector.firewall.listeners is empty ? '(none)' : profiler_dump(collector.firewall.listeners, maxDepth=1) }} - - {% endif %} + + authenticators + {{ collector.firewall.authenticators is empty ? '(none)' : profiler_dump(collector.firewall.authenticators, maxDepth=1) }} + {% endif %} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/UserChangingUserProvider.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/UserChangingUserProvider.php index f28bfff393693..c40a7e0a12267 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/UserChangingUserProvider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/UserChangingUserProvider.php @@ -21,6 +21,8 @@ class UserChangingUserProvider implements UserProviderInterface { private $inner; + public static $changePassword = false; + public function __construct(InMemoryUserProvider $inner) { $this->inner = $inner; @@ -28,26 +30,31 @@ public function __construct(InMemoryUserProvider $inner) public function loadUserByUsername($username): UserInterface { - return $this->inner->loadUserByUsername($username); + return $this->changeUser($this->inner->loadUserByUsername($username)); } public function loadUserByIdentifier(string $userIdentifier): UserInterface { - return $this->inner->loadUserByIdentifier($userIdentifier); + return $this->changeUser($this->inner->loadUserByIdentifier($userIdentifier)); } public function refreshUser(UserInterface $user): UserInterface { - $user = $this->inner->refreshUser($user); - - $alterUser = \Closure::bind(function (InMemoryUser $user) { $user->password = 'foo'; }, null, class_exists(User::class) ? User::class : InMemoryUser::class); - $alterUser($user); - - return $user; + return $this->changeUser($this->inner->refreshUser($user)); } public function supportsClass($class): bool { return $this->inner->supportsClass($class); } + + private function changeUser(UserInterface $user): UserInterface + { + if (self::$changePassword) { + $alterUser = \Closure::bind(function (InMemoryUser $user) { $user->password = 'changed!'; }, null, class_exists(User::class) ? User::class : InMemoryUser::class); + $alterUser($user); + } + + return $user; + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php index d9dd477b15b68..0ccc17d9c989d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php @@ -11,8 +11,15 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\RememberMeBundle\Security\UserChangingUserProvider; + class RememberMeTest extends AbstractWebTestCase { + protected function setUp(): void + { + UserChangingUserProvider::$changePassword = false; + } + /** * @dataProvider provideConfigs */ @@ -51,11 +58,19 @@ public function testUserChangeClearsCookie() $this->assertSame(302, $client->getResponse()->getStatusCode()); $cookieJar = $client->getCookieJar(); - $this->assertNotNull($cookieJar->get('REMEMBERME')); + $this->assertNotNull($cookie = $cookieJar->get('REMEMBERME')); + UserChangingUserProvider::$changePassword = true; + + // change password (through user provider), this deauthenticates the session $client->request('GET', '/profile'); $this->assertRedirect($client->getResponse(), '/login'); $this->assertNull($cookieJar->get('REMEMBERME')); + + // restore the old remember me cookie, it should no longer be valid + $cookieJar->set($cookie); + $client->request('GET', '/profile'); + $this->assertRedirect($client->getResponse(), '/login'); } public function testSessionLessRememberMeLogout() diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index f4e7877a26e0c..9f928c2c4fb57 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -27,7 +27,6 @@ "symfony/password-hasher": "^5.4|^6.0", "symfony/security-core": "^5.4|^6.0", "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-guard": "^5.4|^6.0", "symfony/security-http": "^5.4|^6.0" }, "require-dev": { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 4b234d24b354c..fbe3c0794314b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -409,6 +409,14 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { renderAjaxRequests: renderAjaxRequests, + getSfwdt: function(token) { + if (!this.sfwdt) { + this.sfwdt = document.getElementById('sfwdt' + token); + } + + return this.sfwdt; + }, + load: function(selector, url, onSuccess, onError, options) { var el = document.getElementById(selector); @@ -440,7 +448,7 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { }, showToolbar: function(token) { - var sfwdt = document.getElementById('sfwdt' + token); + var sfwdt = this.getSfwdt(token); removeClass(sfwdt, 'sf-display-none'); if (getPreference('toolbar/displayState') == 'none') { @@ -455,7 +463,7 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { }, hideToolbar: function(token) { - var sfwdt = document.getElementById('sfwdt' + token); + var sfwdt = this.getSfwdt(token); addClass(sfwdt, 'sf-display-none'); }, @@ -606,7 +614,7 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { }, function(xhr) { if (xhr.status !== 0 && !options.stop) { - var sfwdt = document.getElementById('sfwdt' + token); + var sfwdt = that.getSfwdt(token); sfwdt.innerHTML = '\
\
\ diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index fa5042cf3afb7..2326917ef1c90 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -32,6 +32,7 @@ }, "conflict": { "symfony/form": "<5.4", + "symfony/mailer": "<5.4", "symfony/messenger": "<5.4", "symfony/dependency-injection": "<5.4" }, diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php index 7bb16573db32f..b020ddc9f43a8 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php @@ -96,6 +96,7 @@ public function provideFailedCreateConnection(): array ['redis://localhost:1234'], ['redis://foo@localhost'], ['redis://localhost/123'], + ['redis:///some/local/path'], ]; } diff --git a/src/Symfony/Component/Cache/Tests/Fixtures/PrunableCache.php b/src/Symfony/Component/Cache/Tests/Fixtures/PrunableCache.php deleted file mode 100644 index c1b3f740129d8..0000000000000 --- a/src/Symfony/Component/Cache/Tests/Fixtures/PrunableCache.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Fixtures; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; - -abstract class PrunableCache implements CacheInterface, PruneableInterface -{ -} diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 1d8d512c38640..fc833beb7f23a 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -142,7 +142,7 @@ public static function createConnection(string $dsn, array $options = []): \Redi if (preg_match('#/(\d+)$#', $params['path'], $m)) { $params['dbindex'] = $m[1]; $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } else { + } elseif (isset($params['host'])) { throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s", the "dbindex" parameter must be a number.', $dsn)); } } diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 735a5fb3992c4..8969c33192055 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -24,8 +24,8 @@ "php": ">=8.0.2", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^1.1.7|^2.0|^3.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/cache-contracts": "^1.1.7|^2|^3", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/var-exporter": "^5.4|^6.0" }, "require-dev": { diff --git a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php index a157d25f96859..6381d70bb3674 100644 --- a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php +++ b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php @@ -119,14 +119,12 @@ private function computeHash(): string private function generateSignature(\ReflectionClass $class): iterable { - if (\PHP_VERSION_ID >= 80000) { - $attributes = []; - foreach ($class->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; + $attributes = []; + foreach ($class->getAttributes() as $a) { + $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; } + yield print_r($attributes, true); + $attributes = []; yield $class->getDocComment(); yield (int) $class->isFinal(); @@ -144,13 +142,11 @@ private function generateSignature(\ReflectionClass $class): iterable $defaults = $class->getDefaultProperties(); foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($p->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; + foreach ($p->getAttributes() as $a) { + $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; } + yield print_r($attributes, true); + $attributes = []; yield $p->getDocComment(); yield $p->isDefault() ? '' : ''; @@ -164,24 +160,20 @@ private function generateSignature(\ReflectionClass $class): iterable $defined = \Closure::bind(static function ($c) { return \defined($c); }, null, $class->name); foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($m->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; + foreach ($m->getAttributes() as $a) { + $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; } + yield print_r($attributes, true); + $attributes = []; $defaults = []; $parametersWithUndefinedConstants = []; foreach ($m->getParameters() as $p) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($p->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; + foreach ($p->getAttributes() as $a) { + $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; } + yield print_r($attributes, true); + $attributes = []; if (!$p->isDefaultValueAvailable()) { $defaults[$p->name] = null; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/ReceivingConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/ReceivingConfig.php new file mode 100644 index 0000000000000..b408fb1f32de9 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/ReceivingConfig.php @@ -0,0 +1,73 @@ +priority = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function color($value): static + { + $this->color = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['priority'])) { + $this->priority = $value['priority']; + unset($value['priority']); + } + + if (isset($value['color'])) { + $this->color = $value['color']; + unset($value['color']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->priority) { + $output['priority'] = $this->priority; + } + if (null !== $this->color) { + $output['color'] = $this->color; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/RoutingConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/RoutingConfig.php new file mode 100644 index 0000000000000..744ffd9c40ffb --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/Messenger/RoutingConfig.php @@ -0,0 +1,52 @@ + $value + * + * @return $this + */ + public function senders(ParamConfigurator|array $value): static + { + $this->senders = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['senders'])) { + $this->senders = $value['senders']; + unset($value['senders']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->senders) { + $output['senders'] = $this->senders; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/MessengerConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/MessengerConfig.php new file mode 100644 index 0000000000000..2189fde0f3bec --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/MessengerConfig.php @@ -0,0 +1,67 @@ +routing[$message_class])) { + return $this->routing[$message_class] = new \Symfony\Config\AddToList\Messenger\RoutingConfig($value); + } + if ([] === $value) { + return $this->routing[$message_class]; + } + + throw new InvalidConfigurationException('The node created by "routing()" has already been initialized. You cannot pass values the second time you call routing().'); + } + + public function receiving(array $value = []): \Symfony\Config\AddToList\Messenger\ReceivingConfig + { + return $this->receiving[] = new \Symfony\Config\AddToList\Messenger\ReceivingConfig($value); + } + + public function __construct(array $value = []) + { + + if (isset($value['routing'])) { + $this->routing = array_map(function ($v) { return new \Symfony\Config\AddToList\Messenger\RoutingConfig($v); }, $value['routing']); + unset($value['routing']); + } + + if (isset($value['receiving'])) { + $this->receiving = array_map(function ($v) { return new \Symfony\Config\AddToList\Messenger\ReceivingConfig($v); }, $value['receiving']); + unset($value['receiving']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->routing) { + $output['routing'] = array_map(function ($v) { return $v->toArray(); }, $this->routing); + } + if (null !== $this->receiving) { + $output['receiving'] = array_map(function ($v) { return $v->toArray(); }, $this->receiving); + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php new file mode 100644 index 0000000000000..10713b582cd49 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToList/TranslatorConfig.php @@ -0,0 +1,71 @@ + $value + * + * @return $this + */ + public function fallbacks(ParamConfigurator|array $value): static + { + $this->fallbacks = $value; + + return $this; + } + + /** + * @return $this + */ + public function source(string $source_class, mixed $value): static + { + $this->sources[$source_class] = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['fallbacks'])) { + $this->fallbacks = $value['fallbacks']; + unset($value['fallbacks']); + } + + if (isset($value['sources'])) { + $this->sources = $value['sources']; + unset($value['sources']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->fallbacks) { + $output['fallbacks'] = $this->fallbacks; + } + if (null !== $this->sources) { + $output['sources'] = $this->sources; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php new file mode 100644 index 0000000000000..679aa9bbc7fca --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/AddToList/Symfony/Config/AddToListConfig.php @@ -0,0 +1,77 @@ +translator) { + $this->translator = new \Symfony\Config\AddToList\TranslatorConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "translator()" has already been initialized. You cannot pass values the second time you call translator().'); + } + + return $this->translator; + } + + public function messenger(array $value = []): \Symfony\Config\AddToList\MessengerConfig + { + if (null === $this->messenger) { + $this->messenger = new \Symfony\Config\AddToList\MessengerConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "messenger()" has already been initialized. You cannot pass values the second time you call messenger().'); + } + + return $this->messenger; + } + + public function getExtensionAlias(): string + { + return 'add_to_list'; + } + + public function __construct(array $value = []) + { + + if (isset($value['translator'])) { + $this->translator = new \Symfony\Config\AddToList\TranslatorConfig($value['translator']); + unset($value['translator']); + } + + if (isset($value['messenger'])) { + $this->messenger = new \Symfony\Config\AddToList\MessengerConfig($value['messenger']); + unset($value['messenger']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->translator) { + $output['translator'] = $this->translator->toArray(); + } + if (null !== $this->messenger) { + $output['messenger'] = $this->messenger->toArray(); + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys.php index 453468330b26d..751fe5c2934cc 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys.php @@ -29,6 +29,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() ->end() + ->arrayNode('baz') + ->ignoreExtraKeys(false) + ->end() ; return $tb; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BarConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BarConfig.php new file mode 100644 index 0000000000000..4447d6db76984 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BarConfig.php @@ -0,0 +1,88 @@ +corge = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function grault($value): static + { + $this->grault = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['corge'])) { + $this->corge = $value['corge']; + unset($value['corge']); + } + + if (isset($value['grault'])) { + $this->grault = $value['grault']; + unset($value['grault']); + } + + $this->_extraKeys = $value; + + } + + public function toArray(): array + { + $output = []; + if (null !== $this->corge) { + $output['corge'] = $this->corge; + } + if (null !== $this->grault) { + $output['grault'] = $this->grault; + } + + return $output + $this->_extraKeys; + } + + /** + * @param ParamConfigurator|mixed $value + * + * @return $this + */ + public function set(string $key, mixed $value): static + { + if (null === $value) { + unset($this->_extraKeys[$key]); + } else { + $this->_extraKeys[$key] = $value; + } + + return $this; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BazConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BazConfig.php new file mode 100644 index 0000000000000..6ba4de7a56a2e --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/BazConfig.php @@ -0,0 +1,46 @@ +_extraKeys = $value; + + } + + public function toArray(): array + { + $output = []; + + return $output + $this->_extraKeys; + } + + /** + * @param ParamConfigurator|mixed $value + * + * @return $this + */ + public function set(string $key, mixed $value): static + { + if (null === $value) { + unset($this->_extraKeys[$key]); + } else { + $this->_extraKeys[$key] = $value; + } + + return $this; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/FooConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/FooConfig.php new file mode 100644 index 0000000000000..35cf66d3f169b --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeys/FooConfig.php @@ -0,0 +1,88 @@ +baz = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function qux($value): static + { + $this->qux = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['baz'])) { + $this->baz = $value['baz']; + unset($value['baz']); + } + + if (isset($value['qux'])) { + $this->qux = $value['qux']; + unset($value['qux']); + } + + $this->_extraKeys = $value; + + } + + public function toArray(): array + { + $output = []; + if (null !== $this->baz) { + $output['baz'] = $this->baz; + } + if (null !== $this->qux) { + $output['qux'] = $this->qux; + } + + return $output + $this->_extraKeys; + } + + /** + * @param ParamConfigurator|mixed $value + * + * @return $this + */ + public function set(string $key, mixed $value): static + { + if (null === $value) { + unset($this->_extraKeys[$key]); + } else { + $this->_extraKeys[$key] = $value; + } + + return $this; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeysConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeysConfig.php new file mode 100644 index 0000000000000..20ff730475f54 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayExtraKeys/Symfony/Config/ArrayExtraKeysConfig.php @@ -0,0 +1,92 @@ +foo) { + $this->foo = new \Symfony\Config\ArrayExtraKeys\FooConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "foo()" has already been initialized. You cannot pass values the second time you call foo().'); + } + + return $this->foo; + } + + public function bar(array $value = []): \Symfony\Config\ArrayExtraKeys\BarConfig + { + return $this->bar[] = new \Symfony\Config\ArrayExtraKeys\BarConfig($value); + } + + public function baz(array $value = []): \Symfony\Config\ArrayExtraKeys\BazConfig + { + if (null === $this->baz) { + $this->baz = new \Symfony\Config\ArrayExtraKeys\BazConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "baz()" has already been initialized. You cannot pass values the second time you call baz().'); + } + + return $this->baz; + } + + public function getExtensionAlias(): string + { + return 'array_extra_keys'; + } + + public function __construct(array $value = []) + { + + if (isset($value['foo'])) { + $this->foo = new \Symfony\Config\ArrayExtraKeys\FooConfig($value['foo']); + unset($value['foo']); + } + + if (isset($value['bar'])) { + $this->bar = array_map(function ($v) { return new \Symfony\Config\ArrayExtraKeys\BarConfig($v); }, $value['bar']); + unset($value['bar']); + } + + if (isset($value['baz'])) { + $this->baz = new \Symfony\Config\ArrayExtraKeys\BazConfig($value['baz']); + unset($value['baz']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->foo) { + $output['foo'] = $this->foo->toArray(); + } + if (null !== $this->bar) { + $output['bar'] = array_map(function ($v) { return $v->toArray(); }, $this->bar); + } + if (null !== $this->baz) { + $output['baz'] = $this->baz->toArray(); + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php new file mode 100644 index 0000000000000..e524f94e9c60b --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php @@ -0,0 +1,94 @@ +dsn = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function serializer($value): static + { + $this->serializer = $value; + + return $this; + } + + /** + * @param ParamConfigurator|list $value + * + * @return $this + */ + public function options(ParamConfigurator|array $value): static + { + $this->options = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['dsn'])) { + $this->dsn = $value['dsn']; + unset($value['dsn']); + } + + if (isset($value['serializer'])) { + $this->serializer = $value['serializer']; + unset($value['serializer']); + } + + if (isset($value['options'])) { + $this->options = $value['options']; + unset($value['options']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->dsn) { + $output['dsn'] = $this->dsn; + } + if (null !== $this->serializer) { + $output['serializer'] = $this->serializer; + } + if (null !== $this->options) { + $output['options'] = $this->options; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/MessengerConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/MessengerConfig.php new file mode 100644 index 0000000000000..8e59732f2d024 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/MessengerConfig.php @@ -0,0 +1,52 @@ +transports[$name])) { + return $this->transports[$name] = new \Symfony\Config\NodeInitialValues\Messenger\TransportsConfig($value); + } + if ([] === $value) { + return $this->transports[$name]; + } + + throw new InvalidConfigurationException('The node created by "transports()" has already been initialized. You cannot pass values the second time you call transports().'); + } + + public function __construct(array $value = []) + { + + if (isset($value['transports'])) { + $this->transports = array_map(function ($v) { return new \Symfony\Config\NodeInitialValues\Messenger\TransportsConfig($v); }, $value['transports']); + unset($value['transports']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->transports) { + $output['transports'] = array_map(function ($v) { return $v->toArray(); }, $this->transports); + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/SomeCleverNameConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/SomeCleverNameConfig.php new file mode 100644 index 0000000000000..25f6a01fe496a --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/SomeCleverNameConfig.php @@ -0,0 +1,73 @@ +first = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function second($value): static + { + $this->second = $value; + + return $this; + } + + public function __construct(array $value = []) + { + + if (isset($value['first'])) { + $this->first = $value['first']; + unset($value['first']); + } + + if (isset($value['second'])) { + $this->second = $value['second']; + unset($value['second']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->first) { + $output['first'] = $this->first; + } + if (null !== $this->second) { + $output['second'] = $this->second; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php new file mode 100644 index 0000000000000..d2f8bc654cfde --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValuesConfig.php @@ -0,0 +1,77 @@ +someCleverName) { + $this->someCleverName = new \Symfony\Config\NodeInitialValues\SomeCleverNameConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "someCleverName()" has already been initialized. You cannot pass values the second time you call someCleverName().'); + } + + return $this->someCleverName; + } + + public function messenger(array $value = []): \Symfony\Config\NodeInitialValues\MessengerConfig + { + if (null === $this->messenger) { + $this->messenger = new \Symfony\Config\NodeInitialValues\MessengerConfig($value); + } elseif ([] !== $value) { + throw new InvalidConfigurationException('The node created by "messenger()" has already been initialized. You cannot pass values the second time you call messenger().'); + } + + return $this->messenger; + } + + public function getExtensionAlias(): string + { + return 'node_initial_values'; + } + + public function __construct(array $value = []) + { + + if (isset($value['some_clever_name'])) { + $this->someCleverName = new \Symfony\Config\NodeInitialValues\SomeCleverNameConfig($value['some_clever_name']); + unset($value['some_clever_name']); + } + + if (isset($value['messenger'])) { + $this->messenger = new \Symfony\Config\NodeInitialValues\MessengerConfig($value['messenger']); + unset($value['messenger']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->someCleverName) { + $output['some_clever_name'] = $this->someCleverName->toArray(); + } + if (null !== $this->messenger) { + $output['messenger'] = $this->messenger->toArray(); + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/Placeholders/Symfony/Config/PlaceholdersConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/Placeholders/Symfony/Config/PlaceholdersConfig.php new file mode 100644 index 0000000000000..f05f40ce1eed6 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/Placeholders/Symfony/Config/PlaceholdersConfig.php @@ -0,0 +1,99 @@ +enabled = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|float $value + * @return $this + */ + public function favoriteFloat($value): static + { + $this->favoriteFloat = $value; + + return $this; + } + + /** + * @param ParamConfigurator|list $value + * + * @return $this + */ + public function goodIntegers(ParamConfigurator|array $value): static + { + $this->goodIntegers = $value; + + return $this; + } + + public function getExtensionAlias(): string + { + return 'placeholders'; + } + + public function __construct(array $value = []) + { + + if (isset($value['enabled'])) { + $this->enabled = $value['enabled']; + unset($value['enabled']); + } + + if (isset($value['favorite_float'])) { + $this->favoriteFloat = $value['favorite_float']; + unset($value['favorite_float']); + } + + if (isset($value['good_integers'])) { + $this->goodIntegers = $value['good_integers']; + unset($value['good_integers']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->enabled) { + $output['enabled'] = $this->enabled; + } + if (null !== $this->favoriteFloat) { + $output['favorite_float'] = $this->favoriteFloat; + } + if (null !== $this->goodIntegers) { + $output['good_integers'] = $this->goodIntegers; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/PrimitiveTypes/Symfony/Config/PrimitiveTypesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/PrimitiveTypes/Symfony/Config/PrimitiveTypesConfig.php new file mode 100644 index 0000000000000..313499b20cbb6 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/PrimitiveTypes/Symfony/Config/PrimitiveTypesConfig.php @@ -0,0 +1,141 @@ +booleanNode = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|'foo'|'bar'|'baz' $value + * @return $this + */ + public function enumNode($value): static + { + $this->enumNode = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|float $value + * @return $this + */ + public function floatNode($value): static + { + $this->floatNode = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|int $value + * @return $this + */ + public function integerNode($value): static + { + $this->integerNode = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|mixed $value + * @return $this + */ + public function scalarNode($value): static + { + $this->scalarNode = $value; + + return $this; + } + + public function getExtensionAlias(): string + { + return 'primitive_types'; + } + + public function __construct(array $value = []) + { + + if (isset($value['boolean_node'])) { + $this->booleanNode = $value['boolean_node']; + unset($value['boolean_node']); + } + + if (isset($value['enum_node'])) { + $this->enumNode = $value['enum_node']; + unset($value['enum_node']); + } + + if (isset($value['float_node'])) { + $this->floatNode = $value['float_node']; + unset($value['float_node']); + } + + if (isset($value['integer_node'])) { + $this->integerNode = $value['integer_node']; + unset($value['integer_node']); + } + + if (isset($value['scalar_node'])) { + $this->scalarNode = $value['scalar_node']; + unset($value['scalar_node']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->booleanNode) { + $output['boolean_node'] = $this->booleanNode; + } + if (null !== $this->enumNode) { + $output['enum_node'] = $this->enumNode; + } + if (null !== $this->floatNode) { + $output['float_node'] = $this->floatNode; + } + if (null !== $this->integerNode) { + $output['integer_node'] = $this->integerNode; + } + if (null !== $this->scalarNode) { + $output['scalar_node'] = $this->scalarNode; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/VariableType/Symfony/Config/VariableTypeConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/VariableType/Symfony/Config/VariableTypeConfig.php new file mode 100644 index 0000000000000..2ccd609255b17 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/VariableType/Symfony/Config/VariableTypeConfig.php @@ -0,0 +1,58 @@ +anyValue = $value; + + return $this; + } + + public function getExtensionAlias(): string + { + return 'variable_type'; + } + + public function __construct(array $value = []) + { + + if (isset($value['any_value'])) { + $this->anyValue = $value['any_value']; + unset($value['any_value']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (null !== $this->anyValue) { + $output['any_value'] = $this->anyValue; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php b/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php index 4089bacc97f26..e85558cac8d96 100644 --- a/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php +++ b/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php @@ -11,6 +11,8 @@ use Symfony\Component\Config\Tests\Builder\Fixtures\NodeInitialValues; use Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator; use Symfony\Config\AddToListConfig; /** @@ -20,6 +22,23 @@ */ class GeneratedConfigTest extends TestCase { + private $tempDir = []; + + protected function setup(): void + { + parent::setup(); + + $this->tempDir = []; + } + + protected function tearDown(): void + { + (new Filesystem())->remove($this->tempDir); + $this->tempDir = []; + + parent::tearDown(); + } + public function fixtureNames() { $array = [ @@ -49,11 +68,20 @@ public function fixtureNames() public function testConfig(string $name, string $alias) { $basePath = __DIR__.'/Fixtures/'; - $configBuilder = $this->generateConfigBuilder('Symfony\\Component\\Config\\Tests\\Builder\\Fixtures\\'.$name); $callback = include $basePath.$name.'.config.php'; $expectedOutput = include $basePath.$name.'.output.php'; + $expectedCode = $basePath.$name; + + // to regenerate snapshot files, uncomment these lines + // (new Filesystem())->remove($expectedCode); + // $configBuilder = $this->generateConfigBuilder('Symfony\\Component\\Config\\Tests\\Builder\\Fixtures\\'.$name, $expectedCode); + + $outputDir = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('sf_config_builder', true); + $configBuilder = $this->generateConfigBuilder('Symfony\\Component\\Config\\Tests\\Builder\\Fixtures\\'.$name, $outputDir); $callback($configBuilder); + $this->assertDirectorySame($expectedCode, $outputDir); + $this->assertInstanceOf(ConfigBuilderInterface::class, $configBuilder); $this->assertSame($alias, $configBuilder->getExtensionAlias()); $output = $configBuilder->toArray(); @@ -118,8 +146,13 @@ public function testSetExtraKeyMethodIsNotGeneratedWhenAllowExtraKeysIsFalse() /** * Generate the ConfigBuilder or return an already generated instance. */ - private function generateConfigBuilder(string $configurationClass) + private function generateConfigBuilder(string $configurationClass, string $outputDir = null) { + $outputDir ?? $outputDir = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('sf_config_builder', true); + if (!str_contains($outputDir, __DIR__)) { + $this->tempDir[] = $outputDir; + } + $configuration = new $configurationClass(); $rootNode = $configuration->getConfigTreeBuilder()->buildTree(); $rootClass = new ClassBuilder('Symfony\\Config', $rootNode->getName()); @@ -128,13 +161,31 @@ private function generateConfigBuilder(string $configurationClass) return new $fqcn(); } - $outputDir = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('sf_config_builder', true); - - // This line is helpful for debugging - // $outputDir = __DIR__.'/.build'; - $loader = (new ConfigBuilderGenerator($outputDir))->build(new $configurationClass()); return $loader(); } + + private function assertDirectorySame($expected, $current) + { + $expectedFiles = []; + foreach (new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($expected, \FilesystemIterator::SKIP_DOTS)) as $file) { + if ($file->isDir()) { + continue; + } + $expectedFiles[substr($file->getPathname(), \strlen($expected))] = $file->getPathname(); + } + $currentFiles = []; + foreach (new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($current, \FilesystemIterator::SKIP_DOTS)) as $file) { + if ($file->isDir()) { + continue; + } + $currentFiles[substr($file->getPathname(), \strlen($current))] = $file->getPathname(); + } + + $this->assertSame(array_keys($expectedFiles), array_keys($currentFiles)); + foreach ($expectedFiles as $fileName => $filePath) { + $this->assertFileEquals($filePath, $currentFiles[$fileName]); + } + } } diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index 1443ca95dd93c..c6d52a147a745 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -121,10 +121,7 @@ public function provideHashedSignature(): iterable { yield [false, 0, "// line change\n\n"]; yield [true, 0, '/** class docblock */']; - - if (\PHP_VERSION_ID >= 80000) { - yield [true, 0, '#[Foo]']; - } + yield [true, 0, '#[Foo]']; if (\PHP_VERSION_ID >= 80100) { yield [true, 0, '#[Foo(new MissingClass)]']; @@ -154,11 +151,8 @@ public function provideHashedSignature(): iterable yield [false, 11, "public function pub(\$arg = null) {\nreturn 123;\n}"]; yield [true, 12, '/** prot docblock */']; yield [true, 13, 'protected function prot($a = [123]) {}']; - - if (\PHP_VERSION_ID >= 80000) { - yield [true, 13, '#[Foo] protected function prot($a = []) {}']; - yield [true, 13, 'protected function prot(#[Foo] $a = []) {}']; - } + yield [true, 13, '#[Foo] protected function prot($a = []) {}']; + yield [true, 13, 'protected function prot(#[Foo] $a = []) {}']; if (\PHP_VERSION_ID >= 80100) { yield [true, 13, '#[Foo(new MissingClass)] protected function prot($a = []) {}']; diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index d03f53212ff41..1375ad83582a7 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/filesystem": "^5.4|^6.0", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-php81": "^1.22" @@ -26,7 +26,7 @@ "symfony/event-dispatcher": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/yaml": "^5.4|^6.0" }, "conflict": { diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index f47e01d7b2146..b582435f7d102 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -1037,7 +1037,7 @@ protected function getDefaultInputDefinition(): InputDefinition new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), - new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', false), + new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), ]); } diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index fe66897574b10..9a93c7991de89 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -27,6 +27,7 @@ CHANGELOG * Add support for bright colors * Add `#[AsCommand]` attribute for declaring commands on PHP 8 * Add `Helper::width()` and `Helper::length()` + * The `--ansi` and `--no-ansi` options now default to `null`. 5.2.0 ----- diff --git a/src/Symfony/Component/Console/Completion/CompletionSuggestions.php b/src/Symfony/Component/Console/Completion/CompletionSuggestions.php index e69c667101187..719118177f354 100644 --- a/src/Symfony/Component/Console/Completion/CompletionSuggestions.php +++ b/src/Symfony/Component/Console/Completion/CompletionSuggestions.php @@ -18,7 +18,7 @@ * * @author Wouter de Jong */ -class CompletionSuggestions +final class CompletionSuggestions { private $valueSuggestions = []; private $optionSuggestions = []; @@ -28,9 +28,9 @@ class CompletionSuggestions * * @return $this */ - public function suggestValue(string $value): static + public function suggestValue(string|Suggestion $value): static { - $this->valueSuggestions[] = $value; + $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value; return $this; } @@ -38,13 +38,15 @@ public function suggestValue(string $value): static /** * Add multiple suggested values at once for an input option or argument. * - * @param string[] $values + * @param list $values * * @return $this */ public function suggestValues(array $values): static { - $this->valueSuggestions = array_merge($this->valueSuggestions, $values); + foreach ($values as $value) { + $this->suggestValue($value); + } return $this; } @@ -86,7 +88,7 @@ public function getOptionSuggestions(): array } /** - * @return string[] + * @return Suggestion[] */ public function getValueSuggestions(): array { diff --git a/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php b/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php index cfe8415d1a2a0..8d5ffa6b67d4b 100644 --- a/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php +++ b/src/Symfony/Component/Console/Completion/Output/BashCompletionOutput.php @@ -21,10 +21,10 @@ class BashCompletionOutput implements CompletionOutputInterface { public function write(CompletionSuggestions $suggestions, OutputInterface $output): void { - $options = $suggestions->getValueSuggestions(); + $values = $suggestions->getValueSuggestions(); foreach ($suggestions->getOptionSuggestions() as $option) { - $options[] = '--'.$option->getName(); + $values[] = '--'.$option->getName(); } - $output->writeln(implode("\n", $options)); + $output->writeln(implode("\n", $values)); } } diff --git a/src/Symfony/Component/Console/Completion/Suggestion.php b/src/Symfony/Component/Console/Completion/Suggestion.php new file mode 100644 index 0000000000000..ff156f84ce7e3 --- /dev/null +++ b/src/Symfony/Component/Console/Completion/Suggestion.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion; + +/** + * Represents a single suggested value. + * + * @author Wouter de Jong + */ +class Suggestion +{ + private string $value; + + public function __construct(string $value) + { + $this->value = $value; + } + + public function getValue(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->getValue(); + } +} diff --git a/src/Symfony/Component/Console/README.md b/src/Symfony/Component/Console/README.md index c89b4a1a2066b..c4c129989cbd9 100644 --- a/src/Symfony/Component/Console/README.md +++ b/src/Symfony/Component/Console/README.md @@ -4,6 +4,18 @@ Console Component The Console component eases the creation of beautiful and testable command line interfaces. +Sponsor +------- + +The Console component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and +fix your projects. We provide a wide range of professional services including development, +consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps. +We are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -18,3 +30,7 @@ Credits `Resources/bin/hiddeninput.exe` is a third party binary provided within this component. Find sources and license at https://github.com/Seldaek/hidden-input. + +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Console/Tester/CommandCompletionTester.php b/src/Symfony/Component/Console/Tester/CommandCompletionTester.php index 95cec8982e70f..ade7327529c32 100644 --- a/src/Symfony/Component/Console/Tester/CommandCompletionTester.php +++ b/src/Symfony/Component/Console/Tester/CommandCompletionTester.php @@ -51,6 +51,6 @@ public function complete(array $input): array $options[] = '--'.$option->getName(); } - return array_merge($options, $suggestions->getValueSuggestions()); + return array_map('strval', array_merge($options, $suggestions->getValueSuggestions())); } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json index 8c8ba2285f59a..280a4247eb39f 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json @@ -63,7 +63,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -72,7 +72,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -175,7 +175,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -184,7 +184,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -287,7 +287,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -296,7 +296,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -390,7 +390,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -399,7 +399,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.md b/src/Symfony/Component/Console/Tests/Fixtures/application_1.md index dd88bef8724f6..98474874d2e59 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_1.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.md @@ -111,7 +111,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -222,7 +222,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -349,7 +349,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json index 172eaa310fb44..89171150ca858 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json @@ -67,7 +67,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -76,7 +76,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -179,7 +179,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -188,7 +188,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -291,7 +291,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -300,7 +300,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -394,7 +394,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -403,7 +403,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -482,7 +482,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -491,7 +491,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -578,7 +578,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -587,7 +587,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -655,7 +655,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -664,7 +664,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", @@ -734,7 +734,7 @@ "is_value_required": false, "is_multiple": false, "description": "Force (or disable --no-ansi) ANSI output", - "default": false + "default": null }, "no-ansi": { "name": "--no-ansi", @@ -743,7 +743,7 @@ "is_value_required": false, "is_multiple": false, "description": "Negate the \"--ansi\" option", - "default": false + "default": null }, "no-interaction": { "name": "--no-interaction", diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.md b/src/Symfony/Component/Console/Tests/Fixtures/application_2.md index f45be81999c5c..265e7117f21c9 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_2.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.md @@ -124,7 +124,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -235,7 +235,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -362,7 +362,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -437,7 +437,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -528,7 +528,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -600,7 +600,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_mbstring.md b/src/Symfony/Component/Console/Tests/Fixtures/application_mbstring.md index b64976d13a90c..2e6fc5f695b8a 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_mbstring.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_mbstring.md @@ -115,7 +115,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -226,7 +226,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -353,7 +353,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` @@ -444,7 +444,7 @@ Force (or disable --no-ansi) ANSI output * Is value required: no * Is multiple: no * Is negatable: yes -* Default: `false` +* Default: `NULL` #### `--no-interaction|-n` diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 9ecb8ffd1adc4..7d3947fcc7ec1 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=8.0.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.4|^6.0" }, "require-dev": { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php index d7d65a12ab992..e0054ef9d2e84 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php @@ -41,7 +41,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed $i = 0; $hasNamedArgs = false; foreach ($value->getArguments() as $k => $v) { - if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { + if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { $hasNamedArgs = true; continue; } @@ -79,7 +79,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed $i = 0; $hasNamedArgs = false; foreach ($methodCall[1] as $k => $v) { - if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { + if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { $hasNamedArgs = true; continue; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index fe4645147c49f..c91d9bdfade26 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -263,7 +263,7 @@ private function addServices(\DOMElement $parent) private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key') { - $withKeys = array_keys($parameters) !== range(0, \count($parameters) - 1); + $withKeys = !array_is_list($parameters); foreach ($parameters as $key => $value) { $element = $this->document->createElement($type); if ($withKeys) { diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 35ac8af647f30..192efbdb5adee 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -18,7 +18,8 @@ "require": { "php": ">=8.0.2", "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php81": "^1.22", "symfony/service-contracts": "^1.1.6|^2.0|^3.0" }, "require-dev": { diff --git a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php index b66adb61fe9a9..d0c9e8d47879c 100644 --- a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php +++ b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php @@ -130,7 +130,7 @@ public function __construct(callable $classLoader) $this->patchTypes += [ 'force' => null, 'php' => \PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION, - 'deprecations' => \PHP_VERSION_ID >= 70400, + 'deprecations' => true, ]; if ('phpdoc' === $this->patchTypes['force']) { @@ -878,7 +878,7 @@ private function normalizeType(string $type, string $class, ?string $parent, ?\R */ private function patchReturnTypeWillChange(\ReflectionMethod $method) { - if (\PHP_VERSION_ID >= 80000 && \count($method->getAttributes(\ReturnTypeWillChange::class))) { + if (\count($method->getAttributes(\ReturnTypeWillChange::class))) { return; } diff --git a/src/Symfony/Component/ErrorHandler/composer.json b/src/Symfony/Component/ErrorHandler/composer.json index 0ce12164fb844..d3cb8035f075b 100644 --- a/src/Symfony/Component/ErrorHandler/composer.json +++ b/src/Symfony/Component/ErrorHandler/composer.json @@ -23,7 +23,7 @@ "require-dev": { "symfony/http-kernel": "^5.4|^6.0", "symfony/serializer": "^5.4|^6.0", - "symfony/deprecation-contracts": "^2.1|^3.0" + "symfony/deprecation-contracts": "^2.1|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index 5106670b824f7..53a86ee9df7b9 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/event-dispatcher-contracts": "^2.0|^3.0" + "symfony/event-dispatcher-contracts": "^2|^3" }, "require-dev": { "symfony/dependency-injection": "^5.4|^6.0", @@ -25,7 +25,7 @@ "symfony/config": "^5.4|^6.0", "symfony/error-handler": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/stopwatch": "^5.4|^6.0", "psr/log": "^1|^2|^3" }, diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index c8dff7d489e64..473f5666de9f3 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=8.0.2", "symfony/cache": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0" + "symfony/service-contracts": "^1.1|^2|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index b88e1eeeba108..9bdf5a8778c91 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/options-resolver": "^5.4|^6.0", "symfony/polyfill-ctype": "~1.8", @@ -25,7 +25,7 @@ "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php81": "^1.23", "symfony/property-access": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0" + "symfony/service-contracts": "^1.1|^2|^3" }, "require-dev": { "doctrine/collections": "~1.0", diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 1a5b0a34a2c58..cecb1c0d9220d 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -488,7 +488,7 @@ private static function parseUrl(string $url, array $query = [], array $allowedS throw new InvalidArgumentException(sprintf('Unsupported IDN "%s", try enabling the "intl" PHP extension or running "composer require symfony/polyfill-intl-idn".', $host)); } - $host = \defined('INTL_IDNA_VARIANT_UTS46') ? idn_to_ascii($host, \IDNA_DEFAULT, \INTL_IDNA_VARIANT_UTS46) ?: strtolower($host) : strtolower($host); + $host = \defined('INTL_IDNA_VARIANT_UTS46') ? idn_to_ascii($host, \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46) ?: strtolower($host) : strtolower($host); $host .= $port ? ':'.$port : ''; } diff --git a/src/Symfony/Component/HttpClient/README.md b/src/Symfony/Component/HttpClient/README.md index 214489b7e7f76..0c55ccc118876 100644 --- a/src/Symfony/Component/HttpClient/README.md +++ b/src/Symfony/Component/HttpClient/README.md @@ -3,6 +3,16 @@ HttpClient component The HttpClient component provides powerful methods to fetch HTTP resources synchronously or asynchronously. +Sponsor +------- + +The Httpclient component for Symfony 5.4/6.0 is [backed][1] by [Klaxoon][2]. + +Klaxoon is a platform that empowers organizations to run effective and +productive workshops easily in a hybrid environment. Anytime, Anywhere. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -11,3 +21,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://klaxoon.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php index cc44e9d5625cd..b811626c0c670 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php @@ -163,6 +163,8 @@ public function provideParseUrl(): iterable yield [[null, null, 'bar', '?a%5Bb%5Bc%5D=d', null], 'bar?a[b[c]=d', []]; yield [[null, null, 'bar', '?a%5Bb%5D%5Bc%5D=dd', null], 'bar?a[b][c]=d&e[f]=g', ['a' => ['b' => ['c' => 'dd']], 'e[f]' => null]]; yield [[null, null, 'bar', '?a=b&a%5Bb%20c%5D=d&e%3Df=%E2%9C%93', null], 'bar?a=b', ['a' => ['b c' => 'd'], 'e=f' => '✓']]; + // IDNA 2008 compliance + yield [['https:', '//xn--fuball-cta.test', null, null, null], 'https://fußball.test']; } /** diff --git a/src/Symfony/Component/HttpClient/composer.json b/src/Symfony/Component/HttpClient/composer.json index f33147e61660c..02a7653b52902 100644 --- a/src/Symfony/Component/HttpClient/composer.json +++ b/src/Symfony/Component/HttpClient/composer.json @@ -23,8 +23,8 @@ "require": { "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/http-client-contracts": "^3.0", - "symfony/service-contracts": "^1.0|^2.0|^3.0" + "symfony/http-client-contracts": "^3", + "symfony/service-contracts": "^1.0|^2|^3" }, "require-dev": { "amphp/amp": "^2.5", diff --git a/src/Symfony/Component/HttpFoundation/README.md b/src/Symfony/Component/HttpFoundation/README.md index 5cf9007444456..424f2c4f0b848 100644 --- a/src/Symfony/Component/HttpFoundation/README.md +++ b/src/Symfony/Component/HttpFoundation/README.md @@ -4,6 +4,16 @@ HttpFoundation Component The HttpFoundation component defines an object-oriented layer for the HTTP specification. +Sponsor +------- + +The HttpFoundation component for Symfony 5.4/6.0 is [backed][1] by [Laravel][2]. + +Laravel is a PHP web development framework that is passionate about maximum developer +happiness. Laravel is built using a variety of bespoke and Symfony based components. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -12,3 +22,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://laravel.com/ +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index f4a95ba147638..9f5cccc65a8a2 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3.0", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { diff --git a/src/Symfony/Component/HttpKernel/HttpCache/SubRequestHandler.php b/src/Symfony/Component/HttpKernel/HttpCache/SubRequestHandler.php index a453e432be80d..253071f07da7b 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/SubRequestHandler.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/SubRequestHandler.php @@ -38,6 +38,7 @@ public static function handle(HttpKernelInterface $kernel, Request $request, int 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, + 'X_FORWARDED_PREFIX' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PREFIX, ]; foreach (array_filter($trustedHeaders) as $name => $key) { $request->headers->remove($name); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index c5583e49738d0..4fdfde448b00b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.0.0-BETA3'; + public const VERSION = '6.0.0-RC1'; public const VERSION_ID = 60000; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 0; public const RELEASE_VERSION = 0; - public const EXTRA_VERSION = 'BETA3'; + public const EXTRA_VERSION = 'RC1'; public const END_OF_MAINTENANCE = '07/2022'; public const END_OF_LIFE = '07/2022'; diff --git a/src/Symfony/Component/HttpKernel/README.md b/src/Symfony/Component/HttpKernel/README.md index 18d15f5ad835f..ca504178278c4 100644 --- a/src/Symfony/Component/HttpKernel/README.md +++ b/src/Symfony/Component/HttpKernel/README.md @@ -5,6 +5,18 @@ The HttpKernel component provides a structured process for converting a Request into a Response by making use of the EventDispatcher component. It's flexible enough to create full-stack frameworks, micro-frameworks or advanced CMS systems like Drupal. +Sponsor +------- + +The HttpKernel component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and +fix your projects. We provide a wide range of professional services including development, +consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps. +We are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -13,3 +25,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SubRequestHandlerTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SubRequestHandlerTest.php index 7ab9b6c45f037..f17abb20281f3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SubRequestHandlerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SubRequestHandlerTest.php @@ -42,6 +42,7 @@ public function testTrustedHeadersAreKept() $request->headers->set('X-Forwarded-Host', 'Good'); $request->headers->set('X-Forwarded-Port', '1234'); $request->headers->set('X-Forwarded-Proto', 'https'); + $request->headers->set('X-Forwarded-Prefix', '/admin'); $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); @@ -49,6 +50,7 @@ public function testTrustedHeadersAreKept() $this->assertSame('Good', $request->headers->get('X-Forwarded-Host')); $this->assertSame('1234', $request->headers->get('X-Forwarded-Port')); $this->assertSame('https', $request->headers->get('X-Forwarded-Proto')); + $this->assertSame('/admin', $request->headers->get('X-Forwarded-Prefix')); }); SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true); @@ -64,6 +66,7 @@ public function testUntrustedHeadersAreRemoved() $request->headers->set('X-Forwarded-Host', 'Evil'); $request->headers->set('X-Forwarded-Port', '1234'); $request->headers->set('X-Forwarded-Proto', 'http'); + $request->headers->set('X-Forwarded-Prefix', '/admin'); $request->headers->set('Forwarded', 'Evil2'); $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { @@ -72,6 +75,7 @@ public function testUntrustedHeadersAreRemoved() $this->assertFalse($request->headers->has('X-Forwarded-Host')); $this->assertFalse($request->headers->has('X-Forwarded-Port')); $this->assertFalse($request->headers->has('X-Forwarded-Proto')); + $this->assertFalse($request->headers->has('X-Forwarded-Prefix')); $this->assertSame('for="10.0.0.1";host="localhost";proto=http', $request->headers->get('Forwarded')); }); @@ -112,12 +116,14 @@ public function testTrustedXForwardedForHeader() $request->headers->set('X-Forwarded-For', '10.0.0.2'); $request->headers->set('X-Forwarded-Host', 'foo.bar'); $request->headers->set('X-Forwarded-Proto', 'https'); + $request->headers->set('X-Forwarded-Prefix', '/admin'); $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); $this->assertSame('10.0.0.2', $request->getClientIp()); $this->assertSame('foo.bar', $request->getHttpHost()); $this->assertSame('https', $request->getScheme()); + $this->assertSame('/admin', $request->getBaseUrl()); }); SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true); diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 4a6c6f0e1f87e..e28f8585624e7 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -19,7 +19,6 @@ "php": ">=8.0.2", "symfony/error-handler": "^5.4|^6.0", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", "symfony/http-foundation": "^5.4|^6.0", "symfony/polyfill-ctype": "^1.8", "psr/log": "^1|^2|^3" @@ -33,11 +32,12 @@ "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2|^3", "symfony/process": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0", "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2.0|^3.0", + "symfony/translation-contracts": "^1.1|^2|^3", "psr/cache": "^1.0|^2.0|^3.0", "twig/twig": "^2.13|^3.0.4" }, diff --git a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php index 6c54071bd0c09..56f9eefc5f992 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php @@ -30,6 +30,7 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; +use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; use Symfony\Component\Security\Http\Event\CheckPassportEvent; use Symfony\Contracts\Service\ServiceLocatorTrait; @@ -215,7 +216,10 @@ public function authenticate(Request $request): Passport { } - public function createAuthenticatedToken(Passport $passport, string $firewallName): TokenInterface + /** + * @internal for compatibility with Symfony 5.4 + */ + public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface { } diff --git a/src/Symfony/Component/Mailer/Bridge/Google/Tests/Transport/GmailTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Google/Tests/Transport/GmailTransportFactoryTest.php index ff9e41058434f..51f0b3ba0f0f0 100644 --- a/src/Symfony/Component/Mailer/Bridge/Google/Tests/Transport/GmailTransportFactoryTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Google/Tests/Transport/GmailTransportFactoryTest.php @@ -12,7 +12,7 @@ class GmailTransportFactoryTest extends TransportFactoryTestCase { public function getFactory(): TransportFactoryInterface { - return new GmailTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + return new GmailTransportFactory($this->getDispatcher(), null, $this->getLogger()); } public function supportsProvider(): iterable diff --git a/src/Symfony/Component/Mailer/Bridge/Google/composer.json b/src/Symfony/Component/Mailer/Bridge/Google/composer.json index fa6245f880046..6ff31d950ff8c 100644 --- a/src/Symfony/Component/Mailer/Bridge/Google/composer.json +++ b/src/Symfony/Component/Mailer/Bridge/Google/composer.json @@ -19,9 +19,6 @@ "php": ">=8.0.2", "symfony/mailer": "^5.4|^6.0" }, - "require-dev": { - "symfony/http-client": "^5.4|^6.0" - }, "autoload": { "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Google\\": "" }, "exclude-from-classmap": [ diff --git a/src/Symfony/Component/Mailer/composer.json b/src/Symfony/Component/Mailer/composer.json index 271fdf45377e0..bd6d83ce5613a 100644 --- a/src/Symfony/Component/Mailer/composer.json +++ b/src/Symfony/Component/Mailer/composer.json @@ -22,10 +22,10 @@ "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/mime": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0" + "symfony/service-contracts": "^1.1|^2|^3" }, "require-dev": { - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-client-contracts": "^1.1|^2|^3", "symfony/messenger": "^5.4|^6.0" }, "conflict": { diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json index 96b56333192fe..d2e2f5ddf70bd 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json @@ -20,11 +20,11 @@ "async-aws/core": "^1.5", "async-aws/sqs": "^1.0", "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "psr/log": "^1|^2|^3" }, "require-dev": { - "symfony/http-client-contracts": "^1.0|^2.0|^3.0", + "symfony/http-client-contracts": "^1|^2|^3", "symfony/property-access": "^5.4|^6.0", "symfony/serializer": "^5.4|^6.0" }, diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json b/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json index 3246dc95b5680..590d5a49ee43e 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json @@ -19,7 +19,7 @@ "php": ">=8.0.2", "doctrine/dbal": "^2.13|^3.0", "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0" + "symfony/service-contracts": "^1.1|^2|^3" }, "require-dev": { "doctrine/persistence": "^1.3|^2", diff --git a/src/Symfony/Component/Messenger/README.md b/src/Symfony/Component/Messenger/README.md index a253171a5529c..644269c7f34a1 100644 --- a/src/Symfony/Component/Messenger/README.md +++ b/src/Symfony/Component/Messenger/README.md @@ -4,6 +4,17 @@ Messenger Component The Messenger component helps applications send and receive messages to/from other applications or via message queues. +Sponsor +------- + +The Messenger component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. + +As the creator of Symfony, SensioLabs supports companies using Symfony, with an +offering encompassing consultancy, expertise, services, training, and technical +assistance to ensure the success of web application development projects. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -12,3 +23,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://sensiolabs.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Messenger/composer.json b/src/Symfony/Component/Messenger/composer.json index 961d45046ddc0..0b74341fe269b 100644 --- a/src/Symfony/Component/Messenger/composer.json +++ b/src/Symfony/Component/Messenger/composer.json @@ -29,7 +29,7 @@ "symfony/property-access": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0", "symfony/serializer": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2.0|^3.0", + "symfony/service-contracts": "^1.1|^2|^3", "symfony/stopwatch": "^5.4|^6.0", "symfony/validator": "^5.4|^6.0" }, diff --git a/src/Symfony/Component/Mime/Encoder/IdnAddressEncoder.php b/src/Symfony/Component/Mime/Encoder/IdnAddressEncoder.php index a14035ba794b9..b56e7e3963010 100644 --- a/src/Symfony/Component/Mime/Encoder/IdnAddressEncoder.php +++ b/src/Symfony/Component/Mime/Encoder/IdnAddressEncoder.php @@ -35,7 +35,7 @@ public function encodeString(string $address): string $domain = substr($address, $i + 1); if (preg_match('/[^\x00-\x7F]/', $domain)) { - $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, \INTL_IDNA_VARIANT_UTS46)); + $address = sprintf('%s@%s', $local, idn_to_ascii($domain, \IDNA_DEFAULT | \IDNA_USE_STD3_RULES | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ | \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46)); } } diff --git a/src/Symfony/Component/Mime/Tests/Encoder/IdnAddressEncoderTest.php b/src/Symfony/Component/Mime/Tests/Encoder/IdnAddressEncoderTest.php new file mode 100644 index 0000000000000..71e7716f8961b --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/Encoder/IdnAddressEncoderTest.php @@ -0,0 +1,13 @@ +assertSame('test@xn--fuball-cta.test', (new IdnAddressEncoder())->encodeString('test@fußball.test')); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/FakeChat/composer.json b/src/Symfony/Component/Notifier/Bridge/FakeChat/composer.json index bd0b595b9a7e2..c468fdc955301 100644 --- a/src/Symfony/Component/Notifier/Bridge/FakeChat/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/FakeChat/composer.json @@ -24,7 +24,7 @@ "php": ">=8.0.2", "symfony/http-client": "^5.4|^6.0", "symfony/notifier": "^5.4|^6.0", - "symfony/event-dispatcher-contracts": "^2.0|^3.0", + "symfony/event-dispatcher-contracts": "^2|^3", "symfony/mailer": "^5.4|^6.0" }, "autoload": { diff --git a/src/Symfony/Component/Notifier/Bridge/FakeSms/composer.json b/src/Symfony/Component/Notifier/Bridge/FakeSms/composer.json index ca4de1571db02..ef4daeb1c0c75 100644 --- a/src/Symfony/Component/Notifier/Bridge/FakeSms/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/FakeSms/composer.json @@ -24,7 +24,7 @@ "php": ">=8.0.2", "symfony/http-client": "^5.4|^6.0", "symfony/notifier": "^5.4|^6.0", - "symfony/event-dispatcher-contracts": "^2.0|^3.0", + "symfony/event-dispatcher-contracts": "^2|^3", "symfony/mailer": "^5.4|^6.0" }, "autoload": { diff --git a/src/Symfony/Component/Notifier/Bridge/Mercure/composer.json b/src/Symfony/Component/Notifier/Bridge/Mercure/composer.json index 31b33f014c6f4..06082a225bfa3 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mercure/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Mercure/composer.json @@ -20,7 +20,7 @@ "ext-json": "*", "symfony/mercure": "^0.5.2", "symfony/notifier": "^5.4|^6.0", - "symfony/service-contracts": "^1.10|^2.0|^3.0" + "symfony/service-contracts": "^1.10|^2|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Mercure\\": "" }, diff --git a/src/Symfony/Component/Notifier/README.md b/src/Symfony/Component/Notifier/README.md index 79e516f69871d..4a9631653841e 100644 --- a/src/Symfony/Component/Notifier/README.md +++ b/src/Symfony/Component/Notifier/README.md @@ -3,6 +3,19 @@ Notifier Component The Notifier component sends notifications via one or more channels (email, SMS, ...). +Sponsor +------- + +The Notifier component for Symfony 5.4/6.0 is [backed][1] by [Mercure.rocks][2]. + +Create real-time experiences in minutes! Mercure.rocks provides a realtime API service +that is tightly integrated with Symfony: create UIs that update in live with UX Turbo, +send notifications with the Notifier component, expose async APIs with API Platform and +create low level stuffs with the Mercure component. We maintain and scale the complex +infrastructure for you! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -11,3 +24,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://mercure.rocks +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Notifier/composer.json b/src/Symfony/Component/Notifier/composer.json index fe512a4363d0c..b75a8bc5a0fa1 100644 --- a/src/Symfony/Component/Notifier/composer.json +++ b/src/Symfony/Component/Notifier/composer.json @@ -20,8 +20,8 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "symfony/event-dispatcher-contracts": "^2.0|^3.0", - "symfony/http-client-contracts": "^2.0|^3.0", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/http-client-contracts": "^2|^3", "symfony/messenger": "^5.4|^6.0" }, "conflict": { diff --git a/src/Symfony/Component/OptionsResolver/composer.json b/src/Symfony/Component/OptionsResolver/composer.json index eadee6ca4d66a..4fd80d95f6f91 100644 --- a/src/Symfony/Component/OptionsResolver/composer.json +++ b/src/Symfony/Component/OptionsResolver/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3.0" + "symfony/deprecation-contracts": "^2.1|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 7fab232566011..987259d39ab92 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -335,7 +335,7 @@ public function start(callable $callback = null, array $env = []) $envPairs = []; foreach ($env as $k => $v) { - if (false !== $v) { + if (false !== $v && 'argc' !== $k && 'argv' !== $k) { $envPairs[] = $k.'='.$v; } } @@ -1089,25 +1089,12 @@ public function getEnv(): array /** * Sets the environment variables. * - * Each environment variable value should be a string. - * If it is an array, the variable is ignored. - * If it is false or null, it will be removed when - * env vars are otherwise inherited. - * - * That happens in PHP when 'argv' is registered into - * the $_ENV array for instance. - * - * @param array $env The new environment variables + * @param array $env The new environment variables * * @return $this */ public function setEnv(array $env): static { - // Process cannot handle env values that are arrays - $env = array_filter($env, function ($value) { - return !\is_array($value); - }); - $this->env = $env; return $this; @@ -1602,12 +1589,6 @@ private function getDefaultEnv(): array $env = getenv(); $env = array_intersect_key($env, $_SERVER) ?: $env; - foreach ($_ENV as $k => $v) { - if (\is_string($v)) { - $env[$k] = $v; - } - } - - return $env; + return $_ENV + $env; } } diff --git a/src/Symfony/Component/Process/README.md b/src/Symfony/Component/Process/README.md index afce5e45eee34..8777de4a65c52 100644 --- a/src/Symfony/Component/Process/README.md +++ b/src/Symfony/Component/Process/README.md @@ -3,6 +3,17 @@ Process Component The Process component executes commands in sub-processes. +Sponsor +------- + +The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. + +As the creator of Symfony, SensioLabs supports companies using Symfony, with an +offering encompassing consultancy, expertise, services, training, and technical +assistance to ensure the success of web application development projects. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -11,3 +22,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://sensiolabs.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Security/Core/README.md b/src/Symfony/Component/Security/Core/README.md index 6b3e5c990107c..b47ab331c82b3 100644 --- a/src/Symfony/Component/Security/Core/README.md +++ b/src/Symfony/Component/Security/Core/README.md @@ -6,6 +6,17 @@ which makes it possible to easily separate the actual authorization logic from so called user providers that hold the users credentials. It is inspired by the Java Spring framework. +Sponsor +------- + +The Security component for Symfony 5.4/6.0 is [backed][1] by [SymfonyCasts][2]. + +Learn Symfony faster by watching real projects being built and actively coding +along with them. SymfonyCasts bridges that learning gap, bringing you video +tutorials and coding challenges. Code on! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -14,3 +25,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://symfonycasts.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php index 03cc6d17e89ed..056123f644baa 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php @@ -94,66 +94,6 @@ public function testSetUser($user) } } -class TestUser -{ - protected $name; - - public function __construct($name) - { - $this->name = $name; - } - - public function __toString(): string - { - return $this->name; - } -} - -class SerializableUser implements UserInterface -{ - private $roles; - private $name; - - public function __construct($name, array $roles = []) - { - $this->name = $name; - $this->roles = $roles; - } - - public function getUsername(): string - { - return $this->name; - } - - public function getUserIdentifier(): string - { - return $this->name; - } - - public function getPassword(): ?string - { - return '***'; - } - - public function getRoles(): array - { - if (empty($this->roles)) { - return ['ROLE_USER']; - } - - return $this->roles; - } - - public function eraseCredentials() - { - } - - public function getSalt(): ?string - { - return null; - } -} - class ConcreteToken extends AbstractToken { private $credentials = 'credentials_value'; diff --git a/src/Symfony/Component/Security/Core/Tests/SecurityTest.php b/src/Symfony/Component/Security/Core/Tests/SecurityTest.php index 53dd23b20b175..064998f97293e 100644 --- a/src/Symfony/Component/Security/Core/Tests/SecurityTest.php +++ b/src/Symfony/Component/Security/Core/Tests/SecurityTest.php @@ -93,11 +93,3 @@ private function createContainer($serviceId, $serviceObject) return $container; } } - -class StringishUser -{ - public function __toString(): string - { - return 'stringish_user'; - } -} diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index de0dbd21568b2..20c5074d6eb90 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -17,8 +17,8 @@ ], "require": { "php": ">=8.0.2", - "symfony/event-dispatcher-contracts": "^1.1|^2.0|^3.0", - "symfony/service-contracts": "^1.1.6|^2.0|^3.0", + "symfony/event-dispatcher-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^1.1.6|^2|^3", "symfony/password-hasher": "^5.4|^6.0" }, "require-dev": { diff --git a/src/Symfony/Component/Security/Csrf/README.md b/src/Symfony/Component/Security/Csrf/README.md index 8933061585ff9..a27d877284343 100644 --- a/src/Symfony/Component/Security/Csrf/README.md +++ b/src/Symfony/Component/Security/Csrf/README.md @@ -4,6 +4,17 @@ Security Component - CSRF The Security CSRF (cross-site request forgery) component provides a class `CsrfTokenManager` for generating and validating CSRF tokens. +Sponsor +------- + +The Security component for Symfony 5.4/6.0 is [backed][1] by [SymfonyCasts][2]. + +Learn Symfony faster by watching real projects being built and actively coding +along with them. SymfonyCasts bridges that learning gap, bringing you video +tutorials and coding challenges. Code on! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -12,3 +23,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://symfonycasts.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Security/Http/README.md b/src/Symfony/Component/Security/Http/README.md index e12d19fbeb697..594f5adb3aece 100644 --- a/src/Symfony/Component/Security/Http/README.md +++ b/src/Symfony/Component/Security/Http/README.md @@ -6,6 +6,17 @@ which makes it possible to easily separate the actual authorization logic from so called user providers that hold the users credentials. It is inspired by the Java Spring framework. +Sponsor +------- + +The Security component for Symfony 5.4/6.0 is [backed][1] by [SymfonyCasts][2]. + +Learn Symfony faster by watching real projects being built and actively coding +along with them. SymfonyCasts bridges that learning gap, bringing you video +tutorials and coding challenges. Code on! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -14,3 +25,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://symfonycasts.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Security/Http/Tests/Authenticator/AbstractAuthenticatorTest.php b/src/Symfony/Component/Security/Http/Tests/Authenticator/AbstractAuthenticatorTest.php index 202a7ee2a9f9c..9562589581b5e 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authenticator/AbstractAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authenticator/AbstractAuthenticatorTest.php @@ -43,11 +43,6 @@ public function createToken(Passport $passport, string $firewallName): TokenInte return parent::createToken($passport, $firewallName); } - public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface - { - return parent::createAuthenticatedToken($passport, $firewallName); - } - public function supports(Request $request): ?bool { return null; diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 4b45a1ffc91cc..cee61fa03a680 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -36,7 +36,8 @@ class CsvEncoder implements EncoderInterface, DecoderInterface private const UTF8_BOM = "\xEF\xBB\xBF"; - private $formulasStartCharacters = ['=', '-', '+', '@']; + private const FORMULAS_START_CHARACTERS = ['=', '-', '+', '@', "\t", "\r"]; + private $defaultContext = [ self::DELIMITER_KEY => ',', self::ENCLOSURE_KEY => '"', @@ -223,8 +224,8 @@ private function flatten(iterable $array, array &$result, string $keySeparator, if (is_iterable($value)) { $this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator, $escapeFormulas); } else { - if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), $this->formulasStartCharacters, true)) { - $result[$parentKey.$key] = "\t".$value; + if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), self::FORMULAS_START_CHARACTERS, true)) { + $result[$parentKey.$key] = "'".$value; } else { // Ensures an actual value is used when dealing with true and false $result[$parentKey.$key] = false === $value ? 0 : (true === $value ? 1 : $value); diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index 8656a400027b3..87589ee89e64a 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -114,7 +114,7 @@ protected function extractAttributes(object $object, string $format = null, arra } } while ($reflectionObject = $reflectionObject->getParentClass()); - return $attributes; + return array_unique($attributes); } /** diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index c66366a985efa..8752acffc8be8 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -251,31 +251,52 @@ public function testEncodeFormulas() $this->assertSame(<<<'CSV' 0 -" =2+3" +'=2+3 CSV , $this->encoder->encode(['=2+3'], 'csv')); $this->assertSame(<<<'CSV' 0 -" -2+3" +'-2+3 CSV , $this->encoder->encode(['-2+3'], 'csv')); $this->assertSame(<<<'CSV' 0 -" +2+3" +'+2+3 CSV , $this->encoder->encode(['+2+3'], 'csv')); $this->assertSame(<<<'CSV' 0 -" @MyDataColumn" +'@MyDataColumn CSV , $this->encoder->encode(['@MyDataColumn'], 'csv')); + + $this->assertSame(<<<'CSV' +0 +"' tab" + +CSV + , $this->encoder->encode(["\ttab"], 'csv')); + + $this->assertSame(<<<'CSV' +0 +"'=1+2"";=1+2" + +CSV + , $this->encoder->encode(['=1+2";=1+2'], 'csv')); + + $this->assertSame(<<<'CSV' +0 +"'=1+2'"" ;,=1+2" + +CSV + , $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv')); } public function testDoNotEncodeFormulas() @@ -307,13 +328,34 @@ public function testDoNotEncodeFormulas() CSV , $this->encoder->encode(['@MyDataColumn'], 'csv')); + + $this->assertSame(<<<'CSV' +0 +" tab" + +CSV + , $this->encoder->encode(["\ttab"], 'csv')); + + $this->assertSame(<<<'CSV' +0 +"=1+2"";=1+2" + +CSV + , $this->encoder->encode(['=1+2";=1+2'], 'csv')); + + $this->assertSame(<<<'CSV' +0 +"=1+2'"" ;,=1+2" + +CSV + , $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv')); } public function testEncodeFormulasWithSettingsPassedInContext() { $this->assertSame(<<<'CSV' 0 -" =2+3" +'=2+3 CSV , $this->encoder->encode(['=2+3'], 'csv', [ @@ -322,7 +364,7 @@ public function testEncodeFormulasWithSettingsPassedInContext() $this->assertSame(<<<'CSV' 0 -" -2+3" +'-2+3 CSV , $this->encoder->encode(['-2+3'], 'csv', [ @@ -331,7 +373,7 @@ public function testEncodeFormulasWithSettingsPassedInContext() $this->assertSame(<<<'CSV' 0 -" +2+3" +'+2+3 CSV , $this->encoder->encode(['+2+3'], 'csv', [ @@ -340,12 +382,39 @@ public function testEncodeFormulasWithSettingsPassedInContext() $this->assertSame(<<<'CSV' 0 -" @MyDataColumn" +'@MyDataColumn CSV , $this->encoder->encode(['@MyDataColumn'], 'csv', [ CsvEncoder::ESCAPE_FORMULAS_KEY => true, ])); + + $this->assertSame(<<<'CSV' +0 +"' tab" + +CSV + , $this->encoder->encode(["\ttab"], 'csv', [ + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ])); + + $this->assertSame(<<<'CSV' +0 +"'=1+2"";=1+2" + +CSV + , $this->encoder->encode(['=1+2";=1+2'], 'csv', [ + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ])); + + $this->assertSame(<<<'CSV' +0 +"'=1+2'"" ;,=1+2" + +CSV + , $this->encoder->encode(['=1+2\'" ;,=1+2'], 'csv', [ + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ])); } public function testEncodeWithoutHeader() diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index cdfa3c9780d61..d62581cd8e6d1 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -1147,38 +1147,6 @@ public function getIterator(): \ArrayIterator } } -class BazLegacy -{ - public $list; - - public $settings = []; - - public function __construct(array $list) - { - $this->list = new DummyListLegacy($list); - } -} - -class DummyListLegacy implements \Countable, \IteratorAggregate -{ - public $list; - - public function __construct(array $list) - { - $this->list = $list; - } - - public function count(): int - { - return \count($this->list); - } - - public function getIterator(): \Traversable - { - return new \ArrayIterator($this->list); - } -} - interface NormalizerAwareNormalizer extends NormalizerInterface, NormalizerAwareInterface { } diff --git a/src/Symfony/Component/Stopwatch/composer.json b/src/Symfony/Component/Stopwatch/composer.json index 4edea5a4ff414..bb68c24de3f0b 100644 --- a/src/Symfony/Component/Stopwatch/composer.json +++ b/src/Symfony/Component/Stopwatch/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=8.0.2", - "symfony/service-contracts": "^1.0|^2.0|^3.0" + "symfony/service-contracts": "^1|^2|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, diff --git a/src/Symfony/Component/Translation/Bridge/Crowdin/README.md b/src/Symfony/Component/Translation/Bridge/Crowdin/README.md index 7caef72eee8d9..a1b8a1a6cc46c 100644 --- a/src/Symfony/Component/Translation/Bridge/Crowdin/README.md +++ b/src/Symfony/Component/Translation/Bridge/Crowdin/README.md @@ -20,6 +20,15 @@ where: [Generate Personal Access Token on Crowdin Enterprise](https://support.crowdin.com/enterprise/personal-access-tokens/) +Sponsor +------- + +This bridge for Symfony 5.4/6.0 is [backed][1] by [Crowdin][2]. + +Crowdin is a cloud-based localization management software helping teams to go global and stay agile. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -27,3 +36,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://crowdin.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Translation/Bridge/Lokalise/README.md b/src/Symfony/Component/Translation/Bridge/Lokalise/README.md index 64e6cd0de7800..e91ac094f3cab 100644 --- a/src/Symfony/Component/Translation/Bridge/Lokalise/README.md +++ b/src/Symfony/Component/Translation/Bridge/Lokalise/README.md @@ -19,6 +19,16 @@ Go to the Project Settings in Lokalise to find the Project ID. [Generate an API key on Lokalise](https://app.lokalise.com/api2docs/curl/#resource-authentication) +Sponsor +------- + +This bridge for Symfony 5.4/6.0 is [backed][1] by [Lokalise][2]. + +Lokalise is a continuous localization and translation management platform. It integrates +into your development workflow so you can ship localized products, faster. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -26,3 +36,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://lokalise.com +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Translation/README.md b/src/Symfony/Component/Translation/README.md index 720bee3b81086..adda9a5b21e55 100644 --- a/src/Symfony/Component/Translation/README.md +++ b/src/Symfony/Component/Translation/README.md @@ -23,6 +23,16 @@ $translator->addResource('array', [ echo $translator->trans('Hello World!'); // outputs « Bonjour ! » ``` +Sponsor +------- + +The Translation component for Symfony 5.4/6.0 is [backed][1] by: + + * [Crowdin][2], a cloud-based localization management software helping teams to go global and stay agile. + * [Lokalise][3], a continuous localization and translation management platform that integrates into your development workflow so you can ship localized products, faster. + +Help Symfony by [sponsoring][4] its development! + Resources --------- @@ -31,3 +41,8 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://crowdin.com +[3]: https://lokalise.com +[4]: https://symfony.com/sponsor diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index eafe5c1766bf9..abe8b972c13d4 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -28,7 +28,7 @@ "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2.0|^3.0", + "symfony/service-contracts": "^1.1.2|^2|^3", "symfony/yaml": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "psr/log": "^1|^2|^3" diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf index b341436bc5e18..75410192190ef 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf @@ -394,6 +394,14 @@ This value is not a valid CSS color. Tato hodnota není platná barva CSS. + + This value is not a valid CIDR notation. + Tato hodnota není platná notace CIDR. + + + The value of the netmask should be between {{ min }} and {{ max }}. + Hodnota masky sítě musí být mezi {{ min }} a {{ max }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf index 6b1d061b81ed3..090add6bd3413 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf @@ -394,6 +394,14 @@ This value is not a valid CSS color. Este valor não é uma cor de CSS válida. + + This value is not a valid CIDR notation. + Este valor não é uma notação CIDR válida. + + + The value of the netmask should be between {{ min }} and {{ max }}. + O valor da máscara de rede deve estar entre {{ min }} e {{ max }}. + diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index d6da361ec3203..52fd7aababd2b 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -19,7 +19,7 @@ "php": ">=8.0.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^1.1|^2.0|^3.0" + "symfony/translation-contracts": "^1.1|^2|^3" }, "require-dev": { "symfony/console": "^5.4|^6.0", diff --git a/src/Symfony/Component/VarExporter/Internal/Exporter.php b/src/Symfony/Component/VarExporter/Internal/Exporter.php index 8fa4322bc7244..73a56105984c5 100644 --- a/src/Symfony/Component/VarExporter/Internal/Exporter.php +++ b/src/Symfony/Component/VarExporter/Internal/Exporter.php @@ -88,13 +88,12 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount $properties = []; $sleep = null; - $arrayValue = (array) $value; $proto = Registry::$prototypes[$class]; if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { // ArrayIterator and ArrayObject need special care because their "flags" // option changes the behavior of the (array) casting operator. - $properties = self::getArrayObjectProperties($value, $arrayValue, $proto); + [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); // populates Registry::$prototypes[$class] with a new instance Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); @@ -106,25 +105,23 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount $properties[] = $value[$v]; } $properties = ['SplObjectStorage' => ["\0" => $properties]]; + $arrayValue = (array) $value; } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class) { ++$objectsCount; $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; $value = new Reference($id); goto handle_value; - } - - if (method_exists($class, '__sleep')) { - if (!\is_array($sleep = $value->__sleep())) { - trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE); - $value = null; - goto handle_value; - } - foreach ($sleep as $name) { - if (property_exists($value, $name) && !$reflector->hasProperty($name)) { - $arrayValue[$name] = $value->$name; + } else { + if (method_exists($class, '__sleep')) { + if (!\is_array($sleep = $value->__sleep())) { + trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE); + $value = null; + goto handle_value; } + $sleep = array_flip($sleep); } - $sleep = array_flip($sleep); + + $arrayValue = (array) $value; } $proto = (array) $proto; @@ -368,13 +365,13 @@ private static function exportHydrator(Hydrator $value, string $indent, string $ * @param \ArrayIterator|\ArrayObject $value * @param \ArrayIterator|\ArrayObject $proto */ - private static function getArrayObjectProperties($value, array &$arrayValue, $proto): array + private static function getArrayObjectProperties($value, $proto): array { $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); $properties = [ - $arrayValue, + $arrayValue = (array) $value, $reflector->getMethod('getFlags')->invoke($value), $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator', ]; @@ -400,6 +397,6 @@ private static function getArrayObjectProperties($value, array &$arrayValue, $pr $properties = [$reflector->class => ["\0" => $properties]]; } - return $properties; + return [$arrayValue, $properties]; } } diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index 0795700f6211a..3ded211f1c9df 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -69,13 +69,10 @@ public function provideFailingSerialization() yield [$a]; - // This test segfaults on the final PHP 7.2 release - if (\PHP_VERSION_ID !== 70234) { - $a = [null, $h]; - $a[0] = &$a; + $a = [null, $h]; + $a[0] = &$a; - yield [$a]; - } + yield [$a]; } /** @@ -181,13 +178,10 @@ public function provideExport() yield ['hard-references', $value]; - // This test segfaults on the final PHP 7.2 release - if (\PHP_VERSION_ID !== 70234) { - $value = []; - $value[0] = &$value; + $value = []; + $value[0] = &$value; - yield ['hard-references-recursive', $value]; - } + yield ['hard-references-recursive', $value]; static $value = [123]; @@ -326,6 +320,13 @@ public function setFlags($flags): void class GoodNight { + public $good; + + public function __construct() + { + unset($this->good); + } + public function __sleep(): array { $this->good = 'night'; diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index b142aeb6ad670..671c133ec309c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -247,10 +247,11 @@ private static function dumpNull(int $flags): string * * @throws ParseException When malformed inline YAML string is parsed */ - public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = []): mixed + public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [], bool &$isQuoted = null): mixed { if (\in_array($scalar[$i], ['"', "'"], true)) { // quoted scalar + $isQuoted = true; $output = self::parseQuotedScalar($scalar, $i); if (null !== $delimiters) { @@ -264,6 +265,8 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi } } else { // "normal" string + $isQuoted = false; + if (!$delimiters) { $output = substr($scalar, $i); $i += \strlen($output); @@ -286,7 +289,7 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi } if ($evaluate) { - $output = self::evaluateScalar($output, $flags, $references); + $output = self::evaluateScalar($output, $flags, $references, $isQuoted); } } @@ -298,7 +301,7 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseQuotedScalar(string $scalar, int &$i): string + private static function parseQuotedScalar(string $scalar, int &$i = 0): string { if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); @@ -351,8 +354,7 @@ private static function parseSequence(string $sequence, int $flags, int &$i = 0, $value = self::parseMapping($sequence, $flags, $i, $references); break; default: - $isQuoted = \in_array($sequence[$i], ['"', "'"], true); - $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references); + $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references, $isQuoted); // the value can be an array if a reference has been resolved to an array var if (\is_string($value) && !$isQuoted && false !== strpos($value, ': ')) { @@ -497,8 +499,7 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a } break; default: - $isValueQuoted = \in_array($mapping[$i], ['"', "'"]); - $value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references); + $value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references, $isValueQuoted); // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. @@ -535,8 +536,9 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a * * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved */ - private static function evaluateScalar(string $scalar, int $flags, array &$references = []): mixed + private static function evaluateScalar(string $scalar, int $flags, array &$references = [], bool &$isQuotedString = null): mixed { + $isQuotedString = false; $scalar = trim($scalar); if (0 === strpos($scalar, '*')) { @@ -572,7 +574,14 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer case '!' === $scalar[0]: switch (true) { case 0 === strpos($scalar, '!!str '): - return (string) substr($scalar, 6); + $s = (string) substr($scalar, 6); + + if (\in_array($s[0] ?? '', ['"', "'"], true)) { + $isQuotedString = true; + $s = self::parseQuotedScalar($s); + } + + return $s; case 0 === strpos($scalar, '! '): return substr($scalar, 2); case 0 === strpos($scalar, '!php/object'): diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 9d672bdc9a36b..77fcee7cad830 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -924,21 +924,31 @@ public function ideographicSpaceProvider(): array ]; } + public function testParseSingleQuotedTaggedString() + { + $this->assertSame('foo', Inline::parse("!!str 'foo'")); + } + + public function testParseDoubleQuotedTaggedString() + { + $this->assertSame('foo', Inline::parse('!!str "foo"')); + } + public function testParseQuotedReferenceLikeStringsInMapping() { $yaml = <<assertSame(['foo' => '&foo', 'bar' => '&bar'], Inline::parse($yaml)); + $this->assertSame(['foo' => '&foo', 'bar' => '&bar', 'baz' => '&baz'], Inline::parse($yaml)); } public function testParseQuotedReferenceLikeStringsInSequence() { $yaml = <<assertSame(['&foo', '&bar'], Inline::parse($yaml)); + $this->assertSame(['&foo', '&bar', '&baz'], Inline::parse($yaml)); } } diff --git a/src/Symfony/Contracts/CHANGELOG.md b/src/Symfony/Contracts/CHANGELOG.md index 275415078d4c0..5c9c3d08d4c9e 100644 --- a/src/Symfony/Contracts/CHANGELOG.md +++ b/src/Symfony/Contracts/CHANGELOG.md @@ -1,6 +1,18 @@ CHANGELOG ========= +3.0 +--- + + * Bump to PHP 8 minimum + * Add native return types + * Remove deprecated features + +2.5 +--- + + * Add `SubscribedService` attribute, deprecate current `ServiceSubscriberTrait` usage + 2.4 --- pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy