diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5e7092d385910..5b76de89c7bee 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,7 @@ Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too.) - - Features and deprecations must be submitted against branch 5.x. + - Features and deprecations must be submitted against the latest branch. - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index c41b6a2be6b12..ea21103be96e3 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -122,7 +122,7 @@ jobs: uses: shivammathur/setup-php@v2 with: coverage: "none" - extensions: "json,couchbase,memcached,mongodb,redis,rdkafka,xsl,ldap" + extensions: "json,couchbase,memcached,mongodb,redis-5.3.4,rdkafka,xsl,ldap" ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 php-version: "${{ matrix.php }}" tools: pecl diff --git a/.github/workflows/package-tests.yml b/.github/workflows/package-tests.yml index 3c0a7c36be89f..23b65286814a9 100644 --- a/.github/workflows/package-tests.yml +++ b/.github/workflows/package-tests.yml @@ -82,7 +82,7 @@ jobs: echo "Verifying new package" _correct_license_file $DIR/LICENSE || localExit=1 - if [ $TYPE == 'component_bridge' ]; then + if [ $TYPE != 'component_bridge' ]; then if [ ! $(cat composer.json | jq -e ".replace.\"$NAME\"|test(\"self.version\")") ]; then echo "Composer.json's replace section needs to contain $NAME" localExit=1 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index a208a253456e2..1b2f1c4b5a3da 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -212,6 +212,11 @@ jobs: [[ ! $X ]] || (exit 1) + - name: Run TTY tests + if: "! matrix.mode" + run: | + script -e -c './phpunit --group tty' /dev/null + - name: Run tests with SIGCHLD enabled PHP if: "matrix.php == '7.2' && ! matrix.mode" run: | diff --git a/CHANGELOG-5.3.md b/CHANGELOG-5.3.md index 0436dd92be510..765cdf7d87099 100644 --- a/CHANGELOG-5.3.md +++ b/CHANGELOG-5.3.md @@ -7,6 +7,40 @@ in 5.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.3.0...v5.3.1 +* 5.3.14 (2022-01-28) + + * bug #44860 [Validator] Fix Choice constraint with associative choices array (derrabus) + * bug #44939 [Form] UrlType should not add protocol to emails (GromNaN) + * bug #43149 Silence warnings during tty detection (neclimdul) + * bug #45154 [Serializer] Fix AbstractObjectNormalizer not considering pseudo type false (Thomas Nunninger) + * bug #45185 [Notifier] Fix encoding of messages with FreeMobileTransport (94noni) + * bug #45181 [Console] Fix PHP 8.1 deprecation in ChoiceQuestion (BrokenSourceCode) + * bug #45174 [Notifier] Use the UTF-8 encoding in smsapi-notifier (marphi) + * bug #45140 [Yaml] Making the parser stateless (mamazu) + * bug #45109 [Console] fix restoring stty mode on CTRL+C (nicolas-grekas) + * bug #45103 [Process] Avoid calling fclose on an already closed resource (Seldaek) + * bug #45088 [Console] fix parsing escaped chars in StringInput (nicolas-grekas) + * bug #45096 [Cache] Throw exception if incompatible version of psr/simple-cache is used (colinodell) + * bug #45063 [DependencyInjection] remove arbitratry limitation to exclude inline services from bindings (nicolas-grekas) + * bug #44986 [DependencyInjection] copy synthetic status when resolving child definitions (kbond) + * bug #45073 [HttpClient] Fix Failed to open stream: Too many open files (adrienfr) + * bug #45053 [Console] use STDOUT/ERR in ConsoleOutput to save opening too many file descriptors (nicolas-grekas) + * bug #45029 [Cache] Set mtime of cache files 1 year into future if they do not expire (Blacksmoke16) + * bug #45012 [DoctrineBridge] Fix invalid guess with enumType (jderusse) + * bug #45015 [HttpClient] fix resetting DNS/etc when calling CurlHttpClient::reset() (nicolas-grekas) + * bug #45004 [HttpClient] Remove deprecated usage of GuzzleHttp\Promise\promise_for (plozmun) + * bug #44998 [FrameworkBundle] Allow default cache pools to be overwritten by user (Seldaek) + * bug #44890 [HttpClient] Remove deprecated usage of `GuzzleHttp\Promise\queue` (GrahamCampbell) + * bug #45002 [PropertyAccess] Fix handling of uninitialized property of anonymous class (filiplikavcan) + * bug #44979 [DependencyInjection] Add iterable to possible binding type (vladimir.panivko) + * bug #44976 [FrameworkBundle] Avoid calling rtrim(null, '/') in AssetsInstallCommand (pavol-tk, GromNaN) + * bug #44879 [DependencyInjection] Ignore argument type check in CheckTypeDeclarationsPass if it's a Definition with a factory (fancyweb) + * bug #44931 Allow a zero time-limit for messenger:consume (fritzmg) + * bug #44932 [DependencyInjection] Fix nested env var with resolve processor (Laurent Moreau) + * bug #44912 [Console] Allow OutputFormatter::escape() to be used for escaping URLs used in (Seldaek) + * bug #44878 [HttpClient] Turn negative timeout to a very long timeout (fancyweb) + * bug #44854 [Validator] throw when Constraint::_construct() has not been called (nicolas-grekas) + * 5.3.13 (2021-12-29) * bug #44838 [DependencyInjection][HttpKernel] Fix enum typed bindings (ogizanagi) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d211dd419d064..c0b3daf15d463 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,83 +1,8 @@ -Code of Conduct -=============== +# Code of Conduct -Our Pledge ----------- +This project follows a [Code of Conduct][code_of_conduct] in order to ensure an open and welcoming environment. +Please read the full text for understanding the accepted and unaccepted behavior. +Please read also the [reporting guidelines][guidelines], in case you encountered or witnessed any misbehavior. -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnic origin, gender identity and expression, level of -experience, education, socio-economic status, nationality, personal appearance, -religion, or sexual identity and orientation. - -Our Standards -------------- - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -Our Responsibilities --------------------- - -[CoC Active Response Ensurers, or CARE][1], are responsible for clarifying the -standards of acceptable behavior and are expected to take appropriate and fair -corrective action in response to any instances of unacceptable behavior. - -CARE team members have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, or to ban temporarily or permanently any -contributor for other behaviors that they deem inappropriate, threatening, -offensive, or harmful. - -Scope ------ - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by CARE team members. - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior -[may be reported][2] by contacting the [CARE team members][1]. -All complaints will be reviewed and investigated and will result in a response -that is deemed necessary and appropriate to the circumstances. The CARE team is -obligated to maintain confidentiality with regard to the reporter of an -incident. Further details of specific enforcement policies may be posted -separately. - -CARE team members who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by the -[core team][3]. - -Attribution ------------ - -This Code of Conduct is adapted from the [Contributor Covenant version 1.4][4]. - -[1]: https://symfony.com/doc/current/contributing/code_of_conduct/care_team.html -[2]: https://symfony.com/doc/current/contributing/code_of_conduct/reporting_guidelines.html -[3]: https://symfony.com/doc/current/contributing/code/core_team.html -[4]: https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +[code_of_conduct]: https://symfony.com/coc +[guidelines]: https://symfony.com/doc/current/contributing/code_of_conduct/reporting_guidelines.html diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b5e87ad1280f4..48ae19030db84 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -12,15 +12,15 @@ The Symfony Connect username in parenthesis allows to get more information - Tobias Schultze (tobion) - Robin Chalas (chalas_r) - Christophe Coevoet (stof) - - Jérémy DERUSSÉ (jderusse) - Wouter De Jong (wouterj) + - Jérémy DERUSSÉ (jderusse) - Grégoire Pineau (lyrixx) - Maxime Steinhausser (ogizanagi) - Kévin Dunglas (dunglas) - Jordi Boggiano (seldaek) + - Thomas Calvet (fancyweb) - Victor Berchet (victor) - Javier Eguiluz (javier.eguiluz) - - Thomas Calvet (fancyweb) - Ryan Weaver (weaverryan) - Roland Franssen (ro0) - Jakub Zalas (jakubzalas) @@ -54,19 +54,19 @@ The Symfony Connect username in parenthesis allows to get more information - Valentin Udaltsov (vudaltsov) - Iltar van der Berg (kjarli) - Jonathan Wage (jwage) + - Jérôme Tamarelle (gromnan) - Matthias Pigulla (mpdude) - Diego Saint Esteben (dosten) - Grégoire Paris (greg0ire) - Alexandre Salomé (alexandresalome) - - Jérôme Tamarelle (gromnan) - William Durand (couac) - ornicar + - Titouan Galopin (tgalopin) - Konstantin Myakshin (koc) - Dany Maillard (maidmaid) - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - - Titouan Galopin (tgalopin) - Laurent VOULLEMIER (lvo) - Vasilij Dusko | CREATION - Bulat Shakirzyanov (avalanche123) @@ -79,10 +79,10 @@ The Symfony Connect username in parenthesis allows to get more information - Miha Vrhovnik - Diego Saint Esteben (dii3g0) - Mathieu Piot (mpiot) + - Antoine M (amakdessi) - Konstantin Kudryashov (everzet) - Vladimir Reznichenko (kalessil) - Bilal Amarni (bamarni) - - Antoine M (amakdessi) - Florin Patan (florinpatan) - Jáchym Toušek (enumag) - Alex Pott @@ -107,24 +107,24 @@ The Symfony Connect username in parenthesis allows to get more information - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Mathieu Santostefano (welcomattic) - Daniel Holmes (dholmes) - Sebastiaan Stok (sstok) + - HypeMC (hypemc) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - - Mathieu Santostefano (welcomattic) - John Wards (johnwards) - Tomas Norkūnas (norkunas) + - Alexandre Daubois (alexandre-daubois) - Baptiste Clavié (talus) - - HypeMC (hypemc) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - - Alexandre Daubois (alexandre-daubois) - Vincent Langlet (deviling) + - Julien Falque (julienfalque) - 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) @@ -143,6 +143,7 @@ The Symfony Connect username in parenthesis allows to get more information - Włodzimierz Gajda (gajdaw) - Christian Scheb - Adrien Brault (adrienbrault) + - Maxime Helias (maxhelias) - Yanick Witschi (toflar) - Jacob Dreesen (jdreesen) - Malte Schlüter (maltemaltesich) @@ -152,6 +153,7 @@ The Symfony Connect username in parenthesis allows to get more information - Teoh Han Hui (teohhanhui) - Colin Frei - Javier Spagnoletti (phansys) + - Ruud Kamphuis (ruudk) - Joshua Thijssen - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) @@ -159,15 +161,13 @@ The Symfony Connect username in parenthesis allows to get more information - Gordon Franke (gimler) - Saif Eddin Gmati (azjezz) - Richard van Laak (rvanlaak) - - Maxime Helias (maxhelias) + - Gary PEGEOT (gary-p) - Jesse Rushlow (geeshoe) - Fabien Pennequin (fabienpennequin) - Olivier Dolbeau (odolbeau) - Smaine Milianni (ismail1432) - Eric GELOEN (gelo) - - Gary PEGEOT (gary-p) - Matthieu Napoli (mnapoli) - - Ruud Kamphuis (ruudk) - Ion Bazan (ionbazan) - Jannik Zschiesche (apfelbox) - Robert Schönthal (digitalkaoz) @@ -190,6 +190,7 @@ The Symfony Connect username in parenthesis allows to get more information - Albert Casademont (acasademont) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) + - Marco Pivetta (ocramius) - SpacePossum - Alexander Menshchikov (zmey_kk) - Pablo Godel (pgodel) @@ -203,20 +204,23 @@ The Symfony Connect username in parenthesis allows to get more information - jwdeitch - Jeroen Spee (jeroens) - Jérôme Parmentier (lctrs) - - Marco Pivetta (ocramius) - Fabien Bourigault (fbourigault) - Joe Bennett (kralos) - Mikael Pajunen - Andreas Schempp (aschempp) - Alessandro Lai (jean85) - Romaric Drigon (romaricdrigon) + - Christopher Hertel (chertel) - Arman Hosseini (arman) + - Rokas Mikalkėnas (rokasm) - Niels Keurentjes (curry684) - Vyacheslav Pavlov + - Andreas Möller (localheinz) - Richard Shank (iampersistent) - Wouter J - Thomas Rabaix (rande) - Chi-teck + - Baptiste Leduc (korbeil) - Timo Bakx (timobakx) - Vincent Touzet (vincenttouzet) - Nate Wiebe (natewiebe13) @@ -225,16 +229,13 @@ The Symfony Connect username in parenthesis allows to get more information - 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) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - Dawid Nowak - - Andreas Möller (localheinz) - Roman Martinuk (a2a4) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) @@ -244,7 +245,6 @@ 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) - zairig imad (zairigimad) - Tien Vo (tienvx) @@ -275,6 +275,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thibaut Cheymol (tcheymol) - Sebastien Morel (plopix) - mcfedr (mcfedr) + - Colin O'Dell (colinodell) - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) - Baptiste Lafontaine (magnetik) @@ -311,7 +312,6 @@ The Symfony Connect username in parenthesis allows to get more information - Matthieu Auger (matthieuauger) - Leszek Prabucki (l3l0) - Nicolas Philippe (nikophil) - - Colin O'Dell (colinodell) - Emanuele Panzeri (thepanz) - François Zaninotto (fzaninotto) - Dustin Whittle (dustinwhittle) @@ -325,6 +325,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sven Paulus (subsven) - Daniel STANCU - Maxime Veber (nek-) + - Sylvain Fabre (sylfabre) - Loick Piera (pyrech) - Clara van Miert - Valentine Boineau (valentineboineau) @@ -340,6 +341,7 @@ The Symfony Connect username in parenthesis allows to get more information - Victor Bocharsky (bocharsky_bw) - Bozhidar Hristov (warxcell) - Marcel Beerta (mazen) + - Thomas Landauer (thomas-landauer) - Pavel Batanov (scaytrase) - Mantis Development - Loïc Faugeron @@ -373,10 +375,11 @@ The Symfony Connect username in parenthesis allows to get more information - Roman Marintšenko (inori) - Xavier Montaña Carreras (xmontana) - Mickaël Andrieu (mickaelandrieu) + - Soner Sayakci - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA - - Sylvain Fabre (sylfabre) + - Artem Lopata - Patrick McDougle (patrick-mcdougle) - Marc Weistroff (futurecat) - Alif Rachmawadi @@ -402,7 +405,6 @@ The Symfony Connect username in parenthesis allows to get more information - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - jdhoek - - Thomas Landauer (thomas-landauer) - Jurica Vlahoviček (vjurica) - Bob den Otter (bopp) - Thomas Schulz (king2500) @@ -436,7 +438,6 @@ The Symfony Connect username in parenthesis allows to get more information - Wouter Van Hecke - Iker Ibarguren (ikerib) - Bob van de Vijver (bobvandevijver) - - Soner Sayakci - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Arjen van der Meijden @@ -459,6 +460,7 @@ The Symfony Connect username in parenthesis allows to get more information - Manuel Kiessling (manuelkiessling) - Dimitri Gritsajuk (ottaviano) - Alexey Kopytko (sanmai) + - Gijs van Lammeren - Pol Dellaiera (drupol) - Atsuhiro KUBO (iteman) - Alireza Mirsepassi (alirezamirsepassi) @@ -535,7 +537,6 @@ The Symfony Connect username in parenthesis allows to get more information - Christian Gärtner (dagardner) - Dmytro Borysovskyi (dmytr0) - Tomasz Kowalczyk (thunderer) - - Artem Lopata - Artur Eshenbrener - Thomas Perez (scullwm) - Yoann RENARD (yrenard) @@ -553,6 +554,7 @@ The Symfony Connect username in parenthesis allows to get more information - hossein zolfi (ocean) - Clément Gautier (clementgautier) - Koen Reiniers (koenre) + - Hugo Alliaume (kocal) - Sanpi - Eduardo Gulias (egulias) - giulio de donato (liuggio) @@ -560,10 +562,12 @@ The Symfony Connect username in parenthesis allows to get more information - ShinDarth - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) + - Rhodri Pugh (rodnaph) - Grzegorz Zdanowski (kiler129) - Kirill chEbba Chebunin (chebba) - - Fabien Villepinte + - SiD (plbsid) - Matthew Grasmick - Greg Thornton (xdissent) - BENOIT POLASZEK (bpolaszek) @@ -575,12 +579,12 @@ The Symfony Connect username in parenthesis allows to get more information - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) - Vyacheslav Salakhutdinov (megazoll) + - Antoine Lamirault - Phil Taylor (prazgod) - Hassan Amouhzi - Tamas Szijarto - Michele Locati - Pavel Volokitin (pvolok) - - Gijs van Lammeren - Arthur de Moulins (4rthem) - Matthias Althaus (althaus) - Nicolas Dewez (nicolas_dewez) @@ -650,6 +654,7 @@ The Symfony Connect username in parenthesis allows to get more information - scyzoryck - Matthias Krauser (mkrauser) - Erkhembayar Gantulga (erheme318) + - Alexis Lefebvre - Lorenzo Millucci (lmillucci) - Jérôme Tamarelle (jtamarelle-prismamedia) - Andrii Popov (andrii-popov) @@ -677,6 +682,7 @@ The Symfony Connect username in parenthesis allows to get more information - Chris Sedlmayr (catchamonkey) - Indra Gunawan (indragunawan) - Mathias STRASSER (roukmoute) + - simon chrzanowski (simonch) - Kamil Kokot (pamil) - Seb Koelen - Christoph Mewes (xrstf) @@ -719,7 +725,6 @@ The Symfony Connect username in parenthesis allows to get more information - Marek Zajac - Adam Harvey - Anton Bakai - - Rhodri Pugh (rodnaph) - battye - Sam Fleming (sam_fleming) - William Arslett @@ -749,7 +754,6 @@ The Symfony Connect username in parenthesis allows to get more information - Sebastian Bergmann - Miroslav Sustek - Pablo Díez (pablodip) - - SiD (plbsid) - Michel Roca (mroca) - Kevin McBride - Sergio Santoro @@ -780,6 +784,7 @@ The Symfony Connect username in parenthesis allows to get more information - Markus Lanthaler (lanthaler) - Remi Collet - Vicent Soria Durá (vicentgodella) + - Daniel Gorgan - Michael Moravec - Carlos Buenosvinos (carlosbuenosvinos) - Leevi Graham (leevigraham) @@ -799,6 +804,7 @@ The Symfony Connect username in parenthesis allows to get more information - Scott Arciszewski - Xavier HAUSHERR - Norbert Orzechowicz (norzechowicz) + - stlrnz - Denis Charrier (brucewouaigne) - Matthijs van den Bos (matthijs) - Simon Podlipsky (simpod) @@ -912,8 +918,8 @@ The Symfony Connect username in parenthesis allows to get more information - vitaliytv - Nicolas Martin (cocorambo) - Adrian Nguyen (vuphuong87) + - Khoo Yong Jun - Sebastian Blum - - Alexis Lefebvre - Laurent Clouet - aubx - Julien Turby @@ -930,6 +936,7 @@ The Symfony Connect username in parenthesis allows to get more information - pizzaminded - Stéphane Escandell (sescandell) - Konstantin S. M. Möllers (ksmmoellers) + - Fractal Zombie - linh - James Johnston - Sinan Eldem @@ -978,6 +985,7 @@ The Symfony Connect username in parenthesis allows to get more information - Evgeny Anisiforov - smoench - Max Grigorian (maxakawizard) + - Martins Sipenko - Guilherme Augusto Henschel - Rostyslav Kinash - Cristoforo Cervino (cristoforocervino) @@ -1021,9 +1029,11 @@ The Symfony Connect username in parenthesis allows to get more information - Tomas Javaisis - Ivan Grigoriev - Johann Saunier (prophet777) + - Kevin SCHNEKENBURGER - Fabien Salles (blacked) - Andreas Erhard - John VanDeWeghe + - Sergey Belyshkin - Michael Devery (mickadoo) - Antoine Corcy - Ahmed Ashraf (ahmedash95) @@ -1085,6 +1095,7 @@ The Symfony Connect username in parenthesis allows to get more information - Roromix - Maxime AILLOUD (mailloud) - Richard van den Brand (ricbra) + - Toon Verwerft (veewee) - mohammadreza honarkhah - develop - flip111 @@ -1191,6 +1202,7 @@ The Symfony Connect username in parenthesis allows to get more information - Julien Pauli - Dominik Piekarski (dompie) - Rares Sebastian Moldovan (raresmldvn) + - Jérémy REYNAUD (babeuloula) - Mathieu Rochette (mathroc) - Victor Garcia - Jérôme Tanghe (deuchnord) @@ -1239,7 +1251,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tito Costa - Jan Prieser - GDIBass - - Antoine Lamirault + - Maximilian Bösing - Thiago Melo - Adrien Lucas (adrienlucas) - Zhuravlev Alexander (scif) @@ -1300,7 +1312,6 @@ The Symfony Connect username in parenthesis allows to get more information - Loïc Beurlet - Sébastien COURJEAN - Ana Raro - - Daniel Gorgan - Ana Raro - Tony Malzhacker - Pchol @@ -1380,13 +1391,14 @@ The Symfony Connect username in parenthesis allows to get more information - Forfarle (forfarle) - Harry Walter (haswalt) - Johnson Page (jwpage) + - Kuba Werłos (kuba) - Ruben Gonzalez (rubenruateltek) - Michael Roterman (wtfzdotnet) + - Philipp Keck - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) - Kai Eichinger (kai_eichinger) - - Hugo Alliaume (kocal) - Marcos Gómez Vilches (markitosgv) - Matthew Davis (mdavis1982) - Paulo Ribeiro (paulo) @@ -1396,7 +1408,6 @@ The Symfony Connect username in parenthesis allows to get more information - Antoine LA - den - Pavol Tuka - - stlrnz - pawel-lewtak - omerida - Gábor Tóth @@ -1476,9 +1487,7 @@ The Symfony Connect username in parenthesis allows to get more information - neghmurken - xaav - Mahmoud Mostafa (mahmoud) - - Fractal Zombie - Ahmed Abdou - - Khoo Yong Jun - shreyadenny - Daniel Iwaniec - Pieter @@ -1509,6 +1518,7 @@ The Symfony Connect username in parenthesis allows to get more information - LHommet Nicolas (nicolaslh) - fabios - Sander Coolen (scoolen) + - Emil Masiakowski - Amirreza Shafaat (amirrezashafaat) - Adoni Pavlakis (adoni) - Nicolas Le Goff (nlegoff) @@ -1628,6 +1638,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jean-Guilhem Rouel (jean-gui) - Yoann MOROCUTTI - jfcixmedia + - Tomasz Kusy - Dominic Tubach - Nikita Konstantinov - Martijn Evers @@ -1635,6 +1646,7 @@ The Symfony Connect username in parenthesis allows to get more information - Philipp Fritsche - tarlepp - Benjamin Paap (benjaminpaap) + - Guillaume Aveline - Christian - Denis Golubovskiy (bukashk0zzz) - Arkadiusz Rzadkowolski (flies) @@ -1647,7 +1659,6 @@ The Symfony Connect username in parenthesis allows to get more information - hugofonseca (fonsecas72) - Marc Duboc (icemad) - Martynas Narbutas - - Toon Verwerft (veewee) - Bailey Parker - Eddie Jaoude - Antanas Arvasevicius @@ -1716,6 +1727,7 @@ The Symfony Connect username in parenthesis allows to get more information - Charles Sanquer (csanquer) - Albert Ganiev (helios-ag) - Neil Katin + - Oleg Mifle - David Otton - Will Donohoe - gnito-org @@ -1740,13 +1752,13 @@ The Symfony Connect username in parenthesis allows to get more information - Amine Yakoubi - Eduardo García Sanz (coma) - Sergio (deverad) - - simon chrzanowski (simonch) - Makdessi Alex - James Gilliland - fduch (fduch) - Juan Miguel Besada Vidal (soutlink) - dlorek - Stuart Fyfe + - Jason Schilling (chapterjason) - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) - Nathan PAGE (nathix) @@ -1765,6 +1777,7 @@ The Symfony Connect username in parenthesis allows to get more information - Roger Webb - Dmitriy Simushev - Pawel Smolinski + - Simon Watiau (simonwatiau) - Oxan van Leeuwen - pkowalczyk - Soner Sayakci @@ -1815,6 +1828,7 @@ The Symfony Connect username in parenthesis allows to get more information - Dmitri Petmanson - heccjj - Alexandre Melard + - PierreRebeilleau - Jay Klehr - Sergey Yuferev - Tobias Stöckler @@ -1954,7 +1968,6 @@ The Symfony Connect username in parenthesis allows to get more information - Wojciech Błoszyk (wbloszyk) - Giorgio Premi - abunch - - Sergey Belyshkin - tamcy - Mikko Pesari - ncou @@ -1982,6 +1995,7 @@ The Symfony Connect username in parenthesis allows to get more information - Raphaëll Roussel - Tadcka - Beth Binkovitz + - Maxim Semkin - Gonzalo Míguez - Fabian Haase - Romain Geissler @@ -2027,6 +2041,7 @@ The Symfony Connect username in parenthesis allows to get more information - Tony Vermeiren (tony) - Bart Wach - Jos Elstgeest + - Kirill Lazarev - Thomas Counsell - BilgeXA - r1pp3rj4ck @@ -2197,6 +2212,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matt Farmer - catch - aetxebeste + - Vitali Tsyrkin - Juga Paazmaya - Alexandre Segura - afaricamp @@ -2249,6 +2265,7 @@ The Symfony Connect username in parenthesis allows to get more information - Andreas - Markus - agaktr + - Mostafa - kernig - Thomas Chmielowiec - shdev @@ -2276,6 +2293,7 @@ The Symfony Connect username in parenthesis allows to get more information - Christoph Nissle (derstoffel) - Denys Voronin (hurricane) - Ionel Scutelnicu (ionelscutelnicu) + - Juan Gonzalez Montes (juanwilde) - Mathieu Dewet (mdewet) - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) @@ -2294,7 +2312,6 @@ The Symfony Connect username in parenthesis allows to get more information - Christopher Parotat - Dennis Haarbrink - me_shaon - - Maximilian Bösing - 蝦米 - Grayson Koonce (breerly) - Andrey Helldar (helldar) @@ -2373,6 +2390,7 @@ The Symfony Connect username in parenthesis allows to get more information - Cyril Pascal (paxal) - Cédric Dugat (ph3nol) - Philip Dahlstrøm (phidah) + - Pierre Rebeilleau (pierrereb) - Milos Colakovic (project2481) - Raphael de Almeida (raphaeldealmeida) - Rénald Casagraude (rcasagraude) @@ -2435,6 +2453,7 @@ The Symfony Connect username in parenthesis allows to get more information - Peter Breuls - Chansig - Tischoi + - divinity76 - Andreas Hasenack - J Bruni - Alexey Prilipko @@ -2468,6 +2487,7 @@ The Symfony Connect username in parenthesis allows to get more information - Pedro Magalhães (pmmaga) - Rares Vlaseanu (raresvla) - Sergii Dolgushev (serhey) + - Rein Baarsma (solidwebcode) - tante kinast (tante) - Stephen Lewis (tehanomalousone) - Ahmed Hannachi (tiecoders) @@ -2525,6 +2545,7 @@ The Symfony Connect username in parenthesis allows to get more information - grifx - Robert Campbell - Matt Lehner + - Olexandr Kalaidzhy - Helmut Januschka - Hein Zaw Htet™ - Ruben Kruiswijk @@ -2585,6 +2606,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gerrit Drost - Linnaea Von Lavia - Bastien Clément + - Julius Šakalys - Javan Eskander - Lenar Lõhmus - Cristian Gonzalez @@ -2596,7 +2618,6 @@ The Symfony Connect username in parenthesis allows to get more information - Pavinthan - Sylvain METAYER - ddebree - - Kuba Werłos - Gyula Szucs - Tomas Liubinas - Ivo Valchev @@ -2664,7 +2685,6 @@ The Symfony Connect username in parenthesis allows to get more information - Geordie - Exploit.cz - GuillaumeVerdon - - Philipp Keck - Angel Fernando Quiroz Campos - Ondrej Mirtes - akimsko @@ -2726,6 +2746,7 @@ The Symfony Connect username in parenthesis allows to get more information - arend - Vincent Godé - Dusan Kasan + - helmi - Michael Steininger - Nardberjean - Karolis @@ -2865,6 +2886,7 @@ The Symfony Connect username in parenthesis allows to get more information - Babichev Maxim - Edvin Hultberg - Benjamin Long + - Kévin Gonella - Ben Miller - Peter Gribanov - Ash014 @@ -2896,6 +2918,7 @@ The Symfony Connect username in parenthesis allows to get more information - Steve Marvell - Dawid Nowak - Lesnykh Ilia + - Shyim - sabruss - darnel - Karolis Daužickas @@ -2943,6 +2966,7 @@ The Symfony Connect username in parenthesis allows to get more information - Christian Gripp (core23) - Christoph Schaefer (cvschaefer) - Damon Jones (damon__jones) + - Alexandre Fiocre (demos77) - Łukasz Giza (destroyer) - Daniel Londero (dlondero) - Sebastian Landwehr (dword123) diff --git a/LICENSE b/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index 2d72874a276a1..bfea9441816af 100644 --- a/composer.json +++ b/composer.json @@ -163,7 +163,6 @@ }, "config": { "allow-plugins": { - "composer/package-versions-deprecated": true, "symfony/runtime": true } }, diff --git a/src/Symfony/Bridge/Doctrine/LICENSE b/src/Symfony/Bridge/Doctrine/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bridge/Doctrine/LICENSE +++ b/src/Symfony/Bridge/Doctrine/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index 44c725ab4a9c3..3ba347b253ca6 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -134,14 +134,17 @@ public function getTypes(string $class, string $property, array $context = []) } if ($metadata->hasField($property)) { + $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); + if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) { + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass)]; + } + $typeOfField = $metadata->getTypeOfField($property); if (!$builtinType = $this->getPhpType($typeOfField)) { return null; } - $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); - switch ($builtinType) { case Type::BUILTIN_TYPE_OBJECT: switch ($typeOfField) { diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEnum.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEnum.php new file mode 100644 index 0000000000000..8ac883e89c4a2 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEnum.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures; + +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity + */ +class DoctrineLoaderEnum +{ + /** + * @ORM\Id + * @ORM\Column + */ + public $id; + + /** + * @ORM\Column(type="string", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumString", length=1) + */ + public $enumString; + + /** + * @ORM\Column(type="integer", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt") + */ + public $enumInt; +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 3b9419d174a60..5d0a09f5f906a 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -14,12 +14,16 @@ use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Tools\Setup; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineEnum; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineGeneratedValue; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumString; use Symfony\Component\PropertyInfo\Type; /** @@ -124,6 +128,18 @@ public function testExtractWithEmbedded() $this->assertEquals($expectedTypes, $actualTypes); } + /** + * @requires PHP 8.1 + */ + public function testExtractEnum() + { + if (!property_exists(Column::class, 'enumType')) { + $this->markTestSkipped('The "enumType" requires doctrine/orm 2.11.'); + } + $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, EnumString::class)], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumString', [])); + $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, EnumInt::class)], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumInt', [])); + } + public function typesProvider() { $provider = [ diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php new file mode 100644 index 0000000000000..467522cbd3914 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; + +use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; + +/** + * @Entity + */ +class DoctrineEnum +{ + /** + * @Id + * @Column(type="smallint") + */ + public $id; + + /** + * @Column(type="string", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumString") + */ + protected $enumString; + + /** + * @Column(type="integer", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt") + */ + protected $enumInt; +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumInt.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumInt.php new file mode 100644 index 0000000000000..c9560073fa611 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumInt.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; + +enum EnumInt: int +{ + case Foo = 0; + case Bar = 1; +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumString.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumString.php new file mode 100644 index 0000000000000..0b6ef0df1bd41 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/EnumString.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; + +enum EnumString: string +{ + case Foo = 'f'; + case Bar = 'b'; +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 1ba0b6f254874..0bb9591e185df 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -11,11 +11,13 @@ namespace Symfony\Bridge\Doctrine\Tests\Validator; +use Doctrine\ORM\Mapping\Column; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\BaseUser; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderEmbed; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderEntity; +use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderEnum; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderNestedEmbed; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderNoAutoMappingEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoctrineLoaderParentEntity; @@ -149,6 +151,31 @@ public function testLoadClassMetadata() $this->assertSame(AutoMappingStrategy::DISABLED, $noAutoMappingMetadata[0]->getAutoMappingStrategy()); } + /** + * @requires PHP 8.1 + */ + public function testExtractEnum() + { + if (!property_exists(Column::class, 'enumType')) { + $this->markTestSkipped('The "enumType" requires doctrine/orm 2.11.'); + } + + $validator = Validation::createValidatorBuilder() + ->addMethodMapping('loadValidatorMetadata') + ->enableAnnotationMapping() + ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{^Symfony\\\\Bridge\\\\Doctrine\\\\Tests\\\\Fixtures\\\\DoctrineLoader}')) + ->getValidator() + ; + + $classMetadata = $validator->getMetadataFor(new DoctrineLoaderEnum()); + + $enumStringMetadata = $classMetadata->getPropertyMetadata('enumString'); + $this->assertCount(0, $enumStringMetadata); // asserts the length constraint is not added to an enum + + $enumStringMetadata = $classMetadata->getPropertyMetadata('enumInt'); + $this->assertCount(0, $enumStringMetadata); // asserts the length constraint is not added to an enum + } + public function testFieldMappingsConfiguration() { $validator = Validation::createValidatorBuilder() diff --git a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php index b3ab046ebd42b..7ea316f41a2d0 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php +++ b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php @@ -16,6 +16,7 @@ use Doctrine\ORM\Mapping\MappingException as OrmMappingException; use Doctrine\Persistence\Mapping\MappingException; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\AutoMappingStrategy; @@ -99,7 +100,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool $loaded = true; } - if (null === ($mapping['length'] ?? null) || !\in_array($mapping['type'], ['string', 'text'], true)) { + if (null === ($mapping['length'] ?? null) || null !== ($mapping['enumType'] ?? null) || !\in_array($mapping['type'], ['string', 'text'], true)) { continue; } diff --git a/src/Symfony/Bridge/Monolog/LICENSE b/src/Symfony/Bridge/Monolog/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bridge/Monolog/LICENSE +++ b/src/Symfony/Bridge/Monolog/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index c2a524c44f699..2aeae49d58fa9 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -408,11 +408,11 @@ private static function hasColorSupport() } if (\function_exists('stream_isatty')) { - return stream_isatty(\STDOUT); + return @stream_isatty(\STDOUT); } if (\function_exists('posix_isatty')) { - return posix_isatty(\STDOUT); + return @posix_isatty(\STDOUT); } $stat = fstat(\STDOUT); diff --git a/src/Symfony/Bridge/PhpUnit/LICENSE b/src/Symfony/Bridge/PhpUnit/LICENSE index c1f0aac1c5614..a843ec124ea70 100644 --- a/src/Symfony/Bridge/PhpUnit/LICENSE +++ b/src/Symfony/Bridge/PhpUnit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2021 Fabien Potencier +Copyright (c) 2014-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/ProxyManager/LICENSE b/src/Symfony/Bridge/ProxyManager/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bridge/ProxyManager/LICENSE +++ b/src/Symfony/Bridge/ProxyManager/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/Twig/LICENSE b/src/Symfony/Bridge/Twig/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bridge/Twig/LICENSE +++ b/src/Symfony/Bridge/Twig/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/DebugBundle/LICENSE b/src/Symfony/Bundle/DebugBundle/LICENSE index c1f0aac1c5614..a843ec124ea70 100644 --- a/src/Symfony/Bundle/DebugBundle/LICENSE +++ b/src/Symfony/Bundle/DebugBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2021 Fabien Potencier +Copyright (c) 2014-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index a5a30cbbac350..9de0081f5e22f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -96,8 +96,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int { /** @var KernelInterface $kernel */ $kernel = $this->getApplication()->getKernel(); - $targetArg = rtrim($input->getArgument('target'), '/'); - + $targetArg = rtrim($input->getArgument('target') ?? '', '/'); if (!$targetArg) { $targetArg = $this->getPublicDirectory($kernel->getContainer()); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 556232c88e26f..c2d54a704905d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -307,30 +307,10 @@ public function load(array $configs, ContainerBuilder $container) } } - // register cache before session so both can share the connection services - $this->registerCacheConfiguration($config['cache'], $container); - - if ($this->isConfigEnabled($container, $config['session'])) { - if (!\extension_loaded('session')) { - throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.'); - } - - $this->sessionConfigEnabled = true; - $this->registerSessionConfiguration($config['session'], $container, $loader); - if (!empty($config['test'])) { - $container->getDefinition('test.session.listener')->setArgument(1, '%session.storage.options%'); - } - } - if ($this->isConfigEnabled($container, $config['request'])) { $this->registerRequestConfiguration($config['request'], $container, $loader); } - if (null === $config['csrf_protection']['enabled']) { - $config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']); - } - $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); - if ($this->isConfigEnabled($container, $config['form'])) { if (!class_exists(Form::class)) { throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".'); @@ -459,6 +439,28 @@ public function load(array $configs, ContainerBuilder $container) $this->registerUidConfiguration($config['uid'], $container, $loader); } + // register cache & dependencies last so that user-defined cache pools take precedence over the default pools created above (e.g. in rate_limiter, validation) + $this->registerCacheConfiguration($config['cache'], $container); + + // register session after cache so both can share the connection services + if ($this->isConfigEnabled($container, $config['session'])) { + if (!\extension_loaded('session')) { + throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.'); + } + + $this->sessionConfigEnabled = true; + $this->registerSessionConfiguration($config['session'], $container, $loader); + if (!empty($config['test'])) { + $container->getDefinition('test.session.listener')->setArgument(1, '%session.storage.options%'); + } + } + + // csrf depends on session being registered + if (null === $config['csrf_protection']['enabled']) { + $config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']); + } + $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); + $this->addAnnotatedClassesToCompile([ '**\\Controller\\', '**\\Entity\\', diff --git a/src/Symfony/Bundle/FrameworkBundle/LICENSE b/src/Symfony/Bundle/FrameworkBundle/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/LICENSE +++ b/src/Symfony/Bundle/FrameworkBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/SecurityBundle/LICENSE b/src/Symfony/Bundle/SecurityBundle/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bundle/SecurityBundle/LICENSE +++ b/src/Symfony/Bundle/SecurityBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/TwigBundle/LICENSE b/src/Symfony/Bundle/TwigBundle/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bundle/TwigBundle/LICENSE +++ b/src/Symfony/Bundle/TwigBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/WebProfilerBundle/LICENSE b/src/Symfony/Bundle/WebProfilerBundle/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/LICENSE +++ b/src/Symfony/Bundle/WebProfilerBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Asset/LICENSE b/src/Symfony/Component/Asset/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Asset/LICENSE +++ b/src/Symfony/Component/Asset/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/BrowserKit/LICENSE b/src/Symfony/Component/BrowserKit/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/BrowserKit/LICENSE +++ b/src/Symfony/Component/BrowserKit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Cache/LICENSE b/src/Symfony/Component/Cache/LICENSE index 3796612f43c2b..7fa9539054928 100644 --- a/src/Symfony/Component/Cache/LICENSE +++ b/src/Symfony/Component/Cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2021 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Cache/Psr16Cache.php b/src/Symfony/Component/Cache/Psr16Cache.php index c785144b1bf70..28c7de60564f8 100644 --- a/src/Symfony/Component/Cache/Psr16Cache.php +++ b/src/Symfony/Component/Cache/Psr16Cache.php @@ -19,6 +19,10 @@ use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Traits\ProxyTrait; +if (null !== (new \ReflectionMethod(CacheInterface::class, 'get'))->getReturnType()) { + throw new \LogicException('psr/simple-cache 3.0+ is not compatible with this version of symfony/cache. Please upgrade symfony/cache to 6.0+ or downgrade psr/simple-cache to 1.x or 2.x.'); +} + /** * Turns a PSR-6 cache into a PSR-16 one. * diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php index 46516e0095e6e..37282e8fceee8 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php @@ -50,6 +50,7 @@ static function (CacheItem $item, $expiry) { ); $cache = $this->createCachePool(1); + $cache->clear(); $value = rand(); $item = $cache->getItem('foo'); $setCacheItemExpiry($item, 0); diff --git a/src/Symfony/Component/Cache/Traits/ContractsTrait.php b/src/Symfony/Component/Cache/Traits/ContractsTrait.php index 9a491adb5acb8..9fdb9319edd34 100644 --- a/src/Symfony/Component/Cache/Traits/ContractsTrait.php +++ b/src/Symfony/Component/Cache/Traits/ContractsTrait.php @@ -42,7 +42,7 @@ trait ContractsTrait public function setCallbackWrapper(?callable $callbackWrapper): callable { if (!isset($this->callbackWrapper)) { - $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']); + $this->callbackWrapper = [LockRegistry::class, 'compute']; if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { $this->setCallbackWrapper(null); diff --git a/src/Symfony/Component/Cache/Traits/FilesystemCommonTrait.php b/src/Symfony/Component/Cache/Traits/FilesystemCommonTrait.php index 8e45081aefda7..c06cc309a6b3f 100644 --- a/src/Symfony/Component/Cache/Traits/FilesystemCommonTrait.php +++ b/src/Symfony/Component/Cache/Traits/FilesystemCommonTrait.php @@ -109,7 +109,7 @@ private function write(string $file, string $data, int $expiresAt = null) fclose($h); if (null !== $expiresAt) { - touch($this->tmp, $expiresAt); + touch($this->tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds } return rename($this->tmp, $file); diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index d8747f5e08ca9..e6f2512d20e91 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -189,7 +189,7 @@ public static function createConnection(string $dsn, array $options = []) $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) { $host = $hosts[0]['host'] ?? $hosts[0]['path']; - $port = $hosts[0]['port'] ?? null; + $port = $hosts[0]['port'] ?? 6379; if (isset($hosts[0]['host']) && $tls) { $host = 'tls://'.$host; diff --git a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php index f0b7a5931e29a..14387b51bbdee 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php @@ -91,7 +91,7 @@ public function ifNull() /** * Tests if the value is empty. * - * @return ExprBuilder + * @return $this */ public function ifEmpty() { diff --git a/src/Symfony/Component/Config/LICENSE b/src/Symfony/Component/Config/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Config/LICENSE +++ b/src/Symfony/Component/Config/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 9f9f8394e6bf8..c99a3f7ef6a89 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -952,6 +952,16 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); } + if (Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + + foreach ([\SIGINT, \SIGTERM] as $signal) { + $this->signalRegistry->register($signal, static function () use ($sttyMode) { + shell_exec('stty '.$sttyMode); + }); + } + } + if ($this->dispatcher) { foreach ($this->signalsToDispatchEvent as $signal) { $event = new ConsoleSignalEvent($command, $input, $output, $signal); diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 80d59b3b4d155..3fedc2fe53c90 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -34,13 +34,13 @@ public function __clone() } /** - * Escapes "<" special char in given text. + * Escapes "<" and ">" special chars in given text. * * @return string Escaped text */ public static function escape(string $text) { - $text = preg_replace('/([^\\\\]?)])/', '$1\\\\$2', $text); return self::escapeTrailingBackslash($text); } @@ -142,9 +142,10 @@ public function formatAndWrap(?string $message, int $width) { $offset = 0; $output = ''; - $tagRegex = '[a-z][^<>]*+'; + $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*'; + $closeTagRegex = '[a-z][^<>]*+'; $currentLineLength = 0; - preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); + preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; @@ -178,11 +179,7 @@ public function formatAndWrap(?string $message, int $width) $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); - if (str_contains($output, "\0")) { - return strtr($output, ["\0" => '\\', '\\<' => '<']); - } - - return str_replace('\\<', '<', $output); + return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); } /** @@ -216,7 +213,8 @@ private function createStyleFromString(string $string): ?OutputFormatterStyleInt } elseif ('bg' == $match[0]) { $style->setBackground(strtolower($match[1])); } elseif ('href' === $match[0]) { - $style->setHref($match[1]); + $url = preg_replace('{\\\\([<>])}', '$1', $match[1]); + $style->setHref($url); } elseif ('options' === $match[0]) { preg_match_all('([^,;]+)', strtolower($match[1]), $options); $options = array_shift($options); diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 28931358dd68b..97b0ef854f9d7 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -248,6 +248,9 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu $numMatches = \count($matches); $sttyMode = shell_exec('stty -g'); + $isStdin = 'php://stdin' === (stream_get_meta_data($inputStream)['uri'] ?? null); + $r = [$inputStream]; + $w = []; // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); @@ -257,11 +260,15 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu // Read a keypress while (!feof($inputStream)) { + while ($isStdin && 0 === @stream_select($r, $w, $w, 0, 100)) { + // Give signal handlers a chance to run + $r = [$inputStream]; + } $c = fread($inputStream, 1); // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { - shell_exec(sprintf('stty %s', $sttyMode)); + shell_exec('stty '.$sttyMode); throw new MissingInputException('Aborted.'); } elseif ("\177" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { @@ -366,7 +373,7 @@ function ($match) use ($ret) { } // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); + shell_exec('stty '.$sttyMode); return $fullChoice; } @@ -427,7 +434,7 @@ private function getHiddenResponse(OutputInterface $output, $inputStream, bool $ $value = fgets($inputStream, 4096); if (self::$stty && Terminal::hasSttyAvailable()) { - shell_exec(sprintf('stty %s', $sttyMode)); + shell_exec('stty '.$sttyMode); } if (false === $value) { @@ -482,11 +489,11 @@ private function isInteractiveInput($inputStream): bool } if (\function_exists('stream_isatty')) { - return self::$stdinIsInteractive = stream_isatty(fopen('php://stdin', 'r')); + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); } if (\function_exists('posix_isatty')) { - return self::$stdinIsInteractive = posix_isatty(fopen('php://stdin', 'r')); + return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); } if (!\function_exists('exec')) { diff --git a/src/Symfony/Component/Console/Input/StringInput.php b/src/Symfony/Component/Console/Input/StringInput.php index eb5c07fddffb4..76f1d5030a7a7 100644 --- a/src/Symfony/Component/Console/Input/StringInput.php +++ b/src/Symfony/Component/Console/Input/StringInput.php @@ -24,7 +24,7 @@ */ class StringInput extends ArgvInput { - public const REGEX_STRING = '([^\s]+?)(?:\s|(?hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); + if (!$this->hasStderrSupport()) { + return fopen('php://output', 'w'); + } + + // Use STDERR when possible to prevent from opening too many file descriptors + return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w')); } } diff --git a/src/Symfony/Component/Console/Question/ChoiceQuestion.php b/src/Symfony/Component/Console/Question/ChoiceQuestion.php index 92b6e8663fdc3..bf1f904878d9f 100644 --- a/src/Symfony/Component/Console/Question/ChoiceQuestion.php +++ b/src/Symfony/Component/Console/Question/ChoiceQuestion.php @@ -125,18 +125,18 @@ private function getDefaultValidator(): callable return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { if ($multiselect) { // Check for a separated comma values - if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) { throw new InvalidArgumentException(sprintf($errorMessage, $selected)); } - $selectedChoices = explode(',', $selected); + $selectedChoices = explode(',', (string) $selected); } else { $selectedChoices = [$selected]; } if ($this->isTrimmable()) { foreach ($selectedChoices as $k => $v) { - $selectedChoices[$k] = trim($v); + $selectedChoices[$k] = trim((string) $v); } } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 5421305693149..15319c3d43dd2 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -38,9 +38,11 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\SignalRegistry\SignalRegistry; +use Symfony\Component\Console\Terminal; use Symfony\Component\Console\Tester\ApplicationTester; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Process\Process; class ApplicationTest extends TestCase { @@ -1882,6 +1884,39 @@ public function testSignalableCommandInterfaceWithoutSignals() $application->add($command); $this->assertSame(0, $application->run(new ArrayInput(['signal']))); } + + /** + * @group tty + */ + public function testSignalableRestoresStty() + { + if (!Terminal::hasSttyAvailable()) { + $this->markTestSkipped('stty not available'); + } + + if (!SignalRegistry::isSupported()) { + $this->markTestSkipped('pcntl signals not available'); + } + + $previousSttyMode = shell_exec('stty -g'); + + $p = new Process(['php', __DIR__.'/Fixtures/application_signalable.php']); + $p->setTty(true); + $p->start(); + + for ($i = 0; $i < 10 && shell_exec('stty -g') === $previousSttyMode; ++$i) { + usleep(100000); + } + + $this->assertNotSame($previousSttyMode, shell_exec('stty -g')); + $p->signal(\SIGINT); + $p->wait(); + + $sttyMode = shell_exec('stty -g'); + shell_exec('stty '.$previousSttyMode); + + $this->assertSame($previousSttyMode, $sttyMode); + } } class CustomApplication extends Application diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_signalable.php b/src/Symfony/Component/Console/Tests/Fixtures/application_signalable.php new file mode 100644 index 0000000000000..0194703b2fe01 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_signalable.php @@ -0,0 +1,36 @@ +setCode(function(InputInterface $input, OutputInterface $output) { + $this->getHelper('question') + ->ask($input, $output, new ChoiceQuestion('😊', ['y'])); + + return 0; + }) + ->run() + +; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt index 45e7bec4d9d7e..fcab77a29e19a 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt @@ -2,9 +2,9 @@ command 2 description Usage: - descriptor:command2 [options] [--] \ - descriptor:command2 -o|--option_name \ - descriptor:command2 \ + descriptor:command2 [options] [--] \ + descriptor:command2 -o|--option_name \ + descriptor:command2 \ Arguments: argument_name diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt index 2fd51d057cf62..1fa4e3135fa23 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt @@ -2,9 +2,9 @@ command åèä description Usage: - descriptor:åèä [options] [--] \ - descriptor:åèä -o|--option_name \ - descriptor:åèä \ + descriptor:åèä [options] [--] \ + descriptor:åèä -o|--option_name \ + descriptor:åèä \ Arguments: argument_åèä diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_style.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_style.txt index 35384a6be87e7..79149ca69866a 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_style.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_style.txt @@ -1 +1 @@ - argument_name argument description [default: "\style\"] + argument_name argument description [default: "\style\"] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style.txt index 880a53518e214..4bd30a662f4c3 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style.txt @@ -1 +1 @@ - -o, --option_name=OPTION_NAME option description [default: "\style\"] + -o, --option_name=OPTION_NAME option description [default: "\style\"] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style_array.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style_array.txt index 265c18c5a45d2..1fbb05b8a9ec7 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style_array.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_style_array.txt @@ -1 +1 @@ - -o, --option_name=OPTION_NAME option description [default: ["\Hello\","\world\"]] (multiple values allowed) + -o, --option_name=OPTION_NAME option description [default: ["\Hello\","\world\"]] (multiple values allowed) diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 1a6aae23ef228..3ad18b8978b6c 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -32,7 +32,10 @@ public function testLGCharEscaping() $this->assertEquals('foo << bar \\', $formatter->format('foo << bar \\')); $this->assertEquals("foo << \033[32mbar \\ baz\033[39m \\", $formatter->format('foo << bar \\ baz \\')); $this->assertEquals('some info', $formatter->format('\\some info\\')); - $this->assertEquals('\\some info\\', OutputFormatter::escape('some info')); + $this->assertEquals('\\some info\\', OutputFormatter::escape('some info')); + // every < and > gets escaped if not already escaped, but already escaped ones do not get escaped again + // and escaped backslashes remain as such, same with backslashes escaping non-special characters + $this->assertEquals('foo \\< bar \\< baz \\\\< foo \\> bar \\> baz \\\\> \\x', OutputFormatter::escape('foo < bar \\< baz \\\\< foo > bar \\> baz \\\\> \\x')); $this->assertEquals( "\033[33mSymfony\\Component\\Console does work very well!\033[39m", @@ -264,6 +267,7 @@ public function provideDecoratedAndNonDecoratedOutput() ['some question', 'some question', "\033[30;46msome question\033[39;49m"], ['some text with inline style', 'some text with inline style', "\033[31msome text with inline style\033[39m"], ['some URL', 'some URL', "\033]8;;idea://open/?file=/path/SomeFile.php&line=12\033\\some URL\033]8;;\033\\"], + ['>some URL with \', 'some URL with ', "\033]8;;https://example.com/\033\\some URL with \033]8;;\033\\"], ['some URL', 'some URL', 'some URL', 'JetBrains-JediTerm'], ]; } diff --git a/src/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php index 934e11ac1b0a3..c9a3c5e001d7a 100644 --- a/src/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php @@ -83,9 +83,9 @@ public function testFormatBlockLGEscaping() $formatter = new FormatterHelper(); $this->assertEquals( - ' '."\n". - ' \some info\ '."\n". - ' ', + ' '."\n". + ' \some info\ '."\n". + ' ', $formatter->formatBlock('some info', 'error', true), '::formatBlock() escapes \'<\' chars' ); diff --git a/src/Symfony/Component/Console/Tests/Input/StringInputTest.php b/src/Symfony/Component/Console/Tests/Input/StringInputTest.php index f781b7ccfa174..2bd40dec9c365 100644 --- a/src/Symfony/Component/Console/Tests/Input/StringInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/StringInputTest.php @@ -71,6 +71,7 @@ public function getTokenizeData() ["--long-option='foo bar''another'", ['--long-option=foo baranother'], '->tokenize() parses long options with a value'], ["--long-option='foo bar'\"another\"", ['--long-option=foo baranother'], '->tokenize() parses long options with a value'], ['foo -a -ffoo --long bar', ['foo', '-a', '-ffoo', '--long', 'bar'], '->tokenize() parses when several arguments and options'], + ["--arg=\\\"'Jenny'\''s'\\\"", ["--arg=\"Jenny's\""], '->tokenize() parses quoted quotes'], ]; } diff --git a/src/Symfony/Component/Console/Tests/Question/ChoiceQuestionTest.php b/src/Symfony/Component/Console/Tests/Question/ChoiceQuestionTest.php index 18063eaac90d7..a7a2dfba487a6 100644 --- a/src/Symfony/Component/Console/Tests/Question/ChoiceQuestionTest.php +++ b/src/Symfony/Component/Console/Tests/Question/ChoiceQuestionTest.php @@ -19,14 +19,15 @@ class ChoiceQuestionTest extends TestCase /** * @dataProvider selectUseCases */ - public function testSelectUseCases($multiSelect, $answers, $expected, $message) + public function testSelectUseCases($multiSelect, $answers, $expected, $message, $default = null) { $question = new ChoiceQuestion('A question', [ 'First response', 'Second response', 'Third response', 'Fourth response', - ]); + null, + ], $default); $question->setMultiselect($multiSelect); @@ -59,6 +60,19 @@ public function selectUseCases() ['First response', 'Second response'], 'When passed multiple answers on MultiSelect, the defaultValidator must return these answers as an array', ], + [ + false, + [null], + null, + 'When used null as default single answer on singleSelect, the defaultValidator must return this answer as null', + ], + [ + false, + ['First response'], + 'First response', + 'When used a string as default single answer on singleSelect, the defaultValidator must return this answer as a string', + 'First response', + ], [ false, [0], diff --git a/src/Symfony/Component/CssSelector/LICENSE b/src/Symfony/Component/CssSelector/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/CssSelector/LICENSE +++ b/src/Symfony/Component/CssSelector/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index f8ec9214de425..b7ec85cefb489 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -210,6 +210,10 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar $class = null; if ($value instanceof Definition) { + if ($value->getFactory()) { + return; + } + $class = $value->getClass(); if ($class && isset(self::BUILTIN_TYPES[strtolower($class)])) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index c71ea503bfc0b..5bc379153a19e 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -126,7 +126,7 @@ protected function processValue($value, bool $isRoot = false) $this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file]; } - if (preg_match('/^(?:(?:array|bool|float|int|string|([^ $]++)) )\$/', $key, $m)) { + if (preg_match('/^(?:(?:array|bool|float|int|string|iterable|([^ $]++)) )\$/', $key, $m)) { $bindingNames[substr($key, \strlen($m[0]))] = $binding; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index a1b2c86e3d0de..46a2d7882cf89 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -115,6 +115,8 @@ private function doResolveDefinition(ChildDefinition $definition): Definition $def->setBindings($definition->getBindings() + $parentDef->getBindings()); + $def->setSynthetic($definition->isSynthetic()); + // overwrite with values specified in the decorator $changes = $definition->getChanges(); if (isset($changes['class'])) { diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index 8a454e9f00722..77ac210217cf9 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -272,11 +272,17 @@ public function getEnv(string $prefix, string $name, \Closure $getEnv) } if ('resolve' === $prefix) { - return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) { + return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name, $getEnv) { if (!isset($match[1])) { return '%'; } - $value = $this->container->getParameter($match[1]); + + if (str_starts_with($match[1], 'env(') && str_ends_with($match[1], ')') && 'env()' !== $match[1]) { + $value = $getEnv(substr($match[1], 4, -1)); + } else { + $value = $this->container->getParameter($match[1]); + } + if (!is_scalar($value)) { throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, get_debug_type($value))); } diff --git a/src/Symfony/Component/DependencyInjection/LICENSE b/src/Symfony/Component/DependencyInjection/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/DependencyInjection/LICENSE +++ b/src/Symfony/Component/DependencyInjection/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php index 573b6f53a291d..3021e07088ddd 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php @@ -12,10 +12,8 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator; -use Symfony\Component\DependencyInjection\Reference; trait BindTrait { @@ -34,9 +32,6 @@ trait BindTrait final public function bind(string $nameOrFqcn, $valueOrRef): self { $valueOrRef = static::processValue($valueOrRef, true); - if (!preg_match('/^(?:(?:array|bool|float|int|string|iterable)[ \t]*+)?\$/', $nameOrFqcn) && !$valueOrRef instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn)); - } $bindings = $this->definition->getBindings(); $type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING); $bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, true, $type, $this->path ?? null); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index 38538f27b0f9f..97e167c99cb10 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -996,6 +996,20 @@ public function testCallableClass() $this->addToAssertionCount(1); } + + public function testIgnoreDefinitionFactoryArgument() + { + $container = new ContainerBuilder(); + $container->register('bar', Bar::class) + ->setArguments([ + (new Definition(Foo::class)) + ->setFactory([Foo::class, 'createStdClass']), + ]); + + (new CheckTypeDeclarationsPass())->process($container); + + $this->addToAssertionCount(1); + } } class CallableClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php index 3ddad62d0e5d7..fc48bf0723312 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -28,6 +28,7 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedEnumArgumentDummy; +use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedIterableArgumentDummy; use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists; use Symfony\Component\DependencyInjection\Tests\Fixtures\WithTarget; use Symfony\Component\DependencyInjection\TypedReference; @@ -212,6 +213,28 @@ public function testEmptyBindingTypehint() $pass->process($container); } + public function testIterableBindingTypehint() + { + $autoloader = static function ($class) { + if ('iterable' === $class) { + throw new \RuntimeException('We should not search pseudo-type iterable as class'); + } + }; + spl_autoload_register($autoloader); + + $container = new ContainerBuilder(); + $definition = $container->register('bar', NamedIterableArgumentDummy::class); + $definition->setBindings([ + 'iterable $items' => new TaggedIteratorArgument('foo'), + ]); + $pass = new ResolveBindingsPass(); + $pass->process($container); + + $this->assertInstanceOf(TaggedIteratorArgument::class, $container->getDefinition('bar')->getArgument(0)); + + spl_autoload_unregister($autoloader); + } + /** * @requires PHP 8 */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php index f35d7af581b7b..887e2b1524855 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php @@ -421,4 +421,21 @@ public function testProcessDetectsChildDefinitionIndirectCircularReference() $this->process($container); } + + public function testProcessCopiesSyntheticStatus() + { + $container = new ContainerBuilder(); + + $container->register('parent'); + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ->setSynthetic(true) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertTrue($def->isSynthetic()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php b/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php index 0b84145beda02..5885a9190b615 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php @@ -506,6 +506,109 @@ public function testRequireFile() $this->assertEquals('foo', $result); } + /** + * @dataProvider validResolve + */ + public function testGetEnvResolve($value, $processed) + { + $container = new ContainerBuilder(); + $container->setParameter('bar', $value); + $container->compile(); + + $processor = new EnvVarProcessor($container); + + $result = $processor->getEnv('resolve', 'foo', function () { + return '%bar%'; + }); + + $this->assertSame($processed, $result); + } + + public function validResolve() + { + return [ + ['string', 'string'], + [1, '1'], + [1.1, '1.1'], + [true, '1'], + [false, ''], + ]; + } + + public function testGetEnvResolveNoMatch() + { + $processor = new EnvVarProcessor(new Container()); + + $result = $processor->getEnv('resolve', 'foo', function () { + return '%%'; + }); + + $this->assertSame('%', $result); + } + + /** + * @dataProvider notScalarResolve + */ + public function testGetEnvResolveNotScalar($value) + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Parameter "bar" found when resolving env var "foo" must be scalar'); + + $container = new ContainerBuilder(); + $container->setParameter('bar', $value); + $container->compile(); + + $processor = new EnvVarProcessor($container); + + $processor->getEnv('resolve', 'foo', function () { + return '%bar%'; + }); + } + + public function notScalarResolve() + { + return [ + [null], + [[]], + ]; + } + + public function testGetEnvResolveNestedEnv() + { + $container = new ContainerBuilder(); + $container->setParameter('env(BAR)', 'BAR in container'); + $container->compile(); + + $processor = new EnvVarProcessor($container); + $getEnv = \Closure::fromCallable([$processor, 'getEnv']); + + $result = $processor->getEnv('resolve', 'foo', function ($name) use ($getEnv) { + return 'foo' === $name ? '%env(BAR)%' : $getEnv('string', $name, function () {}); + }); + + $this->assertSame('BAR in container', $result); + } + + public function testGetEnvResolveNestedRealEnv() + { + $_ENV['BAR'] = 'BAR in environment'; + + $container = new ContainerBuilder(); + $container->setParameter('env(BAR)', 'BAR in container'); + $container->compile(); + + $processor = new EnvVarProcessor($container); + $getEnv = \Closure::fromCallable([$processor, 'getEnv']); + + $result = $processor->getEnv('resolve', 'foo', function ($name) use ($getEnv) { + return 'foo' === $name ? '%env(BAR)%' : $getEnv('string', $name, function () {}); + }); + + $this->assertSame('BAR in environment', $result); + + unset($_ENV['BAR']); + } + /** * @dataProvider validCsv */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/Foo.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/Foo.php index be92ec5c297f4..e775def689305 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/Foo.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/Foo.php @@ -23,4 +23,9 @@ public static function createArray(): array { return []; } + + public static function createStdClass(): \stdClass + { + return new \stdClass(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedIterableArgumentDummy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedIterableArgumentDummy.php new file mode 100644 index 0000000000000..c2c9290df3473 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedIterableArgumentDummy.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Fixtures; + +class NamedIterableArgumentDummy +{ + public function __construct(iterable $items) + { + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php index 2ac1f3f02e95e..49545a8dfa2e6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php @@ -8,7 +8,7 @@ #[When(env: 'dev')] class Foo implements FooInterface, Sub\BarInterface { - public function __construct($bar = null, iterable $foo = null) + public function __construct($bar = null, iterable $foo = null, object $baz = null) { } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.expected.yml new file mode 100644 index 0000000000000..9c4ef3ca9d52a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.expected.yml @@ -0,0 +1,28 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + App\BarService: + class: App\BarService + public: true + arguments: [!service { class: FooClass }] + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + tags: + - t: { a: b } + autowire: true + autoconfigure: true + arguments: ['@bar', !tagged_iterator foo, !service { class: Baz }] + bar: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + tags: + - t: { a: b } + autowire: true + arguments: [null, !tagged_iterator foo, !service { class: Baz }] + calls: + - [setFoo, ['@bar']] + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.php new file mode 100644 index 0000000000000..1542285cb3fb7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/inline_binding.php @@ -0,0 +1,23 @@ +import('basic.php'); + + $s = $c->services()->defaults() + ->public() + ->private() + ->autoconfigure() + ->autowire() + ->tag('t', ['a' => 'b']) + ->bind(Foo::class, service('bar')) + ->bind('iterable $foo', tagged_iterator('foo')) + ->bind('object $baz', inline_service('Baz')) + ->public(); + + $s->set(Foo::class)->args([service('bar')])->public(); + $s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false); +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index f3dcb820f81fd..195971624f83a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -86,6 +86,7 @@ public function provideConfig() yield ['php7']; yield ['anonymous']; yield ['lazy_fqcn']; + yield ['inline_binding']; yield ['remove']; yield ['config_builder']; } diff --git a/src/Symfony/Component/DomCrawler/LICENSE b/src/Symfony/Component/DomCrawler/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/DomCrawler/LICENSE +++ b/src/Symfony/Component/DomCrawler/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Dotenv/LICENSE b/src/Symfony/Component/Dotenv/LICENSE index 3796612f43c2b..7fa9539054928 100644 --- a/src/Symfony/Component/Dotenv/LICENSE +++ b/src/Symfony/Component/Dotenv/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2021 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/ErrorHandler/LICENSE b/src/Symfony/Component/ErrorHandler/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/ErrorHandler/LICENSE +++ b/src/Symfony/Component/ErrorHandler/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/EventDispatcher/LICENSE b/src/Symfony/Component/EventDispatcher/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/EventDispatcher/LICENSE +++ b/src/Symfony/Component/EventDispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/ExpressionLanguage/LICENSE b/src/Symfony/Component/ExpressionLanguage/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/ExpressionLanguage/LICENSE +++ b/src/Symfony/Component/ExpressionLanguage/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Filesystem/LICENSE b/src/Symfony/Component/Filesystem/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Filesystem/LICENSE +++ b/src/Symfony/Component/Filesystem/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Finder/LICENSE b/src/Symfony/Component/Finder/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Finder/LICENSE +++ b/src/Symfony/Component/Finder/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php index 53dd4ee8711d2..b44d217ea3214 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php @@ -36,7 +36,7 @@ public function onSubmit(FormEvent $event) { $data = $event->getData(); - if ($this->defaultProtocol && $data && \is_string($data) && !preg_match('~^[\w+.-]+://~', $data)) { + if ($this->defaultProtocol && $data && \is_string($data) && !preg_match('~^([\w+.-]+://|[^:/?@#]++@)~', $data)) { $event->setData($this->defaultProtocol.'://'.$data); } } diff --git a/src/Symfony/Component/Form/LICENSE b/src/Symfony/Component/Form/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Form/LICENSE +++ b/src/Symfony/Component/Form/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index e00cb9e9e1978..55fee6e2243ee 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -20,45 +20,49 @@ class FixUrlProtocolListenerTest extends TestCase { - public function testFixHttpUrl() + public function provideUrlToFix() { - $data = 'www.symfony.com'; - $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); - $event = new FormEvent($form, $data); - - $filter = new FixUrlProtocolListener('http'); - $filter->onSubmit($event); - - $this->assertEquals('http://www.symfony.com', $event->getData()); + return [ + ['www.symfony.com'], + ['twitter.com/@symfony'], + ['symfony.com?foo@bar'], + ['symfony.com#foo@bar'], + ['localhost'], + ]; } - public function testSkipKnownUrl() + /** + * @dataProvider provideUrlToFix + */ + public function testFixUrl($data) { - $data = 'http://www.symfony.com'; $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); - $this->assertEquals('http://www.symfony.com', $event->getData()); + $this->assertEquals('http://'.$data, $event->getData()); } - public function provideUrlsWithSupportedProtocols() + public function provideUrlToSkip() { return [ + ['http://www.symfony.com'], ['ftp://www.symfony.com'], + ['https://twitter.com/@symfony'], ['chrome-extension://foo'], ['h323://foo'], ['iris.beep://foo'], ['foo+bar://foo'], + ['fabien@symfony.com'], ]; } /** - * @dataProvider provideUrlsWithSupportedProtocols + * @dataProvider provideUrlToSkip */ - public function testSkipOtherProtocol($url) + public function testSkipUrl($url) { $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $url); diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 2821e10df8465..d18a3d36b1959 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -171,7 +171,6 @@ public function request(string $method, string $url, array $options = []): Respo if ($resolve && 0x072A00 > CurlClientState::$curlVersion['version_number']) { // DNS cache removals require curl 7.42 or higher - // On lower versions, we have to create a new multi handle $this->multi->reset(); } @@ -288,6 +287,7 @@ public function request(string $method, string $url, array $options = []): Respo if (!$pushedResponse) { $ch = curl_init(); $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url)); + $curlopts += [\CURLOPT_SHARE => $this->multi->share]; } foreach ($curlopts as $opt => $value) { @@ -311,9 +311,9 @@ public function stream($responses, float $timeout = null): ResponseStreamInterfa throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of CurlResponse objects, "%s" given.', __METHOD__, get_debug_type($responses))); } - if (\is_resource($mh = $this->multi->handles[0] ?? null) || $mh instanceof \CurlMultiHandle) { + if (\is_resource($this->multi->handle) || $this->multi->handle instanceof \CurlMultiHandle) { $active = 0; - while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($mh, $active)) { + while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($this->multi->handle, $active)) { } } diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 753a549c35d20..b5235c8ba8e98 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -159,7 +159,10 @@ private static function prepareRequest(?string $method, ?string $url, array $opt // Finalize normalization of options $options['http_version'] = (string) ($options['http_version'] ?? '') ?: null; - $options['timeout'] = (float) ($options['timeout'] ?? ini_get('default_socket_timeout')); + if (0 > $options['timeout'] = (float) ($options['timeout'] ?? ini_get('default_socket_timeout'))) { + $options['timeout'] = 172800.0; // 2 days + } + $options['max_duration'] = isset($options['max_duration']) ? (float) $options['max_duration'] : 0; return [$url, $options]; diff --git a/src/Symfony/Component/HttpClient/HttplugClient.php b/src/Symfony/Component/HttpClient/HttplugClient.php index 7be016da9d8e9..1014500ff4f1a 100644 --- a/src/Symfony/Component/HttpClient/HttplugClient.php +++ b/src/Symfony/Component/HttpClient/HttplugClient.php @@ -13,6 +13,7 @@ use GuzzleHttp\Promise\Promise as GuzzlePromise; use GuzzleHttp\Promise\RejectedPromise; +use GuzzleHttp\Promise\Utils; use Http\Client\Exception\NetworkException; use Http\Client\Exception\RequestException; use Http\Client\HttpAsyncClient; @@ -69,7 +70,7 @@ public function __construct(HttpClientInterface $client = null, ResponseFactoryI $this->client = $client ?? HttpClient::create(); $this->responseFactory = $responseFactory; $this->streamFactory = $streamFactory ?? ($responseFactory instanceof StreamFactoryInterface ? $responseFactory : null); - $this->promisePool = \function_exists('GuzzleHttp\Promise\queue') ? new \SplObjectStorage() : null; + $this->promisePool = class_exists(Utils::class) ? new \SplObjectStorage() : null; if (null === $this->responseFactory || null === $this->streamFactory) { if (!class_exists(Psr17Factory::class) && !class_exists(Psr17FactoryDiscovery::class)) { diff --git a/src/Symfony/Component/HttpClient/Internal/CurlClientState.php b/src/Symfony/Component/HttpClient/Internal/CurlClientState.php index 065e05e173c83..958a00a8819cb 100644 --- a/src/Symfony/Component/HttpClient/Internal/CurlClientState.php +++ b/src/Symfony/Component/HttpClient/Internal/CurlClientState.php @@ -23,8 +23,10 @@ */ final class CurlClientState extends ClientState { - /** @var array<\CurlMultiHandle|resource> */ - public $handles = []; + /** @var \CurlMultiHandle|resource|null */ + public $handle; + /** @var \CurlShareHandle|resource|null */ + public $share; /** @var PushedResponse[] */ public $pushedResponses = []; /** @var DnsCache */ @@ -37,27 +39,23 @@ final class CurlClientState extends ClientState public static $curlVersion; - private $maxHostConnections; - private $maxPendingPushes; - public function __construct(int $maxHostConnections, int $maxPendingPushes) { self::$curlVersion = self::$curlVersion ?? curl_version(); - array_unshift($this->handles, $mh = curl_multi_init()); + $this->handle = curl_multi_init(); $this->dnsCache = new DnsCache(); - $this->maxHostConnections = $maxHostConnections; - $this->maxPendingPushes = $maxPendingPushes; + $this->reset(); // Don't enable HTTP/1.1 pipelining: it forces responses to be sent in order if (\defined('CURLPIPE_MULTIPLEX')) { - curl_multi_setopt($mh, \CURLMOPT_PIPELINING, \CURLPIPE_MULTIPLEX); + curl_multi_setopt($this->handle, \CURLMOPT_PIPELINING, \CURLPIPE_MULTIPLEX); } if (\defined('CURLMOPT_MAX_HOST_CONNECTIONS')) { - $maxHostConnections = curl_multi_setopt($mh, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? 0 : $maxHostConnections; + $maxHostConnections = curl_multi_setopt($this->handle, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? 0 : $maxHostConnections; } if (\defined('CURLMOPT_MAXCONNECTS') && 0 < $maxHostConnections) { - curl_multi_setopt($mh, \CURLMOPT_MAXCONNECTS, $maxHostConnections); + curl_multi_setopt($this->handle, \CURLMOPT_MAXCONNECTS, $maxHostConnections); } // Skip configuring HTTP/2 push when it's unsupported or buggy, see https://bugs.php.net/77535 @@ -72,14 +70,14 @@ public function __construct(int $maxHostConnections, int $maxPendingPushes) // Clone to prevent a circular reference $multi = clone $this; - $multi->handles = [$mh]; + $multi->handle = null; + $multi->share = null; $multi->pushedResponses = &$this->pushedResponses; $multi->logger = &$this->logger; $multi->handlesActivity = &$this->handlesActivity; $multi->openHandles = &$this->openHandles; - $multi->lastTimeout = &$this->lastTimeout; - curl_multi_setopt($mh, \CURLMOPT_PUSHFUNCTION, static function ($parent, $pushed, array $requestHeaders) use ($multi, $maxPendingPushes) { + curl_multi_setopt($this->handle, \CURLMOPT_PUSHFUNCTION, static function ($parent, $pushed, array $requestHeaders) use ($multi, $maxPendingPushes) { return $multi->handlePush($parent, $pushed, $requestHeaders, $maxPendingPushes); }); } @@ -88,10 +86,7 @@ public function reset() { foreach ($this->pushedResponses as $url => $response) { $this->logger && $this->logger->debug(sprintf('Unused pushed response: "%s"', $url)); - - foreach ($this->handles as $mh) { - curl_multi_remove_handle($mh, $response->handle); - } + curl_multi_remove_handle($this->handle, $response->handle); curl_close($response->handle); } @@ -99,11 +94,14 @@ public function reset() $this->dnsCache->evictions = $this->dnsCache->evictions ?: $this->dnsCache->removals; $this->dnsCache->removals = $this->dnsCache->hostnames = []; - if (\defined('CURLMOPT_PUSHFUNCTION')) { - curl_multi_setopt($this->handles[0], \CURLMOPT_PUSHFUNCTION, null); - } + $this->share = curl_share_init(); + + curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_DNS); + curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_SSL_SESSION); - $this->__construct($this->maxHostConnections, $this->maxPendingPushes); + if (\defined('CURL_LOCK_DATA_CONNECT')) { + curl_share_setopt($this->share, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_CONNECT); + } } private function handlePush($parent, $pushed, array $requestHeaders, int $maxPendingPushes): int diff --git a/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php b/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php index dc3ea7fbb4504..7316e1eef96fe 100644 --- a/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php +++ b/src/Symfony/Component/HttpClient/Internal/HttplugWaitLoop.php @@ -47,7 +47,7 @@ public function wait(?ResponseInterface $pendingResponse, float $maxDuration = n return 0; } - $guzzleQueue = \GuzzleHttp\Promise\queue(); + $guzzleQueue = \GuzzleHttp\Promise\Utils::queue(); if (0.0 === $remainingDuration = $maxDuration) { $idleTimeout = 0.0; diff --git a/src/Symfony/Component/HttpClient/LICENSE b/src/Symfony/Component/HttpClient/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/HttpClient/LICENSE +++ b/src/Symfony/Component/HttpClient/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/HttpClient/Response/CurlResponse.php b/src/Symfony/Component/HttpClient/Response/CurlResponse.php index 14fc0c3e4205e..65b425f1ff0ab 100644 --- a/src/Symfony/Component/HttpClient/Response/CurlResponse.php +++ b/src/Symfony/Component/HttpClient/Response/CurlResponse.php @@ -106,9 +106,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null, if (0 < $duration) { if ($execCounter === $multi->execCounter) { $multi->execCounter = !\is_float($execCounter) ? 1 + $execCounter : \PHP_INT_MIN; - foreach ($multi->handles as $mh) { - curl_multi_remove_handle($mh, $ch); - } + curl_multi_remove_handle($multi->handle, $ch); } $lastExpiry = end($multi->pauseExpiries); @@ -120,7 +118,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null, } else { unset($multi->pauseExpiries[(int) $ch]); curl_pause($ch, \CURLPAUSE_CONT); - curl_multi_add_handle($multi->handles[0], $ch); + curl_multi_add_handle($multi->handle, $ch); } }; @@ -174,7 +172,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null, // Schedule the request in a non-blocking way $multi->lastTimeout = null; $multi->openHandles[$id] = [$ch, $options]; - curl_multi_add_handle($multi->handles[0], $ch); + curl_multi_add_handle($multi->handle, $ch); $this->canary = new Canary(static function () use ($ch, $multi, $id) { unset($multi->pauseExpiries[$id], $multi->openHandles[$id], $multi->handlesActivity[$id]); @@ -184,9 +182,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null, return; } - foreach ($multi->handles as $mh) { - curl_multi_remove_handle($mh, $ch); - } + curl_multi_remove_handle($multi->handle, $ch); curl_setopt_array($ch, [ \CURLOPT_NOPROGRESS => true, \CURLOPT_PROGRESSFUNCTION => null, @@ -268,7 +264,7 @@ public function __destruct() */ private static function schedule(self $response, array &$runningResponses): void { - if (isset($runningResponses[$i = (int) $response->multi->handles[0]])) { + if (isset($runningResponses[$i = (int) $response->multi->handle])) { $runningResponses[$i][1][$response->id] = $response; } else { $runningResponses[$i] = [$response->multi, [$response->id => $response]]; @@ -301,47 +297,39 @@ private static function perform(ClientState $multi, array &$responses = null): v try { self::$performing = true; ++$multi->execCounter; + $active = 0; + while (\CURLM_CALL_MULTI_PERFORM === ($err = curl_multi_exec($multi->handle, $active))) { + } - foreach ($multi->handles as $i => $mh) { - $active = 0; - while (\CURLM_CALL_MULTI_PERFORM === ($err = curl_multi_exec($mh, $active))) { - } + if (\CURLM_OK !== $err) { + throw new TransportException(curl_multi_strerror($err)); + } - if (\CURLM_OK !== $err) { - throw new TransportException(curl_multi_strerror($err)); + while ($info = curl_multi_info_read($multi->handle)) { + if (\CURLMSG_DONE !== $info['msg']) { + continue; } + $result = $info['result']; + $id = (int) $ch = $info['handle']; + $waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0'; - while ($info = curl_multi_info_read($mh)) { - if (\CURLMSG_DONE !== $info['msg']) { - continue; - } - $result = $info['result']; - $id = (int) $ch = $info['handle']; - $waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0'; - - if (\in_array($result, [\CURLE_SEND_ERROR, \CURLE_RECV_ERROR, /*CURLE_HTTP2*/ 16, /*CURLE_HTTP2_STREAM*/ 92], true) && $waitFor[1] && 'C' !== $waitFor[0]) { - curl_multi_remove_handle($mh, $ch); - $waitFor[1] = (string) ((int) $waitFor[1] - 1); // decrement the retry counter - curl_setopt($ch, \CURLOPT_PRIVATE, $waitFor); - curl_setopt($ch, \CURLOPT_FORBID_REUSE, true); - - if (0 === curl_multi_add_handle($mh, $ch)) { - continue; - } - } + if (\in_array($result, [\CURLE_SEND_ERROR, \CURLE_RECV_ERROR, /*CURLE_HTTP2*/ 16, /*CURLE_HTTP2_STREAM*/ 92], true) && $waitFor[1] && 'C' !== $waitFor[0]) { + curl_multi_remove_handle($multi->handle, $ch); + $waitFor[1] = (string) ((int) $waitFor[1] - 1); // decrement the retry counter + curl_setopt($ch, \CURLOPT_PRIVATE, $waitFor); + curl_setopt($ch, \CURLOPT_FORBID_REUSE, true); - if (\CURLE_RECV_ERROR === $result && 'H' === $waitFor[0] && 400 <= ($responses[(int) $ch]->info['http_code'] ?? 0)) { - $multi->handlesActivity[$id][] = new FirstChunk(); + if (0 === curl_multi_add_handle($multi->handle, $ch)) { + continue; } - - $multi->handlesActivity[$id][] = null; - $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(sprintf('%s for "%s".', curl_strerror($result), curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); } - if (!$active && 0 < $i) { - curl_multi_close($mh); - unset($multi->handles[$i]); + if (\CURLE_RECV_ERROR === $result && 'H' === $waitFor[0] && 400 <= ($responses[(int) $ch]->info['http_code'] ?? 0)) { + $multi->handlesActivity[$id][] = new FirstChunk(); } + + $multi->handlesActivity[$id][] = null; + $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(sprintf('%s for "%s".', curl_strerror($result), curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); } } finally { self::$performing = false; @@ -371,11 +359,11 @@ private static function select(ClientState $multi, float $timeout): int unset($multi->pauseExpiries[$id]); curl_pause($multi->openHandles[$id][0], \CURLPAUSE_CONT); - curl_multi_add_handle($multi->handles[0], $multi->openHandles[$id][0]); + curl_multi_add_handle($multi->handle, $multi->openHandles[$id][0]); } } - if (0 !== $selected = curl_multi_select($multi->handles[array_key_last($multi->handles)], $timeout)) { + if (0 !== $selected = curl_multi_select($multi->handle, $timeout)) { return $selected; } diff --git a/src/Symfony/Component/HttpClient/Response/HttplugPromise.php b/src/Symfony/Component/HttpClient/Response/HttplugPromise.php index 2231464a229e8..2efacca763b8b 100644 --- a/src/Symfony/Component/HttpClient/Response/HttplugPromise.php +++ b/src/Symfony/Component/HttpClient/Response/HttplugPromise.php @@ -11,7 +11,7 @@ namespace Symfony\Component\HttpClient\Response; -use function GuzzleHttp\Promise\promise_for; +use GuzzleHttp\Promise\Create; use GuzzleHttp\Promise\PromiseInterface as GuzzlePromiseInterface; use Http\Promise\Promise as HttplugPromiseInterface; use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface; @@ -74,7 +74,7 @@ private function wrapThenCallback(?callable $callback): ?callable } return static function ($value) use ($callback) { - return promise_for($callback($value)); + return Create::promiseFor($callback($value)); }; } } diff --git a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php index 52f263a8af3c7..284a243496b91 100644 --- a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php @@ -66,9 +66,9 @@ public function testHandleIsReinitOnReset() $r = new \ReflectionProperty($httpClient, 'multi'); $r->setAccessible(true); $clientState = $r->getValue($httpClient); - $initialHandleId = (int) $clientState->handles[0]; + $initialShareId = $clientState->share; $httpClient->reset(); - self::assertNotSame($initialHandleId, (int) $clientState->handles[0]); + self::assertNotSame($initialShareId, $clientState->share); } public function testProcessAfterReset() diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php index 59e4dc1da7cc8..793053029164c 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php @@ -373,4 +373,13 @@ public function testDebugInfoOnDestruct() $this->assertNotEmpty($traceInfo['debug']); } + + public function testNegativeTimeout() + { + $client = $this->getHttpClient(__FUNCTION__); + + $this->assertSame(200, $client->request('GET', 'http://localhost:8057', [ + 'timeout' => -1, + ])->getStatusCode()); + } } diff --git a/src/Symfony/Component/HttpFoundation/LICENSE b/src/Symfony/Component/HttpFoundation/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/HttpFoundation/LICENSE +++ b/src/Symfony/Component/HttpFoundation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d94a5a971fe2c..d3f174fa4d999 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -75,11 +75,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - public const VERSION = '5.3.13'; - public const VERSION_ID = 50313; + public const VERSION = '5.3.14'; + public const VERSION_ID = 50314; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 3; - public const RELEASE_VERSION = 13; + public const RELEASE_VERSION = 14; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '01/2022'; diff --git a/src/Symfony/Component/HttpKernel/LICENSE b/src/Symfony/Component/HttpKernel/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/HttpKernel/LICENSE +++ b/src/Symfony/Component/HttpKernel/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Inflector/LICENSE b/src/Symfony/Component/Inflector/LICENSE index 28c5b8066c3c1..9f862df305075 100644 --- a/src/Symfony/Component/Inflector/LICENSE +++ b/src/Symfony/Component/Inflector/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2021 Fabien Potencier +Copyright (c) 2012-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Intl/LICENSE b/src/Symfony/Component/Intl/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Intl/LICENSE +++ b/src/Symfony/Component/Intl/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Ldap/LICENSE b/src/Symfony/Component/Ldap/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Ldap/LICENSE +++ b/src/Symfony/Component/Ldap/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Lock/LICENSE b/src/Symfony/Component/Lock/LICENSE index 3796612f43c2b..7fa9539054928 100644 --- a/src/Symfony/Component/Lock/LICENSE +++ b/src/Symfony/Component/Lock/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2021 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/LICENSE b/src/Symfony/Component/Mailer/Bridge/Amazon/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Google/LICENSE b/src/Symfony/Component/Mailer/Bridge/Google/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Google/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Google/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/LICENSE b/src/Symfony/Component/Mailer/Bridge/Mailchimp/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/LICENSE b/src/Symfony/Component/Mailer/Bridge/Mailgun/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Mailjet/LICENSE b/src/Symfony/Component/Mailer/Bridge/Mailjet/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailjet/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Mailjet/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Postmark/LICENSE b/src/Symfony/Component/Mailer/Bridge/Postmark/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Postmark/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Postmark/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/LICENSE b/src/Symfony/Component/Mailer/Bridge/Sendgrid/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/Bridge/Sendinblue/LICENSE b/src/Symfony/Component/Mailer/Bridge/Sendinblue/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendinblue/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Sendinblue/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mailer/LICENSE b/src/Symfony/Component/Mailer/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Mailer/LICENSE +++ b/src/Symfony/Component/Mailer/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/LICENSE b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/LICENSE +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/LICENSE b/src/Symfony/Component/Messenger/Bridge/Amqp/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/LICENSE +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Bridge/Beanstalkd/LICENSE b/src/Symfony/Component/Messenger/Bridge/Beanstalkd/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/Messenger/Bridge/Beanstalkd/LICENSE +++ b/src/Symfony/Component/Messenger/Bridge/Beanstalkd/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/LICENSE b/src/Symfony/Component/Messenger/Bridge/Doctrine/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/LICENSE +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Bridge/Redis/LICENSE b/src/Symfony/Component/Messenger/Bridge/Redis/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/Messenger/Bridge/Redis/LICENSE +++ b/src/Symfony/Component/Messenger/Bridge/Redis/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php index 8707a941c7062..31f68166ccadf 100644 --- a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php +++ b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php @@ -175,7 +175,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->eventDispatcher->addSubscriber(new StopWorkerOnMemoryLimitListener($this->convertToBytes($memoryLimit), $this->logger)); } - if ($timeLimit = $input->getOption('time-limit')) { + if (null !== ($timeLimit = $input->getOption('time-limit'))) { $stopsWhen[] = "been running for {$timeLimit}s"; $this->eventDispatcher->addSubscriber(new StopWorkerOnTimeLimitListener($timeLimit, $this->logger)); } diff --git a/src/Symfony/Component/Messenger/LICENSE b/src/Symfony/Component/Messenger/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/Messenger/LICENSE +++ b/src/Symfony/Component/Messenger/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Mime/LICENSE b/src/Symfony/Component/Mime/LICENSE index 151af4bbc71b9..298be14166c20 100644 --- a/src/Symfony/Component/Mime/LICENSE +++ b/src/Symfony/Component/Mime/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-2021 Fabien Potencier +Copyright (c) 2010-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/AllMySms/LICENSE b/src/Symfony/Component/Notifier/Bridge/AllMySms/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/AllMySms/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/AllMySms/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Clickatell/LICENSE b/src/Symfony/Component/Notifier/Bridge/Clickatell/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/Clickatell/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Clickatell/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Discord/LICENSE b/src/Symfony/Component/Notifier/Bridge/Discord/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Discord/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Discord/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Esendex/LICENSE b/src/Symfony/Component/Notifier/Bridge/Esendex/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Esendex/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Esendex/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/FakeChat/LICENSE b/src/Symfony/Component/Notifier/Bridge/FakeChat/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/FakeChat/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/FakeChat/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/FakeSms/LICENSE b/src/Symfony/Component/Notifier/Bridge/FakeSms/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/FakeSms/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/FakeSms/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Firebase/LICENSE b/src/Symfony/Component/Notifier/Bridge/Firebase/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Firebase/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Firebase/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransport.php b/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransport.php index 163b1fa5e4d48..b34f9046b5e2b 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/FreeMobileTransport.php @@ -60,7 +60,7 @@ protected function doSend(MessageInterface $message): SentMessage $endpoint = sprintf('https://%s', $this->getEndpoint()); $response = $this->client->request('POST', $endpoint, [ - 'json' => [ + 'query' => [ 'user' => $this->login, 'pass' => $this->password, 'msg' => $message->getSubject(), diff --git a/src/Symfony/Component/Notifier/Bridge/FreeMobile/LICENSE b/src/Symfony/Component/Notifier/Bridge/FreeMobile/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/FreeMobile/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/FreeMobile/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/GatewayApi/LICENSE b/src/Symfony/Component/Notifier/Bridge/GatewayApi/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/GatewayApi/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/GatewayApi/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Gitter/LICENSE b/src/Symfony/Component/Notifier/Bridge/Gitter/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/Gitter/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Gitter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/LICENSE b/src/Symfony/Component/Notifier/Bridge/GoogleChat/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE b/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Infobip/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Iqsms/LICENSE b/src/Symfony/Component/Notifier/Bridge/Iqsms/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/Iqsms/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Iqsms/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE b/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/LinkedIn/LICENSE b/src/Symfony/Component/Notifier/Bridge/LinkedIn/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/LinkedIn/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/LinkedIn/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Mattermost/LICENSE b/src/Symfony/Component/Notifier/Bridge/Mattermost/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mattermost/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Mattermost/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Mercure/LICENSE b/src/Symfony/Component/Notifier/Bridge/Mercure/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mercure/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Mercure/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/MessageBird/LICENSE b/src/Symfony/Component/Notifier/Bridge/MessageBird/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/MessageBird/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/MessageBird/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/LICENSE b/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/MicrosoftTeams/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Mobyt/LICENSE b/src/Symfony/Component/Notifier/Bridge/Mobyt/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mobyt/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Mobyt/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Nexmo/LICENSE b/src/Symfony/Component/Notifier/Bridge/Nexmo/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Nexmo/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Nexmo/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Octopush/LICENSE b/src/Symfony/Component/Notifier/Bridge/Octopush/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/Octopush/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Octopush/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/OvhCloud/LICENSE b/src/Symfony/Component/Notifier/Bridge/OvhCloud/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/OvhCloud/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/OvhCloud/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/RocketChat/LICENSE b/src/Symfony/Component/Notifier/Bridge/RocketChat/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/RocketChat/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/RocketChat/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Sendinblue/LICENSE b/src/Symfony/Component/Notifier/Bridge/Sendinblue/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Sendinblue/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Sendinblue/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Sinch/LICENSE b/src/Symfony/Component/Notifier/Bridge/Sinch/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Sinch/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Sinch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/LICENSE b/src/Symfony/Component/Notifier/Bridge/Slack/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Slack/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/SmsBiuras/LICENSE b/src/Symfony/Component/Notifier/Bridge/SmsBiuras/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/SmsBiuras/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/SmsBiuras/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE b/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php index 700447dfdf3a7..e45ae6c0d1c3c 100644 --- a/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/Smsapi/SmsapiTransport.php @@ -64,6 +64,7 @@ protected function doSend(MessageInterface $message): SentMessage 'to' => $message->getPhone(), 'message' => $message->getSubject(), 'format' => 'json', + 'encoding' => 'utf-8', ], ]); diff --git a/src/Symfony/Component/Notifier/Bridge/SpotHit/LICENSE b/src/Symfony/Component/Notifier/Bridge/SpotHit/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Notifier/Bridge/SpotHit/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/SpotHit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/LICENSE b/src/Symfony/Component/Notifier/Bridge/Telegram/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Twilio/LICENSE b/src/Symfony/Component/Notifier/Bridge/Twilio/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/Bridge/Twilio/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Twilio/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/Bridge/Zulip/LICENSE b/src/Symfony/Component/Notifier/Bridge/Zulip/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Notifier/Bridge/Zulip/LICENSE +++ b/src/Symfony/Component/Notifier/Bridge/Zulip/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Notifier/LICENSE b/src/Symfony/Component/Notifier/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/Notifier/LICENSE +++ b/src/Symfony/Component/Notifier/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/OptionsResolver/LICENSE b/src/Symfony/Component/OptionsResolver/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/OptionsResolver/LICENSE +++ b/src/Symfony/Component/OptionsResolver/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/PasswordHasher/LICENSE b/src/Symfony/Component/PasswordHasher/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/PasswordHasher/LICENSE +++ b/src/Symfony/Component/PasswordHasher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Process/LICENSE b/src/Symfony/Component/Process/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Process/LICENSE +++ b/src/Symfony/Component/Process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Process/Pipes/AbstractPipes.php b/src/Symfony/Component/Process/Pipes/AbstractPipes.php index 015816c4fdd35..0105100562849 100644 --- a/src/Symfony/Component/Process/Pipes/AbstractPipes.php +++ b/src/Symfony/Component/Process/Pipes/AbstractPipes.php @@ -47,7 +47,9 @@ public function __construct($input) public function close() { foreach ($this->pipes as $pipe) { - fclose($pipe); + if (\is_resource($pipe)) { + fclose($pipe); + } } $this->pipes = []; } diff --git a/src/Symfony/Component/PropertyAccess/LICENSE b/src/Symfony/Component/PropertyAccess/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/PropertyAccess/LICENSE +++ b/src/Symfony/Component/PropertyAccess/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 5d9298df7a52d..dbea0c153ee1b 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -482,11 +482,11 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid } } catch (\Error $e) { // handle uninitialized properties in PHP >= 7.4 - if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { - $r = new \ReflectionProperty($matches[1], $matches[2]); + if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ('.preg_quote(get_debug_type($object), '/').')::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { + $r = new \ReflectionProperty($class, $matches[2]); $type = ($type = $r->getType()) instanceof \ReflectionNamedType ? $type->getName() : (string) $type; - throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getName(), $type), 0, $e); + throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $matches[1], $r->getName(), $type), 0, $e); } throw $e; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 521218f671c75..c0fb51bf9053e 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\PropertyAccess\Exception\AccessException; use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; @@ -191,7 +190,7 @@ public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetter() public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousClass() { - $this->expectException(AccessException::class); + $this->expectException(UninitializedPropertyException::class); $this->expectExceptionMessage('The method "class@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?'); $object = eval('return new class() { @@ -206,9 +205,44 @@ public function getUninitialized(): array $this->propertyAccessor->getValue($object, 'uninitialized'); } + /** + * @requires PHP 7.4 + */ + public function testGetValueThrowsExceptionIfUninitializedNotNullablePropertyWithGetterOfAnonymousClass() + { + $this->expectException(UninitializedPropertyException::class); + $this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.'); + + $object = eval('return new class() { + private string $uninitialized; + + public function getUninitialized(): string + { + return $this->uninitialized; + } + };'); + + $this->propertyAccessor->getValue($object, 'uninitialized'); + } + + /** + * @requires PHP 7.4 + */ + public function testGetValueThrowsExceptionIfUninitializedPropertyOfAnonymousClass() + { + $this->expectException(UninitializedPropertyException::class); + $this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.'); + + $object = eval('return new class() { + public string $uninitialized; + };'); + + $this->propertyAccessor->getValue($object, 'uninitialized'); + } + public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousStdClass() { - $this->expectException(AccessException::class); + $this->expectException(UninitializedPropertyException::class); $this->expectExceptionMessage('The method "stdClass@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?'); $object = eval('return new class() extends \stdClass { @@ -225,7 +259,7 @@ public function getUninitialized(): array public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousChildClass() { - $this->expectException(AccessException::class); + $this->expectException(UninitializedPropertyException::class); $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?'); $object = eval('return new class() extends \Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty {};'); diff --git a/src/Symfony/Component/PropertyInfo/LICENSE b/src/Symfony/Component/PropertyInfo/LICENSE index c9f0202b242b6..4e90b1b5ae4df 100644 --- a/src/Symfony/Component/PropertyInfo/LICENSE +++ b/src/Symfony/Component/PropertyInfo/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2021 Fabien Potencier +Copyright (c) 2015-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/RateLimiter/LICENSE b/src/Symfony/Component/RateLimiter/LICENSE index 3796612f43c2b..7fa9539054928 100644 --- a/src/Symfony/Component/RateLimiter/LICENSE +++ b/src/Symfony/Component/RateLimiter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2021 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Routing/LICENSE b/src/Symfony/Component/Routing/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Routing/LICENSE +++ b/src/Symfony/Component/Routing/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Runtime/LICENSE b/src/Symfony/Component/Runtime/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Runtime/LICENSE +++ b/src/Symfony/Component/Runtime/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Core/LICENSE b/src/Symfony/Component/Security/Core/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Security/Core/LICENSE +++ b/src/Symfony/Component/Security/Core/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Csrf/LICENSE b/src/Symfony/Component/Security/Csrf/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Security/Csrf/LICENSE +++ b/src/Symfony/Component/Security/Csrf/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Guard/LICENSE b/src/Symfony/Component/Security/Guard/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Security/Guard/LICENSE +++ b/src/Symfony/Component/Security/Guard/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Http/LICENSE b/src/Symfony/Component/Security/Http/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Security/Http/LICENSE +++ b/src/Symfony/Component/Security/Http/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Semaphore/LICENSE b/src/Symfony/Component/Semaphore/LICENSE index 3796612f43c2b..7fa9539054928 100644 --- a/src/Symfony/Component/Semaphore/LICENSE +++ b/src/Symfony/Component/Semaphore/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2021 Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Serializer/LICENSE b/src/Symfony/Component/Serializer/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Serializer/LICENSE +++ b/src/Symfony/Component/Serializer/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index b01c529dbc283..f6f7e5fb653a2 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -537,6 +537,10 @@ private function validateAndDenormalize(string $currentClass, string $attribute, return (float) $data; } + if (Type::BUILTIN_TYPE_FALSE === $builtinType && false === $data) { + return $data; + } + if (('is_'.$builtinType)($data)) { return $data; } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index d60571307b18a..38436e284b029 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -50,6 +50,7 @@ use Symfony\Component\Serializer\Tests\Normalizer\Features\ObjectToPopulateTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\SkipNullValuesTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\TypeEnforcementTestTrait; +use Symfony\Component\Serializer\Tests\Php80Dummy; /** * @author Kévin Dunglas @@ -699,6 +700,25 @@ public function testExtractAttributesRespectsContext() $this->assertSame(['foo' => 'bar', 'bar' => 'foo'], $normalizer->normalize($data, null, ['include_foo_and_bar' => true])); } + /** + * @requires PHP 8 + */ + public function testDenormalizeFalsePseudoType() + { + // given a serializer that extracts the attribute types of an object via ReflectionExtractor + $propertyTypeExtractor = new PropertyInfoExtractor([], [new ReflectionExtractor()], [], [], []); + $objectNormalizer = new ObjectNormalizer(null, null, null, $propertyTypeExtractor); + + $serializer = new Serializer([$objectNormalizer]); + + // when denormalizing some data into an object where an attribute uses the false pseudo type + /** @var Php80Dummy $object */ + $object = $serializer->denormalize(['canBeFalseOrString' => false], Php80Dummy::class); + + // then the attribute that declared false was filled correctly + $this->assertFalse($object->canBeFalseOrString); + } + public function testAdvancedNameConverter() { $nameConverter = new class() implements AdvancedNameConverterInterface { diff --git a/src/Symfony/Component/Serializer/Tests/Php80Dummy.php b/src/Symfony/Component/Serializer/Tests/Php80Dummy.php new file mode 100644 index 0000000000000..baa75b1246659 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Php80Dummy.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests; + +final class Php80Dummy +{ + public false|string $canBeFalseOrString; +} diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index e6e0113f93996..92e97cd1aebcd 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -34,7 +34,7 @@ "symfony/http-kernel": "^4.4|^5.0", "symfony/mime": "^4.4|^5.0", "symfony/property-access": "^5.3.13", - "symfony/property-info": "^5.3", + "symfony/property-info": "^5.3.13", "symfony/uid": "^5.3", "symfony/validator": "^4.4|^5.0", "symfony/var-dumper": "^4.4|^5.0", @@ -47,7 +47,7 @@ "phpdocumentor/type-resolver": "<1.4.0", "symfony/dependency-injection": "<4.4", "symfony/property-access": "<5.3.13", - "symfony/property-info": "<5.3", + "symfony/property-info": "<5.3.13", "symfony/uid": "<5.3", "symfony/yaml": "<4.4" }, diff --git a/src/Symfony/Component/Stopwatch/LICENSE b/src/Symfony/Component/Stopwatch/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Stopwatch/LICENSE +++ b/src/Symfony/Component/Stopwatch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/String/LICENSE b/src/Symfony/Component/String/LICENSE index 383e7a54586e7..9c907a46a6218 100644 --- a/src/Symfony/Component/String/LICENSE +++ b/src/Symfony/Component/String/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2019-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/String/composer.json b/src/Symfony/Component/String/composer.json index bfb03cd363b54..3e77ff4ff9f98 100644 --- a/src/Symfony/Component/String/composer.json +++ b/src/Symfony/Component/String/composer.json @@ -29,6 +29,9 @@ "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0" }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, "autoload": { "psr-4": { "Symfony\\Component\\String\\": "" }, "files": [ "Resources/functions.php" ], diff --git a/src/Symfony/Component/Templating/LICENSE b/src/Symfony/Component/Templating/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Templating/LICENSE +++ b/src/Symfony/Component/Templating/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Translation/Bridge/Crowdin/LICENSE b/src/Symfony/Component/Translation/Bridge/Crowdin/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Translation/Bridge/Crowdin/LICENSE +++ b/src/Symfony/Component/Translation/Bridge/Crowdin/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Translation/Bridge/Loco/LICENSE b/src/Symfony/Component/Translation/Bridge/Loco/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/LICENSE +++ b/src/Symfony/Component/Translation/Bridge/Loco/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Translation/Bridge/Lokalise/LICENSE b/src/Symfony/Component/Translation/Bridge/Lokalise/LICENSE index efb17f98e7dd3..48d17c4fb34f1 100644 --- a/src/Symfony/Component/Translation/Bridge/Lokalise/LICENSE +++ b/src/Symfony/Component/Translation/Bridge/Lokalise/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Fabien Potencier +Copyright (c) 2021-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Translation/Command/TranslationPullCommand.php b/src/Symfony/Component/Translation/Command/TranslationPullCommand.php index 511c7caec6a84..bf0ab6567c73b 100644 --- a/src/Symfony/Component/Translation/Command/TranslationPullCommand.php +++ b/src/Symfony/Component/Translation/Command/TranslationPullCommand.php @@ -81,7 +81,7 @@ protected function configure() Full example: - php %command.full_name% provider --force --domains=messages,validators --locales=en + php %command.full_name% provider --force --domains=messages --domains=validators --locales=en This command pulls all translations associated with the messages and validators domains for the en locale. Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case. diff --git a/src/Symfony/Component/Translation/Command/TranslationPushCommand.php b/src/Symfony/Component/Translation/Command/TranslationPushCommand.php index b28d3e102684a..ad6b676940279 100644 --- a/src/Symfony/Component/Translation/Command/TranslationPushCommand.php +++ b/src/Symfony/Component/Translation/Command/TranslationPushCommand.php @@ -79,7 +79,7 @@ protected function configure() Full example: - php %command.full_name% provider --force --delete-missing --domains=messages,validators --locales=en + php %command.full_name% provider --force --delete-missing --domains=messages --domains=validators --locales=en This command pushes all translations associated with the messages and validators domains for the en locale. Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case. diff --git a/src/Symfony/Component/Translation/LICENSE b/src/Symfony/Component/Translation/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Translation/LICENSE +++ b/src/Symfony/Component/Translation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Uid/LICENSE b/src/Symfony/Component/Uid/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Component/Uid/LICENSE +++ b/src/Symfony/Component/Uid/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 690a1c4b7c2dc..fc3342b56c730 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -235,6 +235,10 @@ public function __isset(string $option) */ public function addImplicitGroupName(string $group) { + if (null === $this->groups && \array_key_exists('groups', (array) $this)) { + throw new \LogicException(sprintf('"%s::$groups" is set to null. Did you forget to call "%s::__construct()"?', static::class, self::class)); + } + if (\in_array(self::DEFAULT_GROUP, $this->groups) && !\in_array($group, $this->groups)) { $this->groups[] = $group; } diff --git a/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 1e37c31f4388b..b5bcc6d3d9864 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/Constraints/Choice.php @@ -52,7 +52,8 @@ public function getDefaultOption() } public function __construct( - $choices = null, + $options = [], + array $choices = null, $callback = null, bool $multiple = null, bool $strict = null, @@ -63,12 +64,13 @@ public function __construct( string $minMessage = null, string $maxMessage = null, $groups = null, - $payload = null, - array $options = [] + $payload = null ) { - if (\is_array($choices) && \is_string(key($choices))) { - $options = array_merge($choices, $options); - } elseif (null !== $choices) { + if (\is_array($options) && $options && array_is_list($options)) { + $choices = $choices ?? $options; + $options = []; + } + if (null !== $choices) { $options['value'] = $choices; } diff --git a/src/Symfony/Component/Validator/LICENSE b/src/Symfony/Component/Validator/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Validator/LICENSE +++ b/src/Symfony/Component/Validator/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index 247ccf24021a7..55a811134dae5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -394,6 +394,14 @@ This value is not a valid CSS color. Táto hodnota nie je platná CSS farba. + + This value is not a valid CIDR notation. + Táto hodnota nie je platnou notáciou CIDR. + + + The value of the netmask should be between {{ min }} and {{ max }}. + Hodnota masky siete by mala byť medzi {{ min }} a {{ max }}. + diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php index 8b5879aedcb42..e94bffbf28d3e 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php @@ -12,6 +12,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintChoiceWithPreset; class ChoiceTest extends TestCase @@ -22,4 +25,50 @@ public function testSetDefaultPropertyChoice() self::assertEquals(['A', 'B', 'C'], $constraint->choices); } + + /** + * @requires PHP 8 + */ + public function testAttributes() + { + $metadata = new ClassMetadata(ChoiceDummy::class); + $loader = new AnnotationLoader(); + self::assertTrue($loader->loadClassMetadata($metadata)); + + /** @var Choice $aConstraint */ + [$aConstraint] = $metadata->properties['a']->getConstraints(); + self::assertSame([1, 2], $aConstraint->choices); + self::assertSame(['Default', 'ChoiceDummy'], $aConstraint->groups); + + /** @var Choice $bConstraint */ + [$bConstraint] = $metadata->properties['b']->getConstraints(); + self::assertSame(['foo', 'bar'], $bConstraint->choices); + self::assertSame('myMessage', $bConstraint->message); + self::assertSame(['Default', 'ChoiceDummy'], $bConstraint->groups); + + /** @var Choice $cConstraint */ + [$cConstraint] = $metadata->properties['c']->getConstraints(); + self::assertSame([1, 2], $aConstraint->choices); + self::assertSame(['my_group'], $cConstraint->groups); + self::assertSame('some attached data', $cConstraint->payload); + + /** @var Choice $stringIndexedConstraint */ + [$stringIndexedConstraint] = $metadata->properties['stringIndexed']->getConstraints(); + self::assertSame(['one' => 1, 'two' => 2], $stringIndexedConstraint->choices); + } +} + +class ChoiceDummy +{ + #[Choice(choices: [1, 2])] + private $a; + + #[Choice(choices: ['foo', 'bar'], message: 'myMessage')] + private $b; + + #[Choice([1, 2], groups: ['my_group'], payload: 'some attached data')] + private $c; + + #[Choice(choices: ['one' => 1, 'two' => 2])] + private $stringIndexed; } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 659b13ceb0cfd..4caf290db196f 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -22,6 +22,7 @@ "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "~1.0", "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", "symfony/translation-contracts": "^1.1|^2" }, "require-dev": { diff --git a/src/Symfony/Component/VarDumper/LICENSE b/src/Symfony/Component/VarDumper/LICENSE index c1f0aac1c5614..a843ec124ea70 100644 --- a/src/Symfony/Component/VarDumper/LICENSE +++ b/src/Symfony/Component/VarDumper/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2021 Fabien Potencier +Copyright (c) 2014-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php index 48db493396500..7d86dfbdeacfc 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php @@ -77,9 +77,7 @@ public function testDumpProducer() $expectedDump = <<broker/1001" brokers: RdKafka\Metadata\Collection { @@ -146,10 +144,7 @@ public function testDumpKafkaConsumer() $expectedDump = << "test-topic" ] assignment: [] diff --git a/src/Symfony/Component/VarExporter/LICENSE b/src/Symfony/Component/VarExporter/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Component/VarExporter/LICENSE +++ b/src/Symfony/Component/VarExporter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/WebLink/LICENSE b/src/Symfony/Component/WebLink/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/WebLink/LICENSE +++ b/src/Symfony/Component/WebLink/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Workflow/LICENSE b/src/Symfony/Component/Workflow/LICENSE index c1f0aac1c5614..a843ec124ea70 100644 --- a/src/Symfony/Component/Workflow/LICENSE +++ b/src/Symfony/Component/Workflow/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2021 Fabien Potencier +Copyright (c) 2014-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Yaml/LICENSE b/src/Symfony/Component/Yaml/LICENSE index 9ff2d0d6306da..88bf75bb4d6a2 100644 --- a/src/Symfony/Component/Yaml/LICENSE +++ b/src/Symfony/Component/Yaml/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2021 Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 03d2ea956b03a..ae80f20dde5a1 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -99,6 +99,8 @@ public function parse(string $value, int $flags = 0) if (null !== $mbEncoding) { mb_internal_encoding($mbEncoding); } + $this->refsBeingParsed = []; + $this->offset = 0; $this->lines = []; $this->currentLine = ''; $this->numberOfParsedLines = 0; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 50ed706f1ae46..769af36eaa6dd 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -84,6 +84,20 @@ public function invalidIndentation(): array ]; } + public function testParserIsStateless() + { + $yamlString = '# translations/messages.en.yaml + +'; + $this->parser->parse($yamlString); + $this->parser->parse($yamlString); + + $this->expectException(ParseException::class); + $this->expectExceptionMessage("A YAML file cannot contain tabs as indentation at line 2 (near \"\tabc\")"); + + $this->parser->parse("abc:\n\tabc"); + } + /** * @dataProvider validTokenSeparators */ diff --git a/src/Symfony/Contracts/Cache/LICENSE b/src/Symfony/Contracts/Cache/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/Cache/LICENSE +++ b/src/Symfony/Contracts/Cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/Deprecation/LICENSE b/src/Symfony/Contracts/Deprecation/LICENSE index ad85e1737485d..406242ff28554 100644 --- a/src/Symfony/Contracts/Deprecation/LICENSE +++ b/src/Symfony/Contracts/Deprecation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/EventDispatcher/LICENSE b/src/Symfony/Contracts/EventDispatcher/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/EventDispatcher/LICENSE +++ b/src/Symfony/Contracts/EventDispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/HttpClient/LICENSE b/src/Symfony/Contracts/HttpClient/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/HttpClient/LICENSE +++ b/src/Symfony/Contracts/HttpClient/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/LICENSE b/src/Symfony/Contracts/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/LICENSE +++ b/src/Symfony/Contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/Service/LICENSE b/src/Symfony/Contracts/Service/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/Service/LICENSE +++ b/src/Symfony/Contracts/Service/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Contracts/Translation/LICENSE b/src/Symfony/Contracts/Translation/LICENSE index 2358414536d95..74cdc2dbf6dbe 100644 --- a/src/Symfony/Contracts/Translation/LICENSE +++ b/src/Symfony/Contracts/Translation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-2021 Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal