diff --git a/.appveyor.yml b/.appveyor.yml index e0d8c17dc1f56..1a91d001f0bee 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,7 @@ install: - php composer.phar global require --no-progress --no-scripts --no-plugins symfony/flex - git config --global user.email "" - git config --global user.name "Symfony" - - FOR /F "tokens=* USEBACKQ" %%F IN (`bash -c "grep branch-version composer.json | grep -o '[0-9.]*'"`) DO (SET SYMFONY_VERSION=%%F) + - FOR /F "tokens=* USEBACKQ" %%F IN (`bash -c "grep branch-version composer.json | grep -o '[0-9.x]*'"`) DO (SET SYMFONY_VERSION=%%F) - php .github/build-packages.php "HEAD^" %SYMFONY_VERSION% src\Symfony\Bridge\PhpUnit src\Symfony\Contracts - SET "SYMFONY_REQUIRE=>=%SYMFONY_VERSION%" - SET COMPOSER_ROOT_VERSION=%SYMFONY_VERSION%.x-dev diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index df9db03fa8bca..c113ccbf96f1b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | 5.x for features / 3.4, 4.4 or 5.1 for bug fixes +| Branch? | 5.x for features / 4.4 or 5.1 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1163e61a554fa..52531183458b8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -114,7 +114,7 @@ jobs: run: | COMPOSER_HOME="$(composer config home)" ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" - echo "COMPOSER_ROOT_VERSION=$(grep branch-version composer.json | grep -o '[0-9.]*').x-dev" >> $GITHUB_ENV + echo "COMPOSER_ROOT_VERSION=$(grep branch-version composer.json | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV - name: Determine composer cache directory id: composer-cache diff --git a/.php_cs.dist b/.php_cs.dist index 8b691441a3e36..84883ff9bf8b4 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -15,6 +15,7 @@ return PhpCsFixer\Config::create() 'protected_to_private' => false, 'native_constant_invocation' => true, 'combine_nested_dirname' => true, + 'list_syntax' => ['syntax' => 'short'], ]) ->setRiskyAllowed(true) ->setFinder( diff --git a/.travis.yml b/.travis.yml index d1f90d9babcfe..8d284a7a121bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,11 +28,11 @@ matrix: env: deps=high - php: 7.4 env: deps=low - - php: nightly + - php: 8.0snapshot services: [memcached] fast_finish: true allow_failures: - - php: nightly + - php: 8.0snapshot services: [memcached] cache: @@ -140,7 +140,7 @@ before_install: echo session.gc_probability = 0 >> $INI echo opcache.enable_cli = 1 >> $INI echo apc.enable_cli = 1 >> $INI - if [[ $PHP != nightly ]]; then + if [[ $PHP != 8.* ]]; then echo extension = memcached.so >> $INI fi done @@ -156,17 +156,17 @@ before_install: if ! php --ri sodium > /dev/null; then tfold ext.libsodium tpecl libsodium sodium.so $INI fi - if [[ $PHP = nightly ]]; then + if [[ $PHP = 8.* ]]; then tfold ext.memcached tpecl memcached-3.1.5 memcached.so $INI else tfold ext.mongodb tpecl mongodb-1.6.16 mongodb.so $INI tfold ext.zookeeper tpecl zookeeper-0.7.2 zookeeper.so $INI tfold ext.amqp tpecl amqp-1.10.2 amqp.so $INI - tfold ext.redis tpecl redis-5.2.2 redis.so $INI "no" fi tfold ext.apcu tpecl apcu-5.1.19 apcu.so $INI tfold ext.igbinary tpecl igbinary-3.1.6 igbinary.so $INI + tfold ext.redis tpecl redis-5.2.3 redis.so $INI "no" done - | @@ -199,7 +199,7 @@ install: git config --global user.email "" git config --global user.name "Symfony" - export SYMFONY_VERSION=$(grep branch-version composer.json | grep -o '[0-9.]*') + export SYMFONY_VERSION=$(grep branch-version composer.json | grep -o '[0-9.x]*') if [[ ! $deps ]]; then php .github/build-packages.php HEAD^ $SYMFONY_VERSION src/Symfony/Bridge/PhpUnit src/Symfony/Contracts @@ -234,7 +234,7 @@ install: - | # Set composer's platform to php 7.4 if we're on php 8. - if [[ $PHP = nightly ]]; then + if [[ $PHP = 8.* ]]; then composer config platform.php 7.4.99 export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 fi diff --git a/CHANGELOG-5.1.md b/CHANGELOG-5.1.md index 2787daf5a9f1d..0f8e3a5c324dd 100644 --- a/CHANGELOG-5.1.md +++ b/CHANGELOG-5.1.md @@ -7,6 +7,44 @@ in 5.1 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.1.0...v5.1.1 +* 5.1.8 (2020-10-28) + + * bug #38713 [DI] Fix Preloader exception when preloading a class with an unknown parent/interface (rgeraads) + * bug #38647 [HttpClient] relax auth bearer format requirements (xabbuh) + * bug #38699 [DependencyInjection] Preload classes with union types correctly (derrabus) + * bug #38669 [Serializer] fix decoding float XML attributes starting with 0 (Marcin Kruk) + * bug #38680 [PhpUnitBridge] Support new expect methods in test case polyfill (alcaeus) + * bug #38681 [PHPUnitBridge] Support PHPUnit 8 and PHPUnit 9 in constraint compatibility trait (alcaeus) + * bug #38686 [TwigBridge] Remove "transchoice" from the code base (nicolas-grekas) + * bug #38678 [String] fix before/after[Last]() returning the empty string instead of the original one on non-match (nicolas-grekas) + * bug #38679 [PhpUnitBridge] Add missing exporter function for PHPUnit 7 (alcaeus) + * bug #38659 [String] fix slicing in UnicodeString (nicolas-grekas) + * bug #38595 [TwigBridge] do not translate null placeholders or titles (xabbuh) + * bug #38635 [Cache] Use correct expiry in ChainAdapter (Nyholm) + * bug #38652 [Filesystem] Check if failed unlink was caused by permission denied (Nyholm) + * bug #38645 [PropertyAccess] forward the caught exception (xabbuh) + * bug #38612 [Messenger/Amqp] Allow setting option "login" in DSN (W0rma) + * bug #38618 [Messenger][Doctrine] Avoid early db access for pgsql detection (chalasr) + * bug #38604 [DoctrineBridge] indexBy does not refer to attributes, but to column names (xabbuh) + * bug #38606 [WebProfilerBundle] Hide debug toolbar in print view (jt2k) + * bug #38582 [DI] Fix Reflection file name with eval()\'d code (maxime-aknin) + * bug #38578 Add missing use statement (jderusse) + * bug #38516 [HttpFoundation] Fix Range Requests (BattleRattle) + * bug #38553 [Lock] Reset Key lifetime time before we acquire it (Nyholm) + * bug #38551 Remove content-type check on toArray methods (jderusse) + * bug #38546 [String] fix "is too large" ValueError on PHP 8 (nicolas-grekas) + * bug #38544 [DI] fix dumping env vars (nicolas-grekas) + * bug #38533 [TwigBridge] Fix preload hint and remove "unlinked class class@anonymous" warning (burned42) + * bug #38530 [HttpClient] fix reading the body after a ClientException (nicolas-grekas) + * bug #38510 [PropertyInfo] Support for the mixed type (derrabus) + * bug #38493 [HttpClient] Fix CurlHttpClient memory leak (HypeMC) + * bug #38456 [Cache] skip igbinary < 3.1.6 (nicolas-grekas) + * bug #38392 [Ldap] Bypass the use of `ldap_control_paged_result` on PHP >= 7.3 (lucasaba) + * bug #38444 [PhpUnitBridge] fix running parallel tests with phpunit 9 (nicolas-grekas) + * bug #38446 [PropertyInfo] Extract from default value doesn't set collection boolean (Korbeil) + * bug #38442 [VarDumper] fix truncating big arrays (nicolas-grekas) + * bug #38433 [Mime] Fix serialization of RawMessage (gilbertsoft) + * 5.1.7 (2020-10-04) * bug #38396 Handle consecutive supports() calls in the RememberMeAuthenticator (wouterj) diff --git a/CHANGELOG-5.2.md b/CHANGELOG-5.2.md index 0b7a3974cf757..4708969f2be28 100644 --- a/CHANGELOG-5.2.md +++ b/CHANGELOG-5.2.md @@ -7,6 +7,40 @@ in 5.2 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.2.0...v5.2.1 +* 5.2.0-RC1 (2020-11-10) + + * bug #39004 [Messenger] Fix JSON deserialization of ErrorDetailsStamp and normalization of FlattenException::$statusText (Jean85) + * bug #38628 [DoctrineBridge] indexBy could reference to association columns (juanmiguelbesada) + * bug #39021 [DependencyInjection] Optimize circular collection by removing flattening (jderusse) + * bug #39031 [Ldap] Fix pagination (jderusse) + * bug #39038 [DoctrineBridge] also reset id readers (xabbuh) + * feature #39032 [Validator] Allow load mappings from attributes without doctrine/annotations (derrabus) + * feature #39022 [FrameworkBundle] Allow to use attribute-based configuration of routing/serializer without doctrine/annotations (derrabus) + * bug #39002 [Validator] Override the default option of the choice constraint (benji07) + * bug #39026 [Messenger] Fix DBAL deprecations in PostgreSqlConnection (chalasr) + * bug #39025 [DoctrineBridge] Fix DBAL deprecations in middlewares (derrabus) + * bug #38991 [Console] Fix ANSI when stdErr is not a tty (jderusse) + * bug #38980 [DependencyInjection] Fix circular reference with Factory + Lazy Iterrator (jderusse) + * bug #38986 [DoctrineBridge] accept converting Uid-as-strings to db-values (nicolas-grekas) + * feature #38850 [Messenger] Do not call getQueueUrl when the url is known in AmazonSqs transport (jderusse) + * feature #38940 [Messenger] Improve formatting of exception in failed message (Jeroen Noten) + * feature #38954 [HttpFundation][FrameworkBundle] Deprecate the HEADER_X_FORWARDED_ALL constant (jderusse) + * bug #38977 [HttpClient] Check status code before decoding content in TraceableResponse (chalasr) + * bug #38971 [PhpUnitBridge] fix replaying skipped tests (nicolas-grekas) + * bug #38910 [HttpKernel] Fix session initialized several times (jderusse) + * bug #38882 [DependencyInjection] Improve performances in CircualReference detection (jderusse) + * bug #38950 [Process] Dont test TTY if there is no TTY support (Nyholm) + * bug #38921 [PHPUnitBridge] Fixed crash on Windows with PHP 8 (villfa) + * feature #38919 [Console] Make error message more verbose (Nyholm) + * bug #38869 [SecurityBundle] inject only compatible token storage implementations for usage tracking (xabbuh) + * feature #38859 [HttpFoundation] Deprecate not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` (nicolas-grekas) + * bug #38894 [HttpKernel] Remove Symfony 3 compatibility code (derrabus) + * bug #38888 remove reflection-docblock from mime requirements (garak) + * bug #38895 [PhpUnitBridge] Fix wrong check for exporter in ConstraintTrait (alcaeus) + * bug #38879 [Cache] Fixed expiry could be int in ChainAdapter due to race conditions (phamviet) + * bug #38867 [FrameworkBundle] Fixing TranslationUpdateCommand failure when using "--no-backup" (liarco) + * bug #38856 [Cache] Add missing use statement (fabpot) + * 5.2.0-BETA3 (2020-10-28) * bug #38845 [Console] Register signal handling only for commands implemeting SignalableCommandInterface (lyrixx) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f3217f25a966c..5d3ae522834d7 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -22,18 +22,18 @@ Symfony is the result of the work of many people who made the code better - Jakub Zalas (jakubzalas) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) + - Alexander M. Turek (derrabus) - Wouter de Jong (wouterj) - Yonel Ceruto (yonelceruto) - - Alexander M. Turek (derrabus) - - Hugo Hamon (hhamon) - Thomas Calvet (fancyweb) + - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) - Samuel ROZE (sroze) - Romain Neutron (romain) - Pascal Borreli (pborreli) + - Jérémy DERUSSÉ (jderusse) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - - Jérémy DERUSSÉ (jderusse) - Jules Pietri (heah) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) @@ -42,12 +42,13 @@ Symfony is the result of the work of many people who made the code better - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Eriksen Costa (eriksencosta) - Tobias Nyholm (tobias) + - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Lynn van der Berg (kjarli) + - Jan Schädlich (jschaedl) - Matthias Pigulla (mpdude) - Diego Saint Esteben (dosten) - Pierre du Plessis (pierredup) @@ -55,28 +56,27 @@ Symfony is the result of the work of many people who made the code better - William Durand (couac) - Valentin Udaltsov (vudaltsov) - ornicar - - Jan Schädlich (jschaedl) - Dany Maillard (maidmaid) - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) + - Kevin Bond (kbond) - Konstantin Myakshin (koc) - Grégoire Paris (greg0ire) - Bulat Shakirzyanov (avalanche123) - - Kevin Bond (kbond) - Saša Stamenković (umpirsky) - Peter Rehm (rpet) - Gabriel Ostrolucký (gadelat) + - Titouan Galopin (tgalopin) - David Maicher (dmaicher) - Gábor Egyed (1ed) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - - Titouan Galopin (tgalopin) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) + - Mathieu Piot (mpiot) - Vladimir Reznichenko (kalessil) - Bilal Amarni (bamarni) - - Mathieu Piot (mpiot) - Florin Patan (florinpatan) - Jáchym Toušek (enumag) - Andrej Hudec (pulzarraider) @@ -86,13 +86,13 @@ Symfony is the result of the work of many people who made the code better - Charles Sarrazin (csarrazi) - Christian Raue - Douglas Greenshields (shieldo) + - Laurent VOULLEMIER (lvo) - Arnout Boks (aboks) + - Graham Campbell (graham) - Jérôme Tamarelle (gromnan) - - Laurent VOULLEMIER (lvo) - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Graham Campbell (graham) - David Buchmann (dbu) - Dariusz Ruminski - Fran Moreno (franmomu) @@ -100,11 +100,11 @@ Symfony is the result of the work of many people who made the code better - Brandon Turner - Luis Cordova (cordoval) - Daniel Holmes (dholmes) + - Alex Pott - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - John Wards (johnwards) - - Alex Pott - Antoine Hérault (herzult) - Paráda József (paradajozsef) - Arnaud Le Blanc (arnaud-lb) @@ -119,18 +119,19 @@ Symfony is the result of the work of many people who made the code better - marc.weistroff - Tomáš Votruba (tomas_votruba) - Peter Kokot (maastermedia) + - Lars Strojny (lstrojny) - lenar - Alexander Schwenn (xelaris) - Włodzimierz Gajda (gajdaw) + - Alexander Schranz (alexander-schranz) + - Oskar Stark (oskarstark) - Adrien Brault (adrienbrault) - - Lars Strojny (lstrojny) - Massimiliano Arione (garak) - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) - Teoh Han Hui (teohhanhui) - Przemysław Bogusz (przemyslaw-bogusz) - Colin Frei - - Oskar Stark (oskarstark) - Javier Spagnoletti (phansys) - Joshua Thijssen - Daniel Wehner (dawehner) @@ -138,7 +139,6 @@ Symfony is the result of the work of many people who made the code better - excelwebzone - Gordon Franke (gimler) - Joel Wurtz (brouznouf) - - Alexander Schranz (alexander-schranz) - Fabien Pennequin (fabienpennequin) - Julien Falque (julienfalque) - Théo FIDRY (theofidry) @@ -175,6 +175,7 @@ Symfony is the result of the work of many people who made the code better - Rafael Dohms (rdohms) - jwdeitch - Ahmed TAILOULOUTE (ahmedtai) + - Andreas Braun - Mikael Pajunen - Arman Hosseini (arman) - Niels Keurentjes (curry684) @@ -209,6 +210,7 @@ Symfony is the result of the work of many people who made the code better - Marek Štípek (maryo) - Filippo Tessarotto (slamdunk) - Daniel Espendiller + - Maxime Helias (maxhelias) - Possum - Dorian Villet (gnutix) - Michaël Perrin (michael.perrin) @@ -228,9 +230,9 @@ Symfony is the result of the work of many people who made the code better - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) - Jan Rosier (rosier) - - Andreas Braun - Mathieu Lemoine (lemoinem) - Rémon van de Kamp (rpkamp) + - HypeMC - Christian Schmidt - Andreas Hucks (meandmymonkey) - Tom Van Looy (tvlooy) @@ -246,7 +248,6 @@ Symfony is the result of the work of many people who made the code better - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) - apetitpa - - Maxime Helias (maxhelias) - Matthieu Bontemps (mbontemps) - apetitpa - Pierre Minnieur (pminnieur) @@ -255,6 +256,7 @@ Symfony is the result of the work of many people who made the code better - Dominique Bongiraud - Hidde Wieringa (hiddewie) - Jeremy Livingston (jeremylivingston) + - Olivier Dolbeau (odolbeau) - Michael Lee (zerustech) - Dmitrii Poddubnyi (karser) - Matthieu Auger (matthieuauger) @@ -288,7 +290,6 @@ Symfony is the result of the work of many people who made the code better - Marco Pivetta (ocramius) - Antonio Pauletich (x-coder264) - Jeroen Spee (jeroens) - - Olivier Dolbeau (odolbeau) - Rob Frawley 2nd (robfrawley) - julien pauli (jpauli) - Lorenz Schori @@ -304,6 +305,7 @@ Symfony is the result of the work of many people who made the code better - Elnur Abdurrakhimov (elnur) - Manuel Reinhard (sprain) - Danny Berger (dpb587) + - zairig imad (zairigimad) - Antonio J. García Lagar (ajgarlag) - Adam Prager (padam87) - Benoît Burnichon (bburnichon) @@ -338,11 +340,13 @@ Symfony is the result of the work of many people who made the code better - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - jdhoek + - Michael Käfer (michael_kaefer) - Bob den Otter (bopp) - Thomas Schulz (king2500) - Frank de Jonge (frenkynet) - Nikita Konstantinov - Wodor Wodorski + - Timo Bakx (timobakx) - Joe Bennett (kralos) - Thomas Lallement (raziel057) - soyuka @@ -370,8 +374,8 @@ Symfony is the result of the work of many people who made the code better - Simon Mönch (sm) - Christian Schmidt - Patrick Landolt (scube) - - HypeMC - MatTheCat + - Bohan Yang (brentybh) - Vilius Grigaliūnas - David Badura (davidbadura) - Chad Sikorra (chadsikorra) @@ -379,6 +383,7 @@ Symfony is the result of the work of many people who made the code better - Chris Smith (cs278) - Thomas Bisignani (toma) - Florian Klein (docteurklein) + - Timothée Barray (tyx) - Benjamin Leveque (benji07) - Manuel Kiessling (manuelkiessling) - Alexey Kopytko (sanmai) @@ -412,7 +417,6 @@ Symfony is the result of the work of many people who made the code better - Romain Pierre (romain-pierre) - Julien Galenski (ruian) - Thomas Landauer (thomas-landauer) - - Michael Käfer (michael_kaefer) - Bongiraud Dominique - janschoenherr - Emanuele Gaspari (inmarelibero) @@ -423,6 +427,8 @@ Symfony is the result of the work of many people who made the code better - Sebastien Morel (plopix) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) + - ivan + - Karoly Gossler (connorhu) - Ahmed Raafat - Philippe Segatori - Gennady Telegin (gtelegin) @@ -432,6 +438,7 @@ Symfony is the result of the work of many people who made the code better - Matthew Lewinski (lewinski) - Magnus Nordlander (magnusnordlander) - Thomas Royer (cydonia7) + - Nicolas Philippe (nikophil) - Nicolas LEFEVRE (nicoweb) - alquerci - Oleg Andreyev @@ -441,12 +448,13 @@ Symfony is the result of the work of many people who made the code better - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) + - Romaric Drigon (romaricdrigon) - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Dmytro Borysovskyi (dmytr0) - Tomasz Kowalczyk (thunderer) + - Sylvain Fabre (sylfabre) - Artur Eshenbrener - - Timo Bakx (timobakx) - Harm van Tilborg (hvt) - Thomas Perez (scullwm) - Felix Labrecque @@ -498,7 +506,6 @@ Symfony is the result of the work of many people who made the code better - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer - - Timothée Barray (tyx) - Shein Alexey - Romain Gautier (mykiwi) - Joe Lencioni @@ -540,9 +547,12 @@ Symfony is the result of the work of many people who made the code better - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) - Webnet team (webnet) + - Ben Ramsey (ramsey) + - Nate Wiebe (natewiebe13) - Marcin Szepczynski (czepol) - Mohammad Emran Hasan (phpfour) - Farhad Safarov + - Dmitriy Mamontov (mamontovdmitriy) - Jan Schumann - Niklas Fiekas - Markus Bachmann (baachi) @@ -554,6 +564,7 @@ Symfony is the result of the work of many people who made the code better - Mihai Stancu - Ivan Nikolaev (destillat) - Gildas Quéméner (gquemener) + - Baptiste Leduc (korbeil) - Laurent Masforné (heisenberg) - Claude Khedhiri (ck-developer) - Desjardins Jérôme (jewome62) @@ -563,22 +574,25 @@ Symfony is the result of the work of many people who made the code better - Toni Rudolf (toooni) - Asmir Mustafic (goetas) - DerManoMann - - Nicolas Philippe (nikophil) - vagrant - Aurimas Niekis (gcds) - EdgarPE + - Bob van de Vijver (bobvandevijver) - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) - - Sylvain Fabre (sylfabre) - Martijn Cuppens - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) - Artem Lopata - Judicaël RUFFIEUX (axanagor) - Chris Sedlmayr (catchamonkey) + - Indra Gunawan (indragunawan) - Kamil Kokot (pamil) - Seb Koelen - Christoph Mewes (xrstf) + - Andrew M-Y (andr) + - Krasimir Bosilkov (kbosilkov) + - Marcin Michalski (marcinmichalski) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Dirk Pahl (dirkaholic) @@ -590,10 +604,11 @@ Symfony is the result of the work of many people who made the code better - Tobias Weichart - Tarmo Leppänen (tarlepp) - Marcin Sikoń (marphi) - - Bohan Yang (brentybh) + - M. Vondano - Dominik Zogg (dominik.zogg) - Marek Pietrzak - Luc Vieillescazes (iamluc) + - Lukáš Holeczy (holicz) - franek (franek) - Raulnet - Marco Petersen (ocrampete16) @@ -659,6 +674,7 @@ Symfony is the result of the work of many people who made the code better - Leevi Graham (leevigraham) - Anthony Ferrara - Ioan Negulescu + - Greg ORIOL - Jakub Škvára (jskvara) - Andrew Udvare (audvare) - alexpods @@ -668,7 +684,6 @@ Symfony is the result of the work of many people who made the code better - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) - Almog Baku (almogbaku) - - Karoly Gossler (connorhu) - Scott Arciszewski - Xavier HAUSHERR - Norbert Orzechowicz (norzechowicz) @@ -735,22 +750,18 @@ Symfony is the result of the work of many people who made the code better - Julien Montel (julienmgel) - Mátyás Somfai (smatyas) - Bastien DURAND (deamon) - - Ben Ramsey (ramsey) - Simon DELICATA - Artem Henvald (artemgenvald) - Dmitry Simushev - alcaeus - Thomas Talbot (ioni) - - Nate Wiebe (natewiebe13) - Fred Cox - vitaliytv - - ivan - Philippe Segatori - Dalibor Karlović (dkarlovi) - Andrey Sevastianov - Sebastian Blum - Alexis Lefebvre - - Dmitriy Mamontov (mamontovdmitriy) - aubx - Julien Turby - Marvin Butkereit @@ -761,7 +772,6 @@ Symfony is the result of the work of many people who made the code better - Max Rath (drak3) - marie - Stéphane Escandell (sescandell) - - Baptiste Leduc (korbeil) - Konstantin S. M. Möllers (ksmmoellers) - James Johnston - Noémi Salaün (noemi-salaun) @@ -779,7 +789,6 @@ Symfony is the result of the work of many people who made the code better - Christophe Villeger (seragan) - Matthias Krauser (mkrauser) - Julien Fredon - - Bob van de Vijver (bobvandevijver) - Xavier Leune (xleune) - Stefan Gehrig (sgehrig) - Hany el-Kerdany @@ -795,7 +804,6 @@ Symfony is the result of the work of many people who made the code better - Geoffrey Brier (geoffrey-brier) - Alexandre Parent - Vladimir Tsykun - - Romaric Drigon (romaricdrigon) - Dustin Dobervich (dustin10) - dantleech - Philipp Kolesnikov @@ -804,7 +812,9 @@ Symfony is the result of the work of many people who made the code better - Carlos Pereira De Amorim (epitre) - zenmate - Michal Trojanowski + - Lescot Edouard (idetox) - David Fuhr + - Rodrigo Aguilera - Mathias STRASSER (roukmoute) - Max Grigorian (maxakawizard) - Rostyslav Kinash @@ -822,13 +832,13 @@ Symfony is the result of the work of many people who made the code better - Xavier Briand (xavierbriand) - Ke WANG (yktd26) - Ivo Bathke (ivoba) + - David Molineus - Strate - Anton A. Sumin - Israel J. Carberry - Miquel Rodríguez Telep (mrtorrent) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - - M. Vondano - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Shaun Simmons (simshaun) @@ -909,6 +919,7 @@ Symfony is the result of the work of many people who made the code better - Davide Borsatto (davide.borsatto) - Julien DIDIER (juliendidier) - Dominik Ritter (dritter) + - Andreas Leathley (iquito) - Sebastian Grodzicki (sgrodzicki) - Mohamed Gamal - Jeroen van den Enden (stoefke) @@ -922,6 +933,7 @@ Symfony is the result of the work of many people who made the code better - Carson Full - Sergey Yastrebov - Trent Steel (trsteel88) + - Steve Grunwell - Yuen-Chi Lian - Tarjei Huse (tarjei) - Besnik Br @@ -949,10 +961,10 @@ Symfony is the result of the work of many people who made the code better - Casper Valdemar Poulsen - Josiah (josiah) - Guillaume Verstraete (versgui) - - Greg ORIOL - Joschi Kuphal - John Bohn (jbohn) - Marc Morera (mmoreram) + - Jason Tan - BENOIT POLASZEK (bpolaszek) - Julien Pauli - Mathieu Rochette (mathroc) @@ -1026,7 +1038,6 @@ Symfony is the result of the work of many people who made the code better - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) - Neil Ferreira - - Indra Gunawan (indragunawan) - Julie Hourcade (juliehde) - Dmitry Parnas (parnas) - Paul LE CORRE @@ -1034,6 +1045,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Gorgan - Tony Malzhacker - Mathieu MARCHOIS + - Tavo Nieves J - Cyril Quintin (cyqui) - Gerard van Helden (drm) - flack (flack) @@ -1098,6 +1110,7 @@ Symfony is the result of the work of many people who made the code better - Johnson Page (jwpage) - Ruben Gonzalez (rubenruateltek) - Michael Roterman (wtfzdotnet) + - Dieter - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) @@ -1133,6 +1146,7 @@ Symfony is the result of the work of many people who made the code better - Erik Saunier (snickers) - Thiago Cordeiro (thiagocordeiro) - Rootie + - Bernd Stellwag - Alireza Mirsepassi (alirezamirsepassi) - Daniel Alejandro Castro Arellano (lexcast) - sensio @@ -1157,6 +1171,7 @@ Symfony is the result of the work of many people who made the code better - Christian Jul Jensen - Alexandre GESLIN (alexandregeslin) - The Whole Life to Learn + - Pierre Tondereau - Alex Vo (votanlean) - Mikkel Paulson - ergiegonzaga @@ -1204,6 +1219,7 @@ Symfony is the result of the work of many people who made the code better - Luciano Mammino (loige) - fabios - Sander Coolen (scoolen) + - Laurent Clouet - Nicolas Le Goff (nlegoff) - Ben Oman - Chris de Kok @@ -1213,21 +1229,22 @@ Symfony is the result of the work of many people who made the code better - Guillaume (guill) - Igor Timoshenko (igor.timoshenko) - Manuele Menozzi - - zairig imad (zairigimad) - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) - Benoit Mallo - - Lescot Edouard (idetox) - Danilo Silva - Giuseppe Campanelli + - Valentin - pizzaminded - Arnaud PETITPAS (apetitpa) - Ken Stanley - Zachary Tong (polyfractal) - linh + - Guilherme Augusto Henschel - Mario Blažek (marioblazek) - Ashura - Hryhorii Hrebiniuk + - Eric Krona - johnstevenson - hamza - dantleech @@ -1238,6 +1255,7 @@ Symfony is the result of the work of many people who made the code better - Stanislav Kocanda - DerManoMann - Damien Fayet (rainst0rm) + - Ippei SUmida (ippey_s) - MatTheCat - Guillaume Royer - Artem (digi) @@ -1247,6 +1265,7 @@ Symfony is the result of the work of many people who made the code better - Pierrick VIGNAND (pierrick) - Vadim Tyukov (vatson) - Arman + - Adamo Crespi (aerendir) - David Wolter (davewww) - Sortex - chispita @@ -1322,12 +1341,15 @@ Symfony is the result of the work of many people who made the code better - Nikita Konstantinov - Martijn Evers - Philipp Fritsche + - tarlepp + - Luca Saba (lucasaba) - Benjamin Paap (benjaminpaap) - Claus Due (namelesscoder) - Christian - Alexandru Patranescu - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) + - Quentin Moreau (sheitak) - Mikkel Paulson - Michał Strzelecki - hugofonseca (fonsecas72) @@ -1420,13 +1442,13 @@ Symfony is the result of the work of many people who made the code better - Arun Philip - Rémi Leclerc - Jan Vernarsky + - Jonas Hünig - Amine Yakoubi - Eduardo García Sanz (coma) - Sergio (deverad) - Makdessi Alex - James Gilliland - fduch (fduch) - - David Molineus - Stuart Fyfe - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) @@ -1532,6 +1554,7 @@ Symfony is the result of the work of many people who made the code better - pthompson - Malaney J. Hill - Alexandre Pavy + - Adiel Cristo (arcristo) - Christian Flach (cmfcmf) - Cédric Girard (enk_) - Lars Ambrosius Wallenborn (larsborn) @@ -1547,6 +1570,7 @@ Symfony is the result of the work of many people who made the code better - Javier Espinosa - Anton Kroshilin - Dawid Sajdak + - Norman Soetbeer - Ludek Stepan - Aaron Stephens (astephens) - Craig Menning (cmenning) @@ -1557,7 +1581,6 @@ Symfony is the result of the work of many people who made the code better - Marc J. Schmidt (marcjs) - František Maša - Sebastian Schwarz - - Jason Tan - Marco Jantke - Saem Ghani - Clément LEFEBVRE @@ -1622,6 +1645,7 @@ Symfony is the result of the work of many people who made the code better - JL - Ilya Biryukov - Kim Laï Trinh + - Johan de Ruijter - Jason Desrosiers - m.chwedziak - Andreas Frömer @@ -1694,6 +1718,7 @@ Symfony is the result of the work of many people who made the code better - Mara Blaga - Rick Prent - skalpa + - Kai - Martin Eckhardt - Bartłomiej Zając - Pieter Jordaan @@ -1702,6 +1727,7 @@ Symfony is the result of the work of many people who made the code better - Michael Dowling (mtdowling) - Karlos Presumido (oneko) - Tony Vermeiren (tony) + - Jos Elstgeest - Thomas Counsell - BilgeXA - r1pp3rj4ck @@ -1746,6 +1772,7 @@ Symfony is the result of the work of many people who made the code better - Pablo Ogando Ferreira - Thomas Ploch - Simon Neidhold + - Ben Hakim - Valentin VALCIU - Jeremiah VALERIE - Julien Menth @@ -1773,6 +1800,7 @@ Symfony is the result of the work of many people who made the code better - Flavian (2much) - Gautier Deuette - mike + - Gilbertsoft - tadas - Kirk Madera - Keith Maika @@ -1792,6 +1820,7 @@ Symfony is the result of the work of many people who made the code better - Zdeněk Drahoš - Dan Harper - moldcraft + - Marcin Kruk - Antoine Bellion (abellion) - Ramon Kleiss (akathos) - Antonio Peric-Mazar (antonioperic) @@ -1853,6 +1882,7 @@ Symfony is the result of the work of many people who made the code better - Wing - Thomas Bibb - kick-the-bucket + - Joni Halme - Matt Farmer - catch - siganushka @@ -2216,6 +2246,7 @@ Symfony is the result of the work of many people who made the code better - Gyula Szucs - Tomas Liubinas - Alex + - Thomas P - Jan Hort - Klaas Naaijkens - Daniel González Cerviño @@ -2275,6 +2306,7 @@ Symfony is the result of the work of many people who made the code better - Vladimir Chernyshev (volch) - Wim Godden (wimg) - Yorkie Chadwick (yorkie76) + - Maxime Aknin (3m1x4m) - GuillaumeVerdon - Philipp Keck - Angel Fernando Quiroz Campos @@ -2383,7 +2415,6 @@ Symfony is the result of the work of many people who made the code better - Jack Wright - MrNicodemuz - Anonymous User - - Dieter - Paweł Tomulik - Eric J. Duran - Alexandru Bucur @@ -2546,6 +2577,7 @@ Symfony is the result of the work of many people who made the code better - Damián Nohales (eagleoneraptor) - Jordane VASPARD (elementaire) - Elliot Anderson (elliot) + - Erwan Nader (ernadoo) - Fabien D. (fabd) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) @@ -2619,6 +2651,7 @@ Symfony is the result of the work of many people who made the code better - Volker (skydiablo) - Success Go (successgo) - Julien Sanchez (sumbobyboys) + - Stephan Vierkant (svierkant) - Guillermo Gisinger (t3chn0r) - Markus Tacker (tacker) - Tom Newby (tomnewbyau) @@ -2645,6 +2678,7 @@ Symfony is the result of the work of many people who made the code better - simpson - Antoine Leblanc - drublic + - Andre Johnson - MaPePeR - Andreas Streichardt - Alexandre Segura diff --git a/UPGRADE-5.2.md b/UPGRADE-5.2.md index cd3c523d7644b..e62963fe2d50b 100644 --- a/UPGRADE-5.2.md +++ b/UPGRADE-5.2.md @@ -39,6 +39,12 @@ Form $builder->setDataMapper(new DataMapper(new PropertyPathAccessor())); ``` +HttpFoundation +-------------- + + * Deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. + * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead. + Lock ---- @@ -120,6 +126,36 @@ Validator * Deprecated the `NumberConstraintTrait` trait. + * Deprecated setting a Doctrine annotation reader via `ValidatorBuilder::enableAnnotationMapping()` + + Before: + + ```php + $builder->enableAnnotationMapping($reader); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->setDoctrineAnnotationReader($reader); + ``` + + * Deprecated creating a Doctrine annotation reader via `ValidatorBuilder::enableAnnotationMapping()` + + Before: + + ```php + $builder->enableAnnotationMapping(); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader(); + ``` + Security -------- diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 2ee58d9ce8f78..6e84d2c0dee2f 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -66,6 +66,8 @@ HttpFoundation * Removed `Response::create()`, `JsonResponse::create()`, `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use `__construct()` instead) + * Not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` throws an `InvalidArgumentException`; wrap your filter in a closure instead. + * Removed the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead. HttpKernel ---------- @@ -187,6 +189,36 @@ Validator * Removed the `NumberConstraintTrait` trait. +* `ValidatorBuilder::enableAnnotationMapping()` does not accept a Doctrine annotation reader anymore. + + Before: + + ```php + $builder->enableAnnotationMapping($reader); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->setDoctrineAnnotationReader($reader); + ``` + +* `ValidatorBuilder::enableAnnotationMapping()` won't automatically setup a Doctrine annotation reader anymore. + + Before: + + ```php + $builder->enableAnnotationMapping(); + ``` + + After: + + ```php + $builder->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader(); + ``` + Yaml ---- diff --git a/composer.json b/composer.json index c82f76928a98e..3034f796f7084 100644 --- a/composer.json +++ b/composer.json @@ -117,7 +117,6 @@ "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.10|^3.0", "doctrine/orm": "~2.4,>=2.4.5", - "doctrine/reflection": "~1.0", "doctrine/doctrine-bundle": "^2.0", "guzzlehttp/promises": "^1.3.1", "masterminds/html5": "^2.6", @@ -176,6 +175,6 @@ ], "minimum-stability": "dev", "extra": { - "branch-version": "5.2" + "branch-version": "5.x" } } diff --git a/phpunit b/phpunit index 71915eecb2b34..03bf63b0aae99 100755 --- a/phpunit +++ b/phpunit @@ -8,17 +8,12 @@ if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) { exit(1); } if (!getenv('SYMFONY_PHPUNIT_VERSION')) { - if (\PHP_VERSION_ID >= 70200) { - if (false === getenv('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT') && false !== strpos(@file_get_contents(__DIR__.'/src/Symfony/Component/HttpKernel/Kernel.php'), 'const MAJOR_VERSION = 3;')) { - putenv('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1'); - } - if (\PHP_VERSION_ID < 70300) { - putenv('SYMFONY_PHPUNIT_VERSION=8.5'); - } else { - putenv('SYMFONY_PHPUNIT_VERSION=9.4'); - } - } elseif (\PHP_VERSION_ID >= 70000) { - putenv('SYMFONY_PHPUNIT_VERSION=6.5'); + if (\PHP_VERSION_ID < 70200) { + putenv('SYMFONY_PHPUNIT_VERSION=7.5'); + } elseif (\PHP_VERSION_ID < 70300) { + putenv('SYMFONY_PHPUNIT_VERSION=8.5'); + } else { + putenv('SYMFONY_PHPUNIT_VERSION=9.4'); } } if (!getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php index 67bf68da01596..8e292cf36b8d7 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php @@ -191,7 +191,7 @@ private function sanitizeQuery(string $connectionName, array $query): array } } - list($query['params'][$j], $explainable, $runnable) = $this->sanitizeParam($param, $e); + [$query['params'][$j], $explainable, $runnable] = $this->sanitizeParam($param, $e); if (!$explainable) { $query['explainable'] = false; } @@ -227,7 +227,7 @@ private function sanitizeParam($var, ?\Throwable $error): array $a = []; $explainable = $runnable = true; foreach ($var as $k => $v) { - list($value, $e, $r) = $this->sanitizeParam($v, null); + [$value, $e, $r] = $this->sanitizeParam($v, null); $explainable = $explainable && $e; $runnable = $runnable && $r; $a[$k] = $value; diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index c1bbde27aa9c6..d2c8343ddb3c1 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -65,7 +65,7 @@ private function addTaggedSubscribers(ContainerBuilder $container) $taggedSubscribers = $this->findAndSortTags($subscriberTag, $container); foreach ($taggedSubscribers as $taggedSubscriber) { - list($id, $tag) = $taggedSubscriber; + [$id, $tag] = $taggedSubscriber; $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); foreach ($connections as $con) { if (!isset($this->connections[$con])) { @@ -84,7 +84,7 @@ private function addTaggedListeners(ContainerBuilder $container) $listenerRefs = []; foreach ($taggedListeners as $taggedListener) { - list($id, $tag) = $taggedListener; + [$id, $tag] = $taggedListener; if (!isset($tag['event'])) { throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); } diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index fd8b013185a69..d222659e5c080 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -42,7 +42,7 @@ public function guessType(string $class, string $property) return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); } - list($metadata, $name) = $ret; + [$metadata, $name] = $ret; if ($metadata->hasAssociation($property)) { $multiple = $metadata->isCollectionValuedAssociation($property); diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index bccb1a9ebdc3e..21b78bada3019 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -244,6 +244,7 @@ public function getParent() public function reset() { + $this->idReaders = []; $this->entityLoaders = []; } diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php index 3ec525d2cfd41..c6b219aa795ab 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Doctrine\Messenger; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Middleware\StackInterface; @@ -38,8 +39,8 @@ private function pingConnection(EntityManagerInterface $entityManager) $connection = $entityManager->getConnection(); try { - $connection->query($connection->getDatabasePlatform()->getDummySelectSQL()); - } catch (DBALException $e) { + $connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL()); + } catch (DBALException | Exception $e) { $connection->close(); $connection->connect(); } diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index ec8057ccb2b05..69d58e701dd57 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -89,10 +89,24 @@ public function getTypes(string $class, string $property, array $context = []) $associationMapping = $metadata->getAssociationMapping($property); if (isset($associationMapping['indexBy'])) { - $indexColumn = $associationMapping['indexBy']; /** @var ClassMetadataInfo $subMetadata */ $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); - $typeOfField = $subMetadata->getTypeOfField($subMetadata->getFieldForColumn($indexColumn)); + + // Check if indexBy value is a property + $fieldName = $associationMapping['indexBy']; + if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { + $fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']); + //Not a property, maybe a column name? + if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { + //Maybe the column name is the association join column? + $associationMapping = $subMetadata->getAssociationMapping($fieldName); + + /** @var ClassMetadataInfo $subMetadata */ + $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName); + $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); + } + } if (!$collectionKeyType = $this->getPhpType($typeOfField)) { return null; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php index 89aa779301350..33e6a6fd87235 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php @@ -24,7 +24,7 @@ */ class EntityTypePerformanceTest extends FormPerformanceTestCase { - const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; + private const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; /** * @var \Doctrine\ORM\EntityManager diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index ca9ab318d3f48..cc15da57ee6e8 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -39,14 +39,14 @@ class EntityTypeTest extends BaseTypeTest { const TESTED_TYPE = 'Symfony\Bridge\Doctrine\Form\Type\EntityType'; - const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; - const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; - const SINGLE_IDENT_NO_TO_STRING_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity'; - const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; - const SINGLE_ASSOC_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleAssociationToIntIdEntity'; - const SINGLE_STRING_CASTABLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringCastableIdEntity'; - const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; - const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity'; + private const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; + private const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; + private const SINGLE_IDENT_NO_TO_STRING_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity'; + private const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; + private const SINGLE_ASSOC_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleAssociationToIntIdEntity'; + private const SINGLE_STRING_CASTABLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringCastableIdEntity'; + private const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; + private const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity'; /** * @var EntityManager diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php index e491558a2addf..f99a48527c442 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware; @@ -49,7 +50,7 @@ public function testMiddlewarePingOk() { $this->connection->expects($this->once()) ->method('getDatabasePlatform') - ->will($this->throwException(new DBALException())); + ->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException())); $this->connection->expects($this->once()) ->method('close') @@ -68,7 +69,7 @@ public function testMiddlewarePingResetEntityManager() { $this->connection->expects($this->once()) ->method('getDatabasePlatform') - ->will($this->throwException(new DBALException())); + ->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException())); $this->entityManager->expects($this->once()) ->method('isOpen') diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 38ede592d9fe8..881b6b607e9d2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -64,10 +64,13 @@ public function testGetProperties() $expected = array_merge($expected, [ 'foo', 'bar', + 'indexedRguid', 'indexedBar', 'indexedFoo', + 'indexedBaz', 'indexedByDt', 'indexedByCustomType', + 'indexedBuz', ]); $this->assertEquals( @@ -143,6 +146,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], + ['indexedRguid', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + 'Doctrine\Common\Collections\Collection', + true, + new Type(Type::BUILTIN_TYPE_STRING), + new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') + )]], ['indexedBar', [new Type( Type::BUILTIN_TYPE_OBJECT, false, @@ -159,6 +170,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], + ['indexedBaz', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + Collection::class, + true, + new Type(Type::BUILTIN_TYPE_INT), + new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) + )]], ['simpleArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]], ['customFoo', null], ['notMapped', null], @@ -171,6 +190,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) )]], ['indexedByCustomType', null], + ['indexedBuz', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + Collection::class, + true, + new Type(Type::BUILTIN_TYPE_STRING), + new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) + )]], ['json', null], ]; diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 178ec9d0485d6..b7c5bffe6c7e4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -41,6 +41,11 @@ class DoctrineDummy */ public $bar; + /** + * @ManyToMany(targetEntity="DoctrineRelation", indexBy="rguid") + */ + protected $indexedRguid; + /** * @ManyToMany(targetEntity="DoctrineRelation", indexBy="rguid_column") */ @@ -51,6 +56,11 @@ class DoctrineDummy */ protected $indexedFoo; + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="baz", indexBy="baz_id") + */ + protected $indexedBaz; + /** * @Column(type="guid") */ @@ -123,6 +133,11 @@ class DoctrineDummy */ private $indexedByCustomType; + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="buzField", indexBy="buzField") + */ + protected $indexedBuz; + /** * @Column(type="json", nullable=true) */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php index e8f2b454cfa95..1131666483d22 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineFooType.php @@ -23,7 +23,7 @@ class DoctrineFooType extends Type /** * Type name. */ - const NAME = 'foo'; + private const NAME = 'foo'; /** * {@inheritdoc} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php index e480ca9d777ba..d6d9af6d70c38 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php @@ -40,6 +40,11 @@ class DoctrineRelation */ protected $foo; + /** + * @ManyToOne(targetEntity="DoctrineDummy") + */ + protected $baz; + /** * @Column(type="datetime") */ @@ -49,4 +54,10 @@ class DoctrineRelation * @Column(type="foo") */ private $customType; + + /** + * @Column(type="guid", name="different_than_field") + * @ManyToOne(targetEntity="DoctrineDummy", inversedBy="indexedBuz") + */ + protected $buzField; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php index 8ea165b49769a..4141dfa55e540 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidBinaryTypeTest.php @@ -52,11 +52,12 @@ public function testUlidConvertsToDatabaseValue() $this->assertEquals($expected, $actual); } - public function testNotSupportedStringUlidConversionToDatabaseValue() + public function testStringUlidConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $expected = Ulid::fromString(self::DUMMY_ULID)->toBinary(); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); - $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $this->assertEquals($expected, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php index 43715bb2324a1..f3969bcb4c725 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php @@ -68,11 +68,14 @@ public function testUlidInterfaceConvertsToDatabaseValue() $this->assertEquals('foo', $actual); } - public function testNotSupportedUlidStringConversionToDatabaseValue() + public function testUlidStringConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $ulid = Ulid::fromString(self::DUMMY_ULID); - $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $expected = $ulid->toRfc4122(); + + $this->assertEquals($expected, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php index 7d38606cf9054..b44a52578c5d2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidBinaryTypeTest.php @@ -52,11 +52,21 @@ public function testUuidConvertsToDatabaseValue() $this->assertEquals($expected, $actual); } - public function testNotSupportedStringUuidConversionToDatabaseValue() + public function testStringUuidConvertsToDatabaseValue() + { + $uuid = self::DUMMY_UUID; + + $expected = uuid_parse(self::DUMMY_UUID); + $actual = $this->type->convertToDatabaseValue($uuid, $this->platform); + + $this->assertEquals($expected, $actual); + } + + public function testInvalidUuidConversionForDatabaseValue() { $this->expectException(ConversionException::class); - $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); + $this->type->convertToDatabaseValue('abcdefg', $this->platform); } public function testNullConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php index c5c6658dad7bd..da775ca81573c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php @@ -68,11 +68,11 @@ public function testUuidInterfaceConvertsToDatabaseValue() $this->assertEquals('foo', $actual); } - public function testNotSupportedUuidStringConversionToDatabaseValue() + public function testUuidStringConvertsToDatabaseValue() { - $this->expectException(ConversionException::class); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); - $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); + $this->assertEquals(self::DUMMY_UUID, $actual); } public function testNotSupportedTypeConversionForDatabaseValue() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php index bd9791bc65a96..2c9c3815654ba 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php @@ -28,7 +28,7 @@ public function testAttributeWithDefaultProperty() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame(['email'], $constraint->fields); self::assertTrue($constraint->ignoreNull); self::assertSame('doctrine.orm.validator.unique', $constraint->validatedBy()); @@ -42,7 +42,7 @@ public function testAttributeWithCustomizedService() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame(['isbn'], $constraint->fields); self::assertSame('my_own_validator', $constraint->validatedBy()); self::assertSame('my_own_entity_manager', $constraint->em); @@ -57,7 +57,7 @@ public function testAttributeWithGroupsAndPaylod() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var UniqueEntity $constraint */ - list($constraint) = $metadata->getConstraints(); + [$constraint] = $metadata->getConstraints(); self::assertSame('uuid', $constraint->fields); self::assertSame('id', $constraint->errorPath); self::assertSame('some attached data', $constraint->payload); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 8507df94bf11c..7880ea92fede5 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -40,7 +40,7 @@ */ class UniqueEntityValidatorTest extends ConstraintValidatorTestCase { - const EM_NAME = 'foo'; + private const EM_NAME = 'foo'; /** * @var ObjectManager @@ -114,17 +114,8 @@ protected function createEntityManagerMock($repositoryMock) ->method('hasField') ->willReturn(true) ; - $reflParser = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionParser') - ->disableOriginalConstructor() - ->getMock() - ; - $refl = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionProperty') - ->setConstructorArgs([$reflParser, 'property-name']) - ->setMethods(['getValue']) - ->getMock() - ; + $refl = $this->createMock(\ReflectionProperty::class); $refl - ->expects($this->any()) ->method('getValue') ->willReturn(true) ; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 35a90044f7bab..31129a8c615d0 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -46,7 +46,8 @@ protected function setUp(): void public function testLoadClassMetadata() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{^Symfony\\\\Bridge\\\\Doctrine\\\\Tests\\\\Fixtures\\\\DoctrineLoader}')) ->getValidator() ; @@ -151,7 +152,8 @@ public function testLoadClassMetadata() public function testFieldMappingsConfiguration() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addXmlMappings([__DIR__.'/../Resources/validator/BaseUser.xml']) ->addLoader( new DoctrineLoader( @@ -192,7 +194,8 @@ public function regexpProvider() public function testClassNoAutoMapping() { $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{.*}')) ->getValidator(); diff --git a/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php b/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php index 9321d148ce3be..1dbb70abf556a 100644 --- a/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php +++ b/src/Symfony/Bridge/Doctrine/Types/AbstractBinaryUidType.php @@ -61,11 +61,19 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str return $value->toBinary(); } - if (null === $value) { + if (null === $value || '' === $value) { return null; } - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', AbstractUid::class]); + if (!\is_string($value)) { + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]); + } + + try { + return $this->getUidClass()::fromString($value)->toBinary(); + } catch (\InvalidArgumentException $e) { + throw ConversionException::conversionFailed($value, $this->getName()); + } } /** diff --git a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php index a14eb853e3868..4b57bc6b852f6 100644 --- a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php +++ b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php @@ -61,11 +61,19 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str return $value->toRfc4122(); } - if (null === $value) { + if (null === $value || '' === $value) { return null; } - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', AbstractUid::class]); + if (!\is_string($value)) { + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]); + } + + try { + return $this->getUidClass()::fromString($value)->toRfc4122(); + } catch (\InvalidArgumentException $e) { + throw ConversionException::conversionFailed($value, $this->getName()); + } } /** diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 78bc96de12ee2..48be4f9215efa 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -48,8 +48,7 @@ "doctrine/collections": "~1.0", "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.10|^3.0", - "doctrine/orm": "^2.6.3", - "doctrine/reflection": "~1.0" + "doctrine/orm": "^2.6.3" }, "conflict": { "doctrine/dbal": "<2.10", diff --git a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php index f170c526b8f74..f3d2fd8f024bb 100644 --- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php @@ -75,7 +75,7 @@ public function testGetLogsWithDebugProcessor2() $logger->info('test'); $this->assertCount(1, $logger->getLogs()); - list($record) = $logger->getLogs(); + [$record] = $logger->getLogs(); $this->assertEquals('test', $record['message']); $this->assertEquals(Logger::INFO, $record['priority']); diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php index 321bd7a8eed32..628facbb21277 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php @@ -22,7 +22,7 @@ class WebProcessorTest extends TestCase { public function testUsesRequestServerData() { - list($event, $server) = $this->createRequestEvent(); + [$event, $server] = $this->createRequestEvent(); $processor = new WebProcessor(); $processor->onKernelRequest($event); @@ -38,8 +38,8 @@ public function testUsesRequestServerData() public function testUseRequestClientIp() { - Request::setTrustedProxies(['192.168.0.1'], Request::HEADER_X_FORWARDED_ALL); - list($event, $server) = $this->createRequestEvent(['X_FORWARDED_FOR' => '192.168.0.2']); + Request::setTrustedProxies(['192.168.0.1'], Request::HEADER_X_FORWARDED_FOR); + [$event, $server] = $this->createRequestEvent(['X_FORWARDED_FOR' => '192.168.0.2']); $processor = new WebProcessor(); $processor->onKernelRequest($event); @@ -61,7 +61,7 @@ public function testCanBeConstructedWithExtraFields() $this->markTestSkipped('WebProcessor of the installed Monolog version does not support $extraFields parameter'); } - list($event, $server) = $this->createRequestEvent(); + [$event, $server] = $this->createRequestEvent(); $processor = new WebProcessor(['url', 'referrer']); $processor->onKernelRequest($event); diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php index 1e625e463a1e8..b132f473c547e 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php @@ -45,7 +45,7 @@ protected function additionalFailureDescription($other): string protected function exporter(): Exporter { - if (null !== $this->exporter) { + if (null === $this->exporter) { $this->exporter = new Exporter(); } diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 693883ed78762..6238fc0281209 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -123,7 +123,7 @@ public function startTestSuite($suite) $suiteName = $suite->getName(); foreach ($suite->tests() as $test) { - if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (!($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { continue; } if (null === Test::getPreserveGlobalStateSettings(\get_class($test), $test->getName(false))) { @@ -158,7 +158,7 @@ public function startTestSuite($suite) $testSuites = [$suite]; for ($i = 0; isset($testSuites[$i]); ++$i) { foreach ($testSuites[$i]->tests() as $test) { - if ($test instanceof TestSuite) { + if ($test instanceof \PHPUnit_Framework_TestSuite || $test instanceof TestSuite) { if (!class_exists($test->getName(), false)) { $testSuites[] = $test; continue; @@ -174,12 +174,19 @@ public function startTestSuite($suite) } } } elseif (2 === $this->state) { + $suites = [$suite]; $skipped = []; - foreach ($suite->tests() as $test) { - if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase) - || isset($this->wasSkipped[$suiteName]['*']) - || isset($this->wasSkipped[$suiteName][$test->getName()])) { - $skipped[] = $test; + while ($s = array_shift($suites)) { + foreach ($s->tests() as $test) { + if ($test instanceof \PHPUnit_Framework_TestSuite || $test instanceof TestSuite) { + $suites[] = $test; + continue; + } + if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) + && isset($this->wasSkipped[\get_class($test)][$test->getName()]) + ) { + $skipped[] = $test; + } } } $suite->setTests($skipped); @@ -189,21 +196,13 @@ public function startTestSuite($suite) public function addSkippedTest($test, \Exception $e, $time) { if (0 < $this->state) { - if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase) { - $class = \get_class($test); - $method = $test->getName(); - } else { - $class = $test->getName(); - $method = '*'; - } - - $this->isSkipped[$class][$method] = 1; + $this->isSkipped[\get_class($test)][$test->getName()] = 1; } } public function startTest($test) { - if (-2 < $this->state && ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (-2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { // This event is triggered before the test is re-run in isolation if ($this->willBeIsolated($test)) { $this->runsInSeparateProcess = tempnam(sys_get_temp_dir(), 'deprec'); @@ -313,7 +312,7 @@ public function endTest($test, $time) self::$expectedDeprecations = self::$gatheredDeprecations = []; self::$previousErrorHandler = null; } - if (!$this->runsInSeparateProcess && -2 < $this->state && ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) { + if (!$this->runsInSeparateProcess && -2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { if (\in_array('time-sensitive', $groups, true)) { ClockMock::withClockMock(false); } diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index f507af9085e44..e0a8d2f381c4a 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -238,7 +238,7 @@ } $prevRoot = getenv('COMPOSER_ROOT_VERSION'); putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); - $q = '\\' === \DIRECTORY_SEPARATOR ? '"' : ''; + $q = '\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 80000 ? '"' : ''; // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS $exit = proc_close(proc_open("$q$COMPOSER install --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index a9772a2b87342..cd7642911ab87 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -11,9 +11,10 @@ namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper; +use ProxyManager\Exception\ExceptionInterface; use ProxyManager\Generator\ClassGenerator; +use ProxyManager\Generator\MethodGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; -use ProxyManager\Version; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; @@ -83,7 +84,7 @@ public function getProxyCode(Definition $definition): string $code = $this->classGenerator->generate($this->generateProxyClass($definition)); $code = preg_replace('/^(class [^ ]++ extends )([^\\\\])/', '$1\\\\$2', $code); - if (version_compare(self::getProxyManagerVersion(), '2.2', '<')) { + if (!method_exists(MethodGenerator::class, 'fromReflectionWithoutBodyAndDocBlock')) { // proxy-manager < 2.2 $code = preg_replace( '/((?:\$(?:this|initializer|instance)->)?(?:publicProperties|initializer|valueHolder))[0-9a-f]++/', '${1}'.$this->getIdentifierSuffix($definition), @@ -91,22 +92,13 @@ public function getProxyCode(Definition $definition): string ); } - if (version_compare(self::getProxyManagerVersion(), '2.5', '<')) { + if (!is_subclass_of(ExceptionInterface::class, 'Throwable')) { // proxy-manager < 2.5 $code = preg_replace('/ \\\\Closure::bind\(function ((?:& )?\(\$instance(?:, \$value)?\))/', ' \Closure::bind(static function \1', $code); } return $code; } - private static function getProxyManagerVersion(): string - { - if (!class_exists(Version::class)) { - return '0.0.1'; - } - - return \defined(Version::class.'::VERSION') ? Version::VERSION : Version::getVersion(); - } - /** * Produces the proxy class name for the given definition. */ diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 974a38a9c3dca..8962a41dd366e 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -147,7 +147,7 @@ private function displayPathsText(SymfonyStyle $io, string $name) $shortnames[] = str_replace('\\', '/', $file->getRelativePathname()); } - list($namespace, $shortname) = $this->parseTemplateName($name); + [$namespace, $shortname] = $this->parseTemplateName($name); $alternatives = $this->findAlternatives($shortname, $shortnames); if (FilesystemLoader::MAIN_NAMESPACE !== $namespace) { $alternatives = array_map(function ($shortname) use ($namespace) { @@ -452,7 +452,7 @@ private function error(SymfonyStyle $io, string $message, array $alternatives = private function findTemplateFiles(string $name): array { - list($namespace, $shortname) = $this->parseTemplateName($name); + [$namespace, $shortname] = $this->parseTemplateName($name); $files = []; foreach ($this->getFilesystemLoaders() as $loader) { diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 0ff70eccd6886..7acf75fb9c17a 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -66,7 +66,7 @@ public function abbrClass(string $class): string public function abbrMethod(string $method): string { if (false !== strpos($method, '::')) { - list($class, $method) = explode('::', $method, 2); + [$class, $method] = explode('::', $method, 2); $result = sprintf('%s::%s()', $this->abbrClass($class), $method); } elseif ('Closure' === $method) { $result = sprintf('%1$s', $method); diff --git a/src/Symfony/Bridge/Twig/Node/TransNode.php b/src/Symfony/Bridge/Twig/Node/TransNode.php index da2b85d1c2861..8a126ba569172 100644 --- a/src/Symfony/Bridge/Twig/Node/TransNode.php +++ b/src/Symfony/Bridge/Twig/Node/TransNode.php @@ -52,7 +52,7 @@ public function compile(Compiler $compiler): void $defaults = $this->getNode('vars'); $vars = null; } - list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); + [$msg, $defaults] = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); $compiler ->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(') diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index dde9bada0961f..c4b5786744fb3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -18,7 +18,7 @@ CHANGELOG 5.1.0 ----- - + * Removed `--no-backup` option from `translation:update` command (broken since `5.0.0`) * Added link to source for controllers registered as named services * Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured) * Added the `framework.router.default_uri` configuration option to configure the default `RequestContext` diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 3eeefb4a94cad..9274d7e70baf6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -79,7 +79,6 @@ protected function configure() new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'), - new InputOption('no-backup', null, InputOption::VALUE_NONE, 'Should backup be disabled'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to update'), new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version', '1.2'), @@ -290,10 +289,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); } - if (true === $input->getOption('no-backup')) { - $this->writer->disableBackup(); - } - // save the files if (true === $input->getOption('force')) { $io->comment('Writing files...'); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 717495d053744..346047062201b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -92,13 +92,12 @@ public function getConfigTreeBuilder() ->arrayNode('trusted_headers') ->fixXmlConfig('trusted_header') ->performNoDeepMerging() - ->defaultValue(['x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix']) + ->defaultValue(['x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto']) ->beforeNormalization()->ifString()->then(function ($v) { return $v ? array_map('trim', explode(',', $v)) : []; })->end() ->enumPrototype() ->values([ 'forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', - 'x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix', ]) ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4c8284c350351..ea5e139e3fe64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -669,7 +669,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']); // Choose storage class based on the DSN - list($class) = explode(':', $config['dsn'], 2); + [$class] = explode(':', $config['dsn'], 2); if ('file' !== $class) { throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); } @@ -965,11 +965,11 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co ->replaceArgument(0, $config['default_uri']); } - if ($this->annotationsConfigEnabled) { + if (\PHP_VERSION_ID >= 80000 || $this->annotationsConfigEnabled) { $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) ->setPublic(false) ->addTag('routing.loader', ['priority' => -10]) - ->addArgument(new Reference('annotation_reader')); + ->addArgument(new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)); $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) ->setPublic(false) @@ -1303,11 +1303,14 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $definition->replaceArgument(0, $config['email_validation_mode']); if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { - throw new \LogicException('"enable_annotations" on the validator cannot be set as Annotations support is disabled.'); + if (!$this->annotationsConfigEnabled && \PHP_VERSION_ID < 80000) { + throw new \LogicException('"enable_annotations" on the validator cannot be set as Doctrine Annotations support is disabled.'); } - $validatorBuilder->addMethodCall('enableAnnotationMapping', [new Reference('annotation_reader')]); + $validatorBuilder->addMethodCall('enableAnnotationMapping', [true]); + if ($this->annotationsConfigEnabled) { + $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]); + } } if (\array_key_exists('static_method', $config) && $config['static_method']) { @@ -1564,13 +1567,13 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $serializerLoaders = []; if (isset($config['enable_annotations']) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { + if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { throw new \LogicException('"enable_annotations" on the serializer cannot be set as Annotations support is disabled.'); } $annotationLoader = new Definition( 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', - [new Reference('annotation_reader')] + [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] ); $annotationLoader->setPublic(false); @@ -2294,13 +2297,6 @@ private function resolveTrustedHeaders(array $headers): int case 'x-forwarded-host': $trustedHeaders |= Request::HEADER_X_FORWARDED_HOST; break; case 'x-forwarded-proto': $trustedHeaders |= Request::HEADER_X_FORWARDED_PROTO; break; case 'x-forwarded-port': $trustedHeaders |= Request::HEADER_X_FORWARDED_PORT; break; - case '!x-forwarded-host': $trustedHeaders &= ~Request::HEADER_X_FORWARDED_HOST; break; - case 'x-forwarded-all': - if (!\in_array('!x-forwarded-prefix', $headers)) { - throw new LogicException('When using "x-forwarded-all" in "framework.trusted_headers", "!x-forwarded-prefix" must be explicitly listed until support for X-Forwarded-Prefix is implemented.'); - } - $trustedHeaders |= Request::HEADER_X_FORWARDED_ALL; - break; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 120ce6c50b42c..c7838ff615360 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -15,6 +15,7 @@ use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory; use Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory; +use Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener; use Symfony\Component\Messenger\EventListener\DispatchPcntlSignalListener; use Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener; use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; @@ -157,6 +158,9 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) + ->set('messenger.failure.add_error_details_stamp_listener', AddErrorDetailsStampListener::class) + ->tag('kernel.event_subscriber') + ->set('messenger.failure.send_failed_message_to_failure_transport_listener', SendFailedMessageToFailureTransportListener::class) ->args([ abstract_arg('failure transport'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php index 92ef379b1b819..8a54680c0f557 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php @@ -26,7 +26,7 @@ public function testWarmUp() $validatorBuilder->addXmlMapping(__DIR__.'/../Fixtures/Validation/Resources/person.xml'); $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/author.yml'); $validatorBuilder->addMethodMapping('loadValidatorMetadata'); - $validatorBuilder->enableAnnotationMapping(); + $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader(); $file = sys_get_temp_dir().'/cache-validator.php'; @unlink($file); @@ -46,7 +46,7 @@ public function testWarmUpWithAnnotations() { $validatorBuilder = new ValidatorBuilder(); $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/categories.yml'); - $validatorBuilder->enableAnnotationMapping(); + $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader(); $file = sys_get_temp_dir().'/cache-validator-with-annotations.php'; @unlink($file); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 6bc6d958b79b4..8dd31fb7d0c25 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -341,9 +341,9 @@ protected static function getBundleDefaultConfig() 'secret' => 's3cr3t', 'trusted_hosts' => [], 'trusted_headers' => [ - 'x-forwarded-all', - '!x-forwarded-host', - '!x-forwarded-prefix', + 'x-forwarded-for', + 'x-forwarded-port', + 'x-forwarded-proto', ], 'csrf_protection' => [ 'enabled' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index fdb1d5a6014a5..b902d3b636a2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -870,7 +870,7 @@ public function testValidation() $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class); - $this->assertCount($annotations ? 7 : 6, $calls); + $this->assertCount($annotations ? 8 : 6, $calls); $this->assertSame('setConstraintValidatorFactory', $calls[0][0]); $this->assertEquals([new Reference('validator.validator_factory')], $calls[0][1]); $this->assertSame('setTranslator', $calls[1][0]); @@ -882,6 +882,7 @@ public function testValidation() $i = 3; if ($annotations) { $this->assertSame('enableAnnotationMapping', $calls[++$i][0]); + $this->assertSame('setDoctrineAnnotationReader', $calls[++$i][0]); } $this->assertSame('addMethodMapping', $calls[++$i][0]); $this->assertSame(['loadValidatorMetadata'], $calls[$i][1]); @@ -923,13 +924,14 @@ public function testValidationAnnotations() $calls = $container->getDefinition('validator.builder')->getMethodCalls(); - $this->assertCount(7, $calls); + $this->assertCount(8, $calls); $this->assertSame('enableAnnotationMapping', $calls[4][0]); - $this->assertEquals([new Reference('annotation_reader')], $calls[4][1]); - $this->assertSame('addMethodMapping', $calls[5][0]); - $this->assertSame(['loadValidatorMetadata'], $calls[5][1]); - $this->assertSame('setMappingCache', $calls[6][0]); - $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[6][1]); + $this->assertSame('setDoctrineAnnotationReader', $calls[5][0]); + $this->assertEquals([new Reference('annotation_reader')], $calls[5][1]); + $this->assertSame('addMethodMapping', $calls[6][0]); + $this->assertSame(['loadValidatorMetadata'], $calls[6][1]); + $this->assertSame('setMappingCache', $calls[7][0]); + $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[7][1]); // no cache this time } @@ -944,14 +946,15 @@ public function testValidationPaths() $calls = $container->getDefinition('validator.builder')->getMethodCalls(); - $this->assertCount(8, $calls); + $this->assertCount(9, $calls); $this->assertSame('addXmlMappings', $calls[3][0]); $this->assertSame('addYamlMappings', $calls[4][0]); $this->assertSame('enableAnnotationMapping', $calls[5][0]); - $this->assertSame('addMethodMapping', $calls[6][0]); - $this->assertSame(['loadValidatorMetadata'], $calls[6][1]); - $this->assertSame('setMappingCache', $calls[7][0]); - $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[7][1]); + $this->assertSame('setDoctrineAnnotationReader', $calls[6][0]); + $this->assertSame('addMethodMapping', $calls[7][0]); + $this->assertSame(['loadValidatorMetadata'], $calls[7][1]); + $this->assertSame('setMappingCache', $calls[8][0]); + $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[8][1]); $xmlMappings = $calls[3][1][0]; $this->assertCount(3, $xmlMappings); @@ -1004,11 +1007,12 @@ public function testValidationNoStaticMethod() $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class); - $this->assertCount($annotations ? 6 : 5, $calls); + $this->assertCount($annotations ? 7 : 5, $calls); $this->assertSame('addXmlMappings', $calls[3][0]); $i = 3; if ($annotations) { $this->assertSame('enableAnnotationMapping', $calls[++$i][0]); + $this->assertSame('setDoctrineAnnotationReader', $calls[++$i][0]); } $this->assertSame('setMappingCache', $calls[++$i][0]); $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[$i][1]); @@ -1232,7 +1236,7 @@ public function testSerializerMapping() $projectDir = $container->getParameter('kernel.project_dir'); $configDir = __DIR__.'/Fixtures/TestBundle/Resources/config'; $expectedLoaders = [ - new Definition(AnnotationLoader::class, [new Reference('annotation_reader')]), + new Definition(AnnotationLoader::class, [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)]), new Definition(XmlFileLoader::class, [$configDir.'/serialization.xml']), new Definition(YamlFileLoader::class, [$configDir.'/serialization.yml']), new Definition(YamlFileLoader::class, [$projectDir.'/config/serializer/foo.yml']), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php index 0d9464d7dfab4..168cd2d45a52a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php @@ -71,7 +71,7 @@ public function showFlashAction(Request $request) $session = $request->getSession(); if ($session->getFlashBag()->has('notice')) { - list($output) = $session->getFlashBag()->get('notice'); + [$output] = $session->getFlashBag()->get('notice'); } else { $output = 'No flash was set.'; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 8ae38fd392168..08c920fd951c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -155,7 +155,7 @@ protected function initialize() $this->addResourceFiles(); } foreach ($this->resources as $key => $params) { - list($format, $resource, $locale, $domain) = $params; + [$format, $resource, $locale, $domain] = $params; parent::addResource($format, $resource, $locale, $domain); } $this->resources = []; diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index b6dd28d614b39..5e3b3c102ef37 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -29,7 +29,7 @@ "symfony/polyfill-php80": "^1.15", "symfony/filesystem": "^4.4|^5.0", "symfony/finder": "^4.4|^5.0", - "symfony/routing": "^5.1" + "symfony/routing": "^5.2" }, "require-dev": { "doctrine/annotations": "~1.7", diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php index 94d5a184727e8..1cd90fe70af1a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php @@ -45,8 +45,12 @@ public function process(ContainerBuilder $container) $container->setAlias('security.token_storage', 'security.untracked_token_storage')->setPublic(true); $container->getDefinition('security.untracked_token_storage')->addTag('kernel.reset', ['method' => 'reset']); } elseif ($container->hasDefinition('security.context_listener')) { - $container->getDefinition('security.context_listener') - ->setArgument(6, [new Reference('security.token_storage'), 'enableUsageTracking']); + $tokenStorageClass = $container->getParameterBag()->resolveValue($container->findDefinition('security.token_storage')->getClass()); + + if (method_exists($tokenStorageClass, 'enableUsageTracking')) { + $container->getDefinition('security.context_listener') + ->setArgument(6, [new Reference('security.token_storage'), 'enableUsageTracking']); + } } } } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 6e3d806cd5551..4d0232d9217b2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -276,7 +276,7 @@ private function createFirewalls(array $config, ContainerBuilder $container) $configId = 'security.firewall.map.config.'.$name; - list($matcher, $listeners, $exceptionListener, $logoutListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId); + [$matcher, $listeners, $exceptionListener, $logoutListener] = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId); $contextId = 'security.firewall.map.context.'.$name; $isLazy = !$firewall['stateless'] && (!empty($firewall['anonymous']['lazy']) || $firewall['lazy']); @@ -460,7 +460,7 @@ private function createFirewall(ContainerBuilder $container, string $id, array $ // Authentication listeners $firewallAuthenticationProviders = []; - list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); + [$authListeners, $defaultEntryPoint] = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); if (!$this->authenticatorManagerEnabled) { $authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders); @@ -578,7 +578,7 @@ private function createAuthenticationListeners(ContainerBuilder $container, stri $entryPoints[$key] = $entryPoint; } } else { - list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); + [$provider, $listenerId, $defaultEntryPoint] = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); $listeners[] = new Reference($listenerId); $authenticationProviders[] = $provider; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php new file mode 100644 index 0000000000000..afdbf9afaf60f --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterTokenUsageTrackingPassTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterTokenUsageTrackingPass; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage; +use Symfony\Component\Security\Http\Firewall\ContextListener; + +class RegisterTokenUsageTrackingPassTest extends TestCase +{ + public function testTokenStorageIsUntrackedIfSessionIsMissing() + { + $container = new ContainerBuilder(); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $this->assertTrue($container->hasAlias('security.token_storage')); + $this->assertEquals(new Alias('security.untracked_token_storage', true), $container->getAlias('security.token_storage')); + } + + public function testContextListenerIsNotModifiedIfTokenStorageDoesNotSupportUsageTracking() + { + $container = new ContainerBuilder(); + + $container->setParameter('security.token_storage.class', TokenStorage::class); + $container->register('session', Session::class); + $container->register('security.context_listener', ContextListener::class) + ->setArguments([ + new Reference('security.untracked_token_storage'), + [], + 'main', + new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('event_dispatcher', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('security.authentication.trust_resolver'), + ]); + $container->register('security.token_storage', '%security.token_storage.class%'); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $this->assertCount(6, $container->getDefinition('security.context_listener')->getArguments()); + } + + public function testContextListenerEnablesUsageTrackingIfSupportedByTokenStorage() + { + $container = new ContainerBuilder(); + + $container->setParameter('security.token_storage.class', UsageTrackingTokenStorage::class); + $container->register('session', Session::class); + $container->register('security.context_listener', ContextListener::class) + ->setArguments([ + new Reference('security.untracked_token_storage'), + [], + 'main', + new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('event_dispatcher', ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('security.authentication.trust_resolver'), + ]); + $container->register('security.token_storage', '%security.token_storage.class%'); + $container->register('security.untracked_token_storage', TokenStorage::class); + + $compilerPass = new RegisterTokenUsageTrackingPass(); + $compilerPass->process($container); + + $contextListener = $container->getDefinition('security.context_listener'); + + $this->assertCount(7, $container->getDefinition('security.context_listener')->getArguments()); + $this->assertEquals([new Reference('security.token_storage'), 'enableUsageTracking'], $contextListener->getArgument(6)); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index a7f56e9958785..f9d8094fbccd4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -235,7 +235,7 @@ public function testAccess() } $matcherIds = []; - foreach ($rules as list($matcherId, $attributes, $channel)) { + foreach ($rules as [$matcherId, $attributes, $channel]) { $requestMatcher = $container->getDefinition($matcherId); $this->assertArrayNotHasKey($matcherId, $matcherIds); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php index 364a9249224cb..4b1ddcf09c3e6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php @@ -19,7 +19,7 @@ class AbstractFactoryTest extends TestCase { public function testCreate() { - list($container, $authProviderId, $listenerId, $entryPointId) = $this->callFactory('foo', [ + [$container, $authProviderId, $listenerId, $entryPointId] = $this->callFactory('foo', [ 'use_forward' => true, 'failure_path' => '/foo', 'success_handler' => 'custom_success_handler', @@ -61,7 +61,7 @@ public function testDefaultFailureHandler($serviceId, $defaultHandlerInjection) $options['failure_handler'] = $serviceId; } - list($container) = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); + [$container] = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); $definition = $container->getDefinition('abstract_listener.foo'); $arguments = $definition->getArguments(); @@ -99,7 +99,7 @@ public function testDefaultSuccessHandler($serviceId, $defaultHandlerInjection) $options['success_handler'] = $serviceId; } - list($container) = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); + [$container] = $this->callFactory('foo', $options, 'user_provider', 'entry_point'); $definition = $container->getDefinition('abstract_listener.foo'); $arguments = $definition->getArguments(); @@ -150,7 +150,7 @@ protected function callFactory($id, $config, $userProviderId, $defaultEntryPoint $container->register('custom_success_handler'); $container->register('custom_failure_handler'); - list($authProviderId, $listenerId, $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); + [$authProviderId, $listenerId, $entryPointId] = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); return [$container, $authProviderId, $listenerId, $entryPointId]; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php index 8215aaf9c90fb..7d6f5f6591278 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php @@ -104,7 +104,7 @@ public function testBasicCreate() 'authenticators' => ['authenticator123'], 'entry_point' => null, ]; - list($container, $entryPointId) = $this->executeCreate($config, null); + [$container, $entryPointId] = $this->executeCreate($config, null); $this->assertEquals('authenticator123', $entryPointId); $providerDefinition = $container->getDefinition('security.authentication.provider.guard.my_firewall'); @@ -127,7 +127,7 @@ public function testExistingDefaultEntryPointUsed() 'authenticators' => ['authenticator123'], 'entry_point' => null, ]; - list(, $entryPointId) = $this->executeCreate($config, 'some_default_entry_point'); + [, $entryPointId] = $this->executeCreate($config, 'some_default_entry_point'); $this->assertEquals('some_default_entry_point', $entryPointId); } @@ -160,7 +160,7 @@ public function testCreateWithEntryPoint() 'authenticators' => ['authenticator123', 'authenticatorABC'], 'entry_point' => 'authenticatorABC', ]; - list(, $entryPointId) = $this->executeCreate($config, null); + [, $entryPointId] = $this->executeCreate($config, null); $this->assertEquals('authenticatorABC', $entryPointId); } @@ -196,7 +196,7 @@ private function executeCreate(array $config, $defaultEntryPointId) $userProviderId = 'my_user_provider'; $factory = new GuardAuthenticationFactory(); - list(, , $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); + [, , $entryPointId] = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId); return [$container, $entryPointId]; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php index f49cfa84c07e1..394e59cc4263e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php @@ -110,6 +110,7 @@ public function testFormLoginRedirectsToProtectedResourceAfterLogin(array $optio /** * @dataProvider provideInvalidCredentials + * @group time-sensitive */ public function testLoginThrottling($username, $password) { diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index fa590a54e908d..7e49cd4fde9b5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -23,7 +23,7 @@ class FirewallMapTest extends TestCase { - const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; + private const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; public function testGetListenersWithEmptyMap() { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index 30dd95e5c75eb..bb9daab006fce 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -72,7 +72,7 @@ public function getNames(Profile $profile) continue; } - list($name, $template) = $arguments; + [$name, $template] = $arguments; if (!$this->profiler->has($name) || !$profile->hasCollector($name)) { continue; diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index 79ca7943109ff..c24661de76ab5 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -133,7 +133,7 @@ public static function fromString(string $cookie, string $url = null) throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0])); } - list($name, $value) = explode('=', array_shift($parts), 2); + [$name, $value] = explode('=', array_shift($parts), 2); $values = [ 'name' => trim($name), diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index efca364ba7ce6..aef2a9a7deb57 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -74,7 +74,7 @@ static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifeti $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) { - $item->expiresAt(\DateTime::createFromFormat('U.u', $item->metadata[CacheItem::METADATA_EXPIRY])); + $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); } elseif (0 < $defaultLifetime) { $item->expiresAfter($defaultLifetime); } diff --git a/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php b/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php index 0fd272700198c..a0e8f4027181c 100644 --- a/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/CouchbaseBucketAdapter.php @@ -134,7 +134,7 @@ private static function getOptions(string $options): array $optionsInArray = explode('&', $options); foreach ($optionsInArray as $option) { - list($key, $value) = explode('=', $option); + [$key, $value] = explode('=', $option); if (\in_array($key, static::VALID_DSN_OPTIONS, true)) { $results[$key] = $value; diff --git a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php index 038892eabc3ba..53ead840c4eee 100644 --- a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php @@ -123,7 +123,7 @@ public static function createConnection($servers, array $options = []) } $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[2])) { - list($username, $password) = explode(':', $m[2], 2) + [1 => null]; + [$username, $password] = explode(':', $m[2], 2) + [1 => null]; } return 'file:'.($m[1] ?? ''); diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 0abf787f44ddb..a8f8f3038a652 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -401,7 +401,7 @@ private function initialize() if (2 !== \count($values) || !isset($values[0], $values[1])) { $this->keys = $this->values = []; } else { - list($this->keys, $this->values) = $values; + [$this->keys, $this->values] = $values; } } diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index 9527fa63ffae9..faba3d8822a75 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -88,7 +88,7 @@ static function (CacheItemInterface $innerItem, array $item) { $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; } $innerItem->set($item["\0*\0value"]); - $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', 0 === $item["\0*\0expiry"] ? \PHP_INT_MAX : $item["\0*\0expiry"])) : null); + $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', 0 === $item["\0*\0expiry"] ? \PHP_INT_MAX : $item["\0*\0expiry"])) : null); }, null, CacheItem::class diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index 57c355eaa43a6..d7fe3ebc60b9e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -118,9 +118,9 @@ public function testGetMetadata() $metadata = $item->getMetadata(); $this->assertArrayHasKey(CacheItem::METADATA_CTIME, $metadata); - $this->assertEqualsWithDelta(1000, $metadata[CacheItem::METADATA_CTIME], 6); + $this->assertEqualsWithDelta(999, $metadata[CacheItem::METADATA_CTIME], 10); $this->assertArrayHasKey(CacheItem::METADATA_EXPIRY, $metadata); - $this->assertEqualsWithDelta(9.5 + time(), $metadata[CacheItem::METADATA_EXPIRY], 0.6); + $this->assertEqualsWithDelta(9 + time(), $metadata[CacheItem::METADATA_EXPIRY], 1); } public function testDefaultLifeTime() diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php index f1ee0d6c71dff..bf1ca393cecc7 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -156,7 +156,7 @@ public function save(CacheItemInterface $item): bool $this->keys[$key] = $id = \count($this->values); $this->data[$key] = $this->values[$id] = $item->get(); $this->warmUp($this->data); - list($this->keys, $this->values) = eval(substr(file_get_contents($this->file), 6)); + [$this->keys, $this->values] = eval(substr(file_get_contents($this->file), 6)); }, $this, PhpArrayAdapter::class))(); return true; diff --git a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php index de3dbfc7a8b3c..86c1aac489dd9 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php @@ -14,6 +14,7 @@ use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerAwareTrait; use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; /** * @author Nicolas Grekas diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 468656e333fa3..34b8aa73a5fc1 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -111,7 +111,7 @@ public static function createConnection($servers, array $options = []) } $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[2])) { - list($username, $password) = explode(':', $m[2], 2) + [1 => null]; + [$username, $password] = explode(':', $m[2], 2) + [1 => null]; } return 'file:'.($m[1] ?? ''); diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 86e15b07b82de..317879aa494e2 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -486,7 +486,7 @@ private function pipeline(\Closure $generator, $redis = null): \Generator foreach ($connections as $h => $c) { $connections[$h] = $c[0]->exec(); } - foreach ($results as $k => list($h, $c)) { + foreach ($results as $k => [$h, $c]) { $results[$k] = $connections[$h][$c]; } } else { diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 1107fff232294..66291014ec92b 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -339,7 +339,7 @@ protected function normalizeValue($value) */ protected function remapXml(array $value) { - foreach ($this->xmlRemappings as list($singular, $plural)) { + foreach ($this->xmlRemappings as [$singular, $plural]) { if (!isset($value[$singular])) { continue; } diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php index f686c53b5718f..ef60eff374dba 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php @@ -53,7 +53,7 @@ private function writeNode(NodeInterface $node, int $depth = 0, bool $root = fal }); if (\count($remapping)) { - list($singular) = current($remapping); + [$singular] = current($remapping); $rootName = $singular; } } diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 60896408a6059..91d1688d06c23 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -418,13 +418,13 @@ private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $tit $crossings = $this->style->getCrossingChars(); if (self::SEPARATOR_MID === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; } elseif (self::SEPARATOR_TOP === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; } else { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; } $markup = $leftChar; diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index c93bda5a9bf0a..2171bdc968519 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -165,11 +165,25 @@ private function parseArgument(string $token) // unexpected argument } else { $all = $this->definition->getArguments(); + $symfonyCommandName = null; + if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) { + $symfonyCommandName = $this->arguments['command'] ?? null; + unset($all[$key]); + } + if (\count($all)) { - throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); + if ($symfonyCommandName) { + $message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all))); + } else { + $message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))); + } + } elseif ($symfonyCommandName) { + $message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token); + } else { + $message = sprintf('No arguments expected, got "%s".', $token); } - throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + throw new RuntimeException($message); } } diff --git a/src/Symfony/Component/Console/Output/ConsoleOutput.php b/src/Symfony/Component/Console/Output/ConsoleOutput.php index 96664f1508abb..2cda213a04b09 100644 --- a/src/Symfony/Component/Console/Output/ConsoleOutput.php +++ b/src/Symfony/Component/Console/Output/ConsoleOutput.php @@ -41,6 +41,13 @@ public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decor { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + if (null === $formatter) { + // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter. + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated); + + return; + } + $actualDecorated = $this->isDecorated(); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); diff --git a/src/Symfony/Component/Console/Tests/ColorTest.php b/src/Symfony/Component/Console/Tests/ColorTest.php index 7fe008cae1c1d..571963cfce788 100644 --- a/src/Symfony/Component/Console/Tests/ColorTest.php +++ b/src/Symfony/Component/Console/Tests/ColorTest.php @@ -40,4 +40,20 @@ public function testTrueColors() $color = new Color('#ffffff', '#000000'); $this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' ')); } + + public function testDegradedTrueColors() + { + $colorterm = getenv('COLORTERM'); + putenv('COLORTERM='); + + try { + $color = new Color('#f00', '#ff0'); + $this->assertSame("\033[31;43m \033[39;49m", $color->apply(' ')); + + $color = new Color('#c0392b', '#f1c40f'); + $this->assertSame("\033[31;43m \033[39;49m", $color->apply(' ')); + } finally { + putenv('COLORTERM='.$colorterm); + } + } } diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 51cc6e5175396..57a561091e77a 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -247,6 +247,16 @@ public function provideInvalidInput() new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_NONE)]), 'The "-Щ" option does not exist.', ], + [ + ['cli.php', 'acme:foo', 'bar'], + new InputDefinition([new InputArgument('command', InputArgument::REQUIRED)]), + 'No arguments expected for "acme:foo" command, got "bar"', + ], + [ + ['cli.php', 'acme:foo', 'bar'], + new InputDefinition([new InputArgument('name', InputArgument::REQUIRED)]), + 'Too many arguments, expected arguments "name".', + ], ]; } diff --git a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php index db39a02b8a616..33a5371d6e4b9 100644 --- a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php +++ b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php @@ -18,11 +18,19 @@ class ConsoleOutputTest extends TestCase { - public function testConstructor() + public function testConstructorWithoutFormatter() { $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true); $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); - $this->assertSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), '__construct() takes a formatter or null as the third argument'); + $this->assertNotSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), 'ErrorOutput should use it own formatter'); + } + + public function testConstructorWithFormatter() + { + $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true, $formatter = new OutputFormatter()); + $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); + $this->assertSame($formatter, $output->getFormatter()); + $this->assertSame($formatter, $output->getErrorOutput()->getFormatter(), 'Output and ErrorOutput should use the same provided formatter'); } public function testSetFormatter() @@ -31,6 +39,7 @@ public function testSetFormatter() $outputFormatter = new OutputFormatter(); $output->setFormatter($outputFormatter); $this->assertSame($outputFormatter, $output->getFormatter()); + $this->assertSame($outputFormatter, $output->getErrorOutput()->getFormatter()); } public function testSetVerbosity() diff --git a/src/Symfony/Component/CssSelector/Parser/Parser.php b/src/Symfony/Component/CssSelector/Parser/Parser.php index e8a46c062ce7f..a03f1527f144b 100644 --- a/src/Symfony/Component/CssSelector/Parser/Parser.php +++ b/src/Symfony/Component/CssSelector/Parser/Parser.php @@ -113,7 +113,7 @@ private function parseSelectorList(TokenStream $stream): array private function parserSelectorNode(TokenStream $stream): Node\SelectorNode { - list($result, $pseudoElement) = $this->parseSimpleSelector($stream); + [$result, $pseudoElement] = $this->parseSimpleSelector($stream); while (true) { $stream->skipWhitespace(); @@ -134,7 +134,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode $combinator = ' '; } - list($nextSelector, $pseudoElement) = $this->parseSimpleSelector($stream); + [$nextSelector, $pseudoElement] = $this->parseSimpleSelector($stream); $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); } @@ -209,7 +209,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation = throw SyntaxErrorException::nestedNot(); } - list($argument, $argumentPseudoElement) = $this->parseSimpleSelector($stream, true); + [$argument, $argumentPseudoElement] = $this->parseSimpleSelector($stream, true); $next = $stream->getNext(); if (null !== $argumentPseudoElement) { diff --git a/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php b/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php index 2b79aaafc9fcb..d3f7222a4d0ab 100644 --- a/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php +++ b/src/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php @@ -51,7 +51,7 @@ public function getFunctionTranslators(): array public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr { try { - list($a, $b) = Parser::parseSeries($function->getArguments()); + [$a, $b] = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); } diff --git a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php index 60059267beea4..f3535d68b0fe5 100644 --- a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php +++ b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php @@ -54,9 +54,9 @@ public function getValues(): array public function setValues(array $values) { if (5 === \count($values)) { - list($this->value, $this->identifier, $this->used, $this->type, $this->file) = $values; + [$this->value, $this->identifier, $this->used, $this->type, $this->file] = $values; } else { - list($this->value, $this->identifier, $this->used) = $values; + [$this->value, $this->identifier, $this->used] = $values; } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index 76c954a987245..85478da5e9b16 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -127,7 +127,7 @@ protected function getConstructor(Definition $definition, bool $required) } if ($factory) { - list($class, $method) = $factory; + [$class, $method] = $factory; if ($class instanceof Reference) { $class = $this->container->findDefinition((string) $class)->getClass(); } elseif ($class instanceof Definition) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index ba10e92b1e7c3..d201b58b987aa 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -126,7 +126,7 @@ private function doProcessValue($value, bool $isRoot = false) $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot); if ($constructor) { - list(, $arguments) = array_shift($this->methodCalls); + [, $arguments] = array_shift($this->methodCalls); if ($arguments !== $value->getArguments()) { $value->setArguments($arguments); @@ -152,7 +152,7 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): foreach ($this->methodCalls as $i => $call) { $this->decoratedMethodIndex = $i; - list($method, $arguments) = $call; + [$method, $arguments] = $call; if ($method instanceof \ReflectionFunctionAbstract) { $reflectionMethod = $method; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php index fc1027677d41c..5c255cfb60761 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php @@ -38,7 +38,7 @@ protected function processValue($value, bool $isRoot = false) $alreadyCalledMethods = []; $withers = []; - foreach ($value->getMethodCalls() as list($method)) { + foreach ($value->getMethodCalls() as [$method]) { $alreadyCalledMethods[strtolower($method)] = true; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index b15506d20b697..9313d7a6e616d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -46,9 +46,9 @@ public function process(ContainerBuilder $container) } $decoratingDefinitions = []; - foreach ($definitions as list($id, $definition)) { + foreach ($definitions as [$id, $definition]) { $decoratedService = $definition->getDecoratedService(); - list($inner, $renamedId) = $decoratedService; + [$inner, $renamedId] = $decoratedService; $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; $definition->setDecoratedService(null); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index b86c1b786477b..61e99d73becf9 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -41,11 +41,11 @@ public function process(ContainerBuilder $container) try { parent::process($container); - foreach ($this->unusedBindings as list($key, $serviceId, $bindingType, $file)) { + foreach ($this->unusedBindings as [$key, $serviceId, $bindingType, $file]) { $argumentType = $argumentName = $message = null; if (false !== strpos($key, ' ')) { - list($argumentType, $argumentName) = explode(' ', $key, 2); + [$argumentType, $argumentName] = explode(' ', $key, 2); } elseif ('$' === $key[0]) { $argumentName = $key; } else { @@ -117,7 +117,7 @@ protected function processValue($value, bool $isRoot = false) $bindingNames = []; foreach ($bindings as $key => $binding) { - list($bindingValue, $bindingId, $used, $bindingType, $file) = $binding->getValues(); + [$bindingValue, $bindingId, $used, $bindingType, $file] = $binding->getValues(); if ($used) { $this->usedBindings[$bindingId] = true; unset($this->unusedBindings[$bindingId]); @@ -156,7 +156,7 @@ protected function processValue($value, bool $isRoot = false) } foreach ($calls as $i => $call) { - list($method, $arguments) = $call; + [$method, $arguments] = $call; if ($method instanceof \ReflectionFunctionAbstract) { $reflectionMethod = $method; @@ -210,7 +210,7 @@ protected function processValue($value, bool $isRoot = false) } if ($constructor) { - list(, $arguments) = array_pop($calls); + [, $arguments] = array_pop($calls); if ($arguments !== $value->getArguments()) { $value->setArguments($arguments); @@ -229,7 +229,7 @@ protected function processValue($value, bool $isRoot = false) */ private function getBindingValue(BoundArgument $binding) { - list($bindingValue, $bindingId) = $binding->getValues(); + [$bindingValue, $bindingId] = $binding->getValues(); $this->usedBindings[$bindingId] = true; unset($this->unusedBindings[$bindingId]); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php index fd3c5e4d1d9f1..c1c5748e8d601 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php @@ -41,7 +41,7 @@ protected function processValue($value, bool $isRoot = false) $calls[] = ['__construct', $value->getArguments()]; foreach ($calls as $i => $call) { - list($method, $arguments) = $call; + [$method, $arguments] = $call; $parameters = null; $resolvedArguments = []; @@ -107,7 +107,7 @@ protected function processValue($value, bool $isRoot = false) } } - list(, $arguments) = array_pop($calls); + [, $arguments] = array_pop($calls); if ($arguments !== $value->getArguments()) { $value->setArguments($arguments); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index ec82969d1bb4c..5267f6fbb9ba9 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1167,7 +1167,7 @@ private function doResolveServices($value, array &$inlineServices = [], bool $is return $this->resolveServices($reference); }; } elseif ($value instanceof IteratorArgument) { - $value = new RewindableGenerator(function () use ($value) { + $value = new RewindableGenerator(function () use ($value, &$inlineServices) { foreach ($value->getValues() as $k => $v) { foreach (self::getServiceConditionals($v) as $s) { if (!$this->has($s)) { @@ -1175,12 +1175,12 @@ private function doResolveServices($value, array &$inlineServices = [], bool $is } } foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { continue 2; } } - yield $k => $this->resolveServices($v); + yield $k => $this->doResolveServices($v, $inlineServices); } }, function () use ($value): int { $count = 0; @@ -1455,7 +1455,7 @@ public function removeBindings(string $id) { if ($this->hasDefinition($id)) { foreach ($this->getDefinition($id)->getBindings() as $key => $binding) { - list(, $bindingId) = $binding->getValues(); + [, $bindingId] = $binding->getValues(); $this->removedBindingIds[(int) $bindingId] = true; } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 93b303ea2bf20..7b0ea433033f6 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -185,25 +185,7 @@ public function dump(array $options = []) } } - (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); - $checkedNodes = []; - $this->circularReferences = []; - $this->singleUsePrivateIds = []; - foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { - if (!$node->getValue() instanceof Definition) { - continue; - } - if (!isset($checkedNodes[$id])) { - $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes); - } - if ($this->isSingleUsePrivateNode($node)) { - $this->singleUsePrivateIds[$id] = $id; - } - } - $this->container->getCompiler()->getServiceReferenceGraph()->clear(); - $checkedNodes = []; - $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences); - + $this->analyzeReferences(); $this->docStar = $options['debug'] ? '*' : ''; if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) { @@ -429,61 +411,65 @@ private function getProxyDumper(): ProxyDumper return $this->proxyDumper; } - /** - * @param ServiceReferenceGraphEdge[] $edges - */ - private function analyzeCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$currentPath = [], bool $byConstructor = true) + private function analyzeReferences() { - $checkedNodes[$sourceId] = true; - $currentPath[$sourceId] = $byConstructor; - - foreach ($edges as $edge) { - $node = $edge->getDestNode(); - $id = $node->getId(); - - if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { - // no-op - } elseif (isset($currentPath[$id])) { - $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); - } elseif (!isset($checkedNodes[$id])) { - $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor()); - } elseif (isset($this->circularReferences[$id])) { - $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); + (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); + $checkedNodes = []; + $this->circularReferences = []; + $this->singleUsePrivateIds = []; + foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { + if (!$node->getValue() instanceof Definition) { + continue; } - } - unset($currentPath[$sourceId]); - } - - private function connectCircularReferences(string $sourceId, array &$currentPath, bool $byConstructor, array &$subPath = []) - { - $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor; - foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) { - if (isset($currentPath[$id])) { - $this->addCircularReferences($id, $currentPath, $byConstructor); - } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) { - $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath); + if ($this->isSingleUsePrivateNode($node)) { + $this->singleUsePrivateIds[$id] = $id; } + + $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes); } - unset($currentPath[$sourceId], $subPath[$sourceId]); + + $this->container->getCompiler()->getServiceReferenceGraph()->clear(); + $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences); } - private function addCircularReferences(string $id, array $currentPath, bool $byConstructor) + private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array $path = [], bool $byConstructor = true): void { - $currentPath[$id] = $byConstructor; - $circularRefs = []; + $path[$sourceId] = $byConstructor; + $checkedNodes[$sourceId] = true; + foreach ($edges as $edge) { + $node = $edge->getDestNode(); + $id = $node->getId(); - foreach (array_reverse($currentPath) as $parentId => $v) { - $byConstructor = $byConstructor && $v; - $circularRefs[] = $parentId; + if (!($definition = $node->getValue()) instanceof Definition || $sourceId === $id || ($edge->isLazy() && ($this->proxyDumper ?? $this->getProxyDumper())->isProxyCandidate($definition)) || $edge->isWeak()) { + continue; + } - if ($parentId === $id) { - break; + if (isset($path[$id])) { + $loop = null; + $loopByConstructor = $edge->isReferencedByConstructor(); + foreach ($path as $k => $pathByConstructor) { + if (null !== $loop) { + $loop[] = $k; + $loopByConstructor = $loopByConstructor && $pathByConstructor; + } elseif ($k === $id) { + $loop = []; + } + } + $this->addCircularReferences($id, $loop, $loopByConstructor); + } elseif (!isset($checkedNodes[$id])) { + $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $path, $edge->isReferencedByConstructor()); } } + unset($path[$sourceId]); + } - $currentId = $id; - foreach ($circularRefs as $parentId) { + private function addCircularReferences(string $sourceId, array $currentPath, bool $byConstructor) + { + $currentId = $sourceId; + $currentPath = array_reverse($currentPath); + $currentPath[] = $currentId; + foreach ($currentPath as $parentId) { if (empty($this->circularReferences[$parentId][$currentId])) { $this->circularReferences[$parentId][$currentId] = $byConstructor; } @@ -597,7 +583,7 @@ private function addServiceInclude(string $cId, Definition $definition): string } } - foreach ($this->serviceCalls as $id => list($callCount, $behavior)) { + foreach ($this->serviceCalls as $id => [$callCount, $behavior]) { if ('service_container' !== $id && $id !== $cId && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior && $this->container->has($id) @@ -950,7 +936,7 @@ private function addInlineReference(string $id, Definition $definition, string $ $targetId = (string) $this->container->getAlias($targetId); } - list($callCount, $behavior) = $this->serviceCalls[$targetId]; + [$callCount, $behavior] = $this->serviceCalls[$targetId]; if ($id === $targetId) { return $this->addInlineService($id, $definition, $definition); @@ -1006,7 +992,7 @@ private function addInlineService(string $id, Definition $definition, Definition $code = ''; if ($isSimpleInstance = $isRootInstance = null === $inlineDef) { - foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) { + foreach ($this->serviceCalls as $targetId => [$callCount, $behavior, $byConstructor]) { if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) { $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor); } @@ -1076,7 +1062,7 @@ private function addServices(array &$services = null): string } foreach ($definitions as $id => $definition) { - if (!(list($file, $code) = $services[$id]) || null !== $file) { + if (!([$file, $code] = $services[$id]) || null !== $file) { continue; } if ($definition->isPublic()) { @@ -1094,7 +1080,7 @@ private function generateServiceFiles(array $services): iterable $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if ((list($file, $code) = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) { + if (([$file, $code] = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) { yield $file => [$code, $definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()]; } } @@ -1796,7 +1782,7 @@ private function dumpValue($value, bool $interpolate = true): string return sprintf('new \%s($this->getService, [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n " : '', $serviceTypes, $serviceTypes ? "\n " : ''); } } finally { - list($this->definitionVariables, $this->referenceVariables) = $scope; + [$this->definitionVariables, $this->referenceVariables] = $scope; } } elseif ($value instanceof Definition) { if ($value->hasErrors() && $e = $value->getErrors()) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index f21571faf6f5e..408ed3c40dc61 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -118,7 +118,7 @@ private function addService(Definition $definition, ?string $id, \DOMElement $pa $service->setAttribute('lazy', 'true'); } if (null !== $decoratedService = $definition->getDecoratedService()) { - list($decorated, $renamedId, $priority) = $decoratedService; + [$decorated, $renamedId, $priority] = $decoratedService; $service->setAttribute('decorates', $decorated); $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index fb9751f89bb10..61b4c5fa6ce7f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -138,7 +138,7 @@ private function addService(string $id, Definition $definition): string } if (null !== $decoratedService = $definition->getDecoratedService()) { - list($decorated, $renamedId, $priority) = $decoratedService; + [$decorated, $renamedId, $priority] = $decoratedService; $code .= sprintf(" decorates: %s\n", $decorated); if (null !== $renamedId) { $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 33b5a009f7b4c..e4620912cb874 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -430,7 +430,7 @@ private function processAnonymousServices(\DOMDocument $xml, string $file) // resolve definitions uksort($definitions, 'strnatcmp'); - foreach (array_reverse($definitions) as $id => list($domElement, $file)) { + foreach (array_reverse($definitions) as $id => [$domElement, $file]) { if (null !== $definition = $this->parseDefinition($domElement, $file, new Definition())) { $this->setDefinition($id, $definition); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php index 2504ff112cf86..c586e72c2acbc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php @@ -67,7 +67,7 @@ public function testAliasParametersShouldBeResolved() public function testBindingsShouldBeResolved() { - list($boundValue) = $this->container->getDefinition('foo')->getBindings()['$baz']->getValues(); + [$boundValue] = $this->container->getDefinition('foo')->getBindings()['$baz']->getValues(); $this->assertSame($this->container->getParameterBag()->resolveValue('%env(BAZ)%'), $boundValue); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 375187a9368fe..df6f06653edcb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1393,6 +1393,10 @@ public function testUninitializedReference() public function testAlmostCircular($visibility) { $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php'; + $container->compile(); + + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index b87a6b8a244f7..3b77b7ed6eb2d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -1054,6 +1054,9 @@ public function testAlmostCircular($visibility) $container = new $container(); + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); + $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php index a1f885399bd58..96c714493e8f3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php @@ -1,5 +1,6 @@ register('monolog.logger', 'stdClass')->setPublic(true) + ->setProperty('handler', new Reference('mailer.transport')); + +$container->register('mailer.transport', 'stdClass')->setPublic($public) + ->setFactory([new Reference('mailer.transport_factory'), 'create']); + +$container->register('mailer.transport_factory', FactoryCircular::class)->setPublic($public) + ->addArgument(new TaggedIteratorArgument('mailer.transport')); + +$container->register('mailer.transport_factory.amazon', 'stdClass')->setPublic($public) + ->addArgument(new Reference('monolog.logger_2')) + ->addTag('mailer.transport'); + +$container->register('monolog.logger_2', 'stdClass')->setPublic($public) + ->setProperty('handler', new Reference('mailer.transport')); + // same visibility for deps $container->register('foo', FooCircular::class)->setPublic(true) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index fee80ac779749..b22e8bcffc744 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -111,6 +111,23 @@ public function __construct($lazyValues, $lazyEmptyValues) } } +class FactoryCircular +{ + public $services; + + public function __construct($services) + { + $this->services = $services; + } + + public function create() + { + foreach ($this->services as $service) { + return $service; + } + } +} + class FoobarCircular { public function __construct(FooCircular $foo) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php index 60c60b3adfb45..8bc0146fb13f7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php @@ -36,6 +36,7 @@ public function __construct() 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -77,7 +78,11 @@ public function getRemovedIds(): array 'level5' => true, 'level6' => true, 'logger2' => true, + 'mailer.transport' => true, + 'mailer.transport_factory' => true, + 'mailer.transport_factory.amazon' => true, 'manager4' => true, + 'monolog.logger_2' => true, 'multiuse1' => true, 'subscriber2' => true, ]; @@ -352,6 +357,20 @@ protected function getManager3Service($lazyLoad = true) return $this->services['manager3'] = new \stdClass($b); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. * @@ -416,6 +435,34 @@ protected function getLevel5Service() return $instance; } + /** + * Gets the private 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + return $this->privates['mailer.transport'] = (new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->privates['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)))->create(); + } + + /** + * Gets the private 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = new \stdClass(); + + $this->privates['mailer.transport_factory.amazon'] = $instance = new \stdClass($a); + + $a->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the private 'manager4' shared service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php index 4905ade2dd408..4540459203d00 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php @@ -42,9 +42,14 @@ public function __construct() 'listener3' => 'getListener3Service', 'listener4' => 'getListener4Service', 'logger' => 'getLoggerService', + 'mailer.transport' => 'getMailer_TransportService', + 'mailer.transport_factory' => 'getMailer_TransportFactoryService', + 'mailer.transport_factory.amazon' => 'getMailer_TransportFactory_AmazonService', 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', + 'monolog.logger_2' => 'getMonolog_Logger2Service', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -434,6 +439,50 @@ protected function getLoggerService() return $instance; } + /** + * Gets the public 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + $a = ($this->services['mailer.transport_factory'] ?? $this->getMailer_TransportFactoryService()); + + if (isset($this->services['mailer.transport'])) { + return $this->services['mailer.transport']; + } + + return $this->services['mailer.transport'] = $a->create(); + } + + /** + * Gets the public 'mailer.transport_factory' shared service. + * + * @return \FactoryCircular + */ + protected function getMailer_TransportFactoryService() + { + return $this->services['mailer.transport_factory'] = new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->services['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)); + } + + /** + * Gets the public 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = ($this->services['monolog.logger_2'] ?? $this->getMonolog_Logger2Service()); + + if (isset($this->services['mailer.transport_factory.amazon'])) { + return $this->services['mailer.transport_factory.amazon']; + } + + return $this->services['mailer.transport_factory.amazon'] = new \stdClass($a); + } + /** * Gets the public 'manager' shared service. * @@ -482,6 +531,34 @@ protected function getManager3Service($lazyLoad = true) return $this->services['manager3'] = new \stdClass($a); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + + /** + * Gets the public 'monolog.logger_2' shared service. + * + * @return \stdClass + */ + protected function getMonolog_Logger2Service() + { + $this->services['monolog.logger_2'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. * diff --git a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php index 747db80d805e1..2c216cbe7f850 100644 --- a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php +++ b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php @@ -493,7 +493,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array $hasCall = $refl->hasMethod('__call'); $hasStaticCall = $refl->hasMethod('__callStatic'); foreach (self::$method[$use] as $method) { - list($interface, $name, $static, $description) = $method; + [$interface, $name, $static, $description] = $method; if ($static ? $hasStaticCall : $hasCall) { continue; } @@ -555,12 +555,12 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array } if ($parent && isset(self::$finalMethods[$parent][$method->name])) { - list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; + [$declaringClass, $message] = self::$finalMethods[$parent][$method->name]; $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); } if (isset(self::$internalMethods[$class][$method->name])) { - list($declaringClass, $message) = self::$internalMethods[$class][$method->name]; + [$declaringClass, $message] = self::$internalMethods[$class][$method->name]; if (strncmp($ns, $declaringClass, $len)) { $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); } @@ -600,7 +600,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array } if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) { - list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; + [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; if ('void' === $normalizedType) { $canAddReturnType = false; @@ -668,7 +668,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array $definedParameters[$parameter->name] = true; } } - foreach ($matches as list(, $parameterType, $parameterName)) { + foreach ($matches as [, $parameterType, $parameterName]) { if (!isset($definedParameters[$parameterName])) { $parameterType = trim($parameterType); self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className); @@ -939,10 +939,10 @@ private function patchMethod(\ReflectionMethod $method, string $returnType, stri continue; } - list($namespace, $useOffset, $useMap) = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); + [$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); if ('\\' !== $type[0]) { - list($declaringNamespace, , $declaringUseMap) = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); + [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); $p = strpos($type, '\\', 1); $alias = $p ? substr($type, 0, $p) : $type; diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 11dce4897bc65..87d538eaf8f04 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -177,7 +177,7 @@ public function getCalledListeners(Request $request = null) $hash = $request ? spl_object_hash($request) : null; $called = []; foreach ($this->callStack as $listener) { - list($eventName, $requestHash) = $this->callStack->getInfo(); + [$eventName, $requestHash] = $this->callStack->getInfo(); if (null === $hash || $hash === $requestHash) { $called[] = $listener->getInfo($eventName); } @@ -207,7 +207,7 @@ public function getNotCalledListeners(Request $request = null) if (null !== $this->callStack) { foreach ($this->callStack as $calledListener) { - list(, $requestHash) = $this->callStack->getInfo(); + [, $requestHash] = $this->callStack->getInfo(); if (null === $hash || $hash === $requestHash) { $calledListeners[] = $calledListener->getWrappedListener(); diff --git a/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php index ea9fe8c1b6cdc..173f4273eb2f4 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php @@ -19,10 +19,9 @@ class EventDispatcherTest extends TestCase { /* Some pseudo events */ - const preFoo = 'pre.foo'; - const postFoo = 'post.foo'; - const preBar = 'pre.bar'; - const postBar = 'post.bar'; + private const preFoo = 'pre.foo'; + private const postFoo = 'post.foo'; + private const preBar = 'pre.bar'; /** * @var EventDispatcher diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index 5a3fb0a0efc17..6e3cc488b1ee3 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -60,7 +60,7 @@ public function tokenize(string $expression) throw new SyntaxError(sprintf('Unexpected "%s".', $expression[$cursor]), $cursor, $expression); } - list($expect, $cur) = array_pop($brackets); + [$expect, $cur] = array_pop($brackets); if ($expression[$cursor] != strtr($expect, '([{', ')]}')) { throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); } @@ -92,7 +92,7 @@ public function tokenize(string $expression) $tokens[] = new Token(Token::EOF_TYPE, null, $cursor + 1); if (!empty($brackets)) { - list($expect, $cur) = array_pop($brackets); + [$expect, $cur] = array_pop($brackets); throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); } diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index aaf62d02674f8..d9609f5484c2d 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -454,8 +454,8 @@ public function makePathRelative(string $endPath, string $startPath) return $result; }; - list($endPath, $endDriveLetter) = $splitDriveLetter($endPath); - list($startPath, $startDriveLetter) = $splitDriveLetter($startPath); + [$endPath, $endDriveLetter] = $splitDriveLetter($endPath); + [$startPath, $startDriveLetter] = $splitDriveLetter($startPath); $startPathArr = $splitPath($startPath); $endPathArr = $splitPath($endPath); @@ -590,7 +590,7 @@ public function isAbsolutePath(string $file) public function tempnam(string $dir, string $prefix/*, string $suffix = ''*/) { $suffix = \func_num_args() > 2 ? func_get_arg(2) : ''; - list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir); + [$scheme, $hierarchy] = $this->getSchemeAndHierarchy($dir); // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) { diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php index 5a47812bd3474..add8e7df596be 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php @@ -35,9 +35,10 @@ public function testAccept($mode, $expected) case SortableIterator::SORT_BY_ACCESSED_TIME: touch(self::toAbsolute('.git')); sleep(1); - file_get_contents(self::toAbsolute('.bar')); + touch(self::toAbsolute('.bar'), time()); break; case SortableIterator::SORT_BY_CHANGED_TIME: + sleep(1); file_put_contents(self::toAbsolute('test.php'), 'foo'); sleep(1); file_put_contents(self::toAbsolute('test.py'), 'foo'); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index 09c5d69a2e02e..be8af57828e05 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -151,7 +151,7 @@ private function getFileUploadError(int $errorCode) $messageParameters = []; if (\UPLOAD_ERR_INI_SIZE === $errorCode) { - list($limitAsString, $suffix) = $this->factorizeSizes(0, self::getMaxFilesize()); + [$limitAsString, $suffix] = $this->factorizeSizes(0, self::getMaxFilesize()); $messageTemplate = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; $messageParameters = [ '{{ limit }}' => $limitAsString, diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index 53fbcb51963c2..8c92046ee3590 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -228,7 +228,7 @@ public function getIterator() */ private function resolveChild(string $name): FormBuilderInterface { - list($type, $options) = $this->unresolvedChildren[$name]; + [$type, $options] = $this->unresolvedChildren[$name]; unset($this->unresolvedChildren[$name]); diff --git a/src/Symfony/Component/Form/Resources/translations/validators.af.xlf b/src/Symfony/Component/Form/Resources/translations/validators.af.xlf new file mode 100644 index 0000000000000..58cd939cf793f --- /dev/null +++ b/src/Symfony/Component/Form/Resources/translations/validators.af.xlf @@ -0,0 +1,139 @@ + + + + + + This form should not contain extra fields. + Hierdie vorm moet nie ekstra velde bevat nie. + + + The uploaded file was too large. Please try to upload a smaller file. + Die opgelaaide lêer was te groot. Probeer asseblief 'n kleiner lêer. + + + The CSRF token is invalid. Please try to resubmit the form. + Die CSRF-teken is ongeldig. Probeer asseblief om die vorm weer in te dien. + + + This value is not a valid HTML5 color. + Hierdie waarde is nie 'n geldige HTML5 kleur nie. + + + Please enter a valid birthdate. + Voer asseblief 'n geldige geboortedatum in. + + + The selected choice is invalid. + Die gekiesde opsie is nie geldig nie. + + + The collection is invalid. + Die versameling is nie geldig nie. + + + Please select a valid color. + Kies asseblief 'n geldige kleur. + + + Please select a valid country. + Kies asseblief 'n geldige land. + + + Please select a valid currency. + Kies asseblief 'n geldige geldeenheid. + + + Please choose a valid date interval. + Kies asseblief 'n geldige datum interval. + + + Please enter a valid date and time. + Voer asseblilef 'n geldige datum en tyd in. + + + Please enter a valid date. + Voer asseblief 'n geldige datum in. + + + Please select a valid file. + Kies asseblief 'n geldige lêer. + + + The hidden field is invalid. + Die versteekte veld is nie geldig nie. + + + Please enter an integer. + Voer asseblief 'n geldige heeltal in. + + + Please select a valid language. + Kies assblief 'n geldige taal. + + + Please select a valid locale. + Voer assebliefn 'n geldige locale in. + + + Please enter a valid money amount. + Voer asseblief 'n geldige bedrag in. + + + Please enter a number. + Voer asseblief 'n nommer in. + + + The password is invalid. + Die wagwoord is ongeldig. + + + Please enter a percentage value. + Voer asseblief 'n geldige persentasie waarde in. + + + The values do not match. + Die waardes is nie dieselfde nie. + + + Please enter a valid time. + Voer asseblief 'n geldige tyd in time. + + + Please select a valid timezone. + Kies asseblief 'n geldige tydsone. + + + Please enter a valid URL. + Voer asseblief 'n geldige URL in. + + + Please enter a valid search term. + Voer asseblief 'n geldige soek term in. + + + Please provide a valid phone number. + Verskaf asseblief 'n geldige telefoonnommer. + + + The checkbox has an invalid value. + Die blokkie het 'n ongeldige waarde. + + + Please enter a valid email address. + Voer asseblief 'n geldige e-pos adres in. + + + Please select a valid option. + Kies asseblief 'n geldige opsie. + + + Please select a valid range. + Kies asseblief 'n geldige reeks. + + + Please enter a valid week. + Voer assblief 'n geldige week in. + + + + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.az.xlf b/src/Symfony/Component/Form/Resources/translations/validators.az.xlf index 69e447385acda..b9269706db3e8 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.az.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.az.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF nişanı yanlışdır. Lütfen formanı yenidən göndərin. + + This value is not a valid HTML5 color. + Bu dəyər doğru bir HTML5 rəngi deyil. + + + Please enter a valid birthdate. + Zəhmət olmasa doğru bir doğum günü daxil edin. + + + The selected choice is invalid. + Seçilmiş seçim doğru deyil. + + + The collection is invalid. + Kolleksiya doğru deyil. + + + Please select a valid color. + Zəhmət olmasa doğru bir rəng seçin. + + + Please select a valid country. + Zəhmət olmasa doğru bir ölkə seçin. + + + Please select a valid currency. + Zəhmət olmasa doğru bir valyuta seçin. + + + Please choose a valid date interval. + Zəhmət olmasa doğru bir tarix aralığı seçin. + + + Please enter a valid date and time. + Zəhmət olmasa doğru bir tarix ve saat daxil edin. + + + Please enter a valid date. + Zəhmət olmasa doğru bir tarix daxil edin. + + + Please select a valid file. + Zəhmət olmasa doğru bir fayl seçin. + + + The hidden field is invalid. + Gizli sahə doğru deyil. + + + Please enter an integer. + Zəhmət olmasa bir tam ədəd daxil edin. + + + Please select a valid language. + Zəhmət olmasa doğru bir dil seçin. + + + Please select a valid locale. + Zəhmət olmasa doğru bir yer seçin. + + + Please enter a valid money amount. + Zəhmət olmasa doğru bir pul miqdarı daxil edin. + + + Please enter a number. + Zəhmət olmasa doğru bir rəqəm daxil edin. + + + The password is invalid. + Parol doğru deyil. + + + Please enter a percentage value. + Zəhmət olmasa doğru bir faiz dəyəri daxil edin. + + + The values do not match. + Dəyərlər örtüşmür. + + + Please enter a valid time. + Zəhmət olmasa doğru bir saat daxil edin. + + + Please select a valid timezone. + Zəhmət olmasa doğru bir saat qurşağı seçin. + + + Please enter a valid URL. + Zəhmət olmasa doğru bir URL daxil edin. + + + Please enter a valid search term. + Zəhmət olmasa doğru bir axtarış termini daxil edin. + + + Please provide a valid phone number. + Zəhmət olmasa doğru bir telefon nömrəsi seçin. + + + The checkbox has an invalid value. + Seçim qutusunda doğru olmayan dəyər var. + + + Please enter a valid email address. + Zəhmət olmasa doğru bir e-poçt seçin. + + + Please select a valid option. + Zəhmət olmasa doğru bir variant seçin. + + + Please select a valid range. + Zəhmət olmasa doğru bir aralıq seçin. + + + Please enter a valid week. + Zəhmət olmasa doğru bir həftə seçin. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.bs.xlf b/src/Symfony/Component/Form/Resources/translations/validators.bs.xlf index cfe681e3b0534..259b05f842995 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.bs.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.bs.xlf @@ -114,6 +114,26 @@ Please provide a valid phone number. Molim navedite ispravan broj telefona. + + The checkbox has an invalid value. + Polje za potvrdu sadrži neispravnu vrijednost. + + + Please enter a valid email address. + Molim upišite ispravnu email adresu. + + + Please select a valid option. + Molim izaberite ispravnu opciju. + + + Please select a valid range. + Molim izaberite ispravan opseg. + + + Please enter a valid week. + Molim upišite ispravnu sedmicu. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf index 3a2fa484f8496..69379608048c9 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. + + This value is not a valid HTML5 color. + Aquest valor no és un color HTML5 valid. + + + Please enter a valid birthdate. + Per favor introdueix una data d'aniversari valida. + + + The selected choice is invalid. + L'opció escollida és invalida. + + + The collection is invalid. + La col·lecció és invalida. + + + Please select a valid color. + Per favor selecciona un color vàlid. + + + Please select a valid country. + Per favor selecciona una ciutat vàlida. + + + Please select a valid currency. + Per favor selecciona una moneda vàlida. + + + Please choose a valid date interval. + Per favor escull un interval de dates vàlides. + + + Please enter a valid date and time. + Per favor introdueix una data i temps vàlid. + + + Please enter a valid date. + Per favor introdueix una data vàlida. + + + Please select a valid file. + Per favor selecciona un arxiu vàlid. + + + The hidden field is invalid. + El camp ocult és invàlid. + + + Please enter an integer. + Per favor introdueix un enter. + + + Please select a valid language. + Per favor selecciona un idioma vàlid. + + + Please select a valid locale. + Per favor seleccioneu una configuració regional vàlida + + + Please enter a valid money amount. + Per favor introdueix una quantitat de diners vàlids. + + + Please enter a number. + Per favor introdueix un número. + + + The password is invalid. + La contrasenya es invàlida. + + + Please enter a percentage value. + Per favor introdueix un valor percentual. + + + The values do not match. + Els valors no coincideixen. + + + Please enter a valid time. + Per favor introdueix un temps vàlid. + + + Please select a valid timezone. + Per favor selecciona una zona horària vàlida. + + + Please enter a valid URL. + Per favor introdueix una URL vàlida. + + + Please enter a valid search term. + Per favor introdueix un concepte de cerca vàlid. + + + Please provide a valid phone number. + Per favor introdueix un número de telèfon vàlid. + + + The checkbox has an invalid value. + La casella de selecció te un valor invàlid. + + + Please enter a valid email address. + Per favor introdueix un correu electrònic vàlid. + + + Please select a valid option. + Per favor selecciona una opció vàlida. + + + Please select a valid range. + Per favor selecciona un rang vàlid. + + + Please enter a valid week. + Per favor introdueix una setmana vàlida. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf index f52f4e0a30db9..dafe20fa02c32 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf @@ -12,7 +12,127 @@ The CSRF token is invalid. Please try to resubmit the form. - CSRF-token er ugyldig. + CSRF-token er ugyldig. Prøv venligst at genindsende. + + + This value is not a valid HTML5 color. + Værdien er ikke en gyldig HTML5 farve. + + + Please enter a valid birthdate. + Indtast venligst en gyldig fødselsdato. + + + The selected choice is invalid. + Den valgte mulighed er ugyldig . + + + The collection is invalid. + Samlingen er ugyldig. + + + Please select a valid color. + Vælg venligst en gyldig farve. + + + Please select a valid country. + Vælg venligst et gyldigt land. + + + Please select a valid currency. + Vælg venligst en gyldig valuta. + + + Please choose a valid date interval. + Vælg venligst et gyldigt datointerval. + + + Please enter a valid date and time. + Vælg venligst en gyldig dato og tid. + + + Please enter a valid date. + Vælg venligst en gyldig dato. + + + Please select a valid file. + Vælg venligst en gyldig fil. + + + The hidden field is invalid. + Det skjulte felt er ugyldigt. + + + Please enter an integer. + Indsæt veligst et heltal. + + + Please select a valid language. + Vælg venligst et gyldigt sprog. + + + Please select a valid locale. + Vælg venligst en gyldigt sprogkode. + + + Please enter a valid money amount. + Vælg venligst et gyldigt beløb. + + + Please enter a number. + Indtast venligst et nummer. + + + The password is invalid. + Passwordet er ugyldigt. + + + Please enter a percentage value. + Indtast venligst en procentværdi. + + + The values do not match. + Værdierne er ikke ens. + + + Please enter a valid time. + Indtast venligst en gyldig tid. + + + Please select a valid timezone. + Vælg venligst en gyldig tidszone. + + + Please enter a valid URL. + Indtast venligst en gyldig URL. + + + Please enter a valid search term. + Indtast venligst et gyldigt søgeord. + + + Please provide a valid phone number. + Giv venligst et gyldigt telefonnummer. + + + The checkbox has an invalid value. + Checkboxen har en ugyldigt værdi. + + + Please enter a valid email address. + Indtast venligst en gyldig emailaddresse. + + + Please select a valid option. + Vælg venligst en gyldig mulighed. + + + Please select a valid range. + Vælg venligst et gyldigt interval . + + + Please enter a valid week. + Indtast venligst en gyldig uge. diff --git a/src/Symfony/Component/Form/Resources/translations/validators.el.xlf b/src/Symfony/Component/Form/Resources/translations/validators.el.xlf index ba2ced74b0111..595630e76f453 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.el.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά. + + This value is not a valid HTML5 color. + Αυτή η τιμή δέν έναι έγκυρο χρώμα HTML5. + + + Please enter a valid birthdate. + Παρακαλόυμε ειχάγεται μία έγκυρη ημερομηνία γέννησης. + + + The selected choice is invalid. + Η επιλεγμένη επιλογή δέν είναι έγκυρη. + + + The collection is invalid. + Η συλλογή δέν είναι έγκυρη. + + + Please select a valid color. + Παρακαλούμε επιλέξτε ένα έγκυρο χρώμα. + + + Please select a valid country. + Παρακαλούμε επιλέξτε μία έγκυρη χώρα. + + + Please select a valid currency. + Παρακαλούμε επιλέξτε ένα έγυρο νόμισμα. + + + Please choose a valid date interval. + Παρακαλούμε επιλέξτε ένα έγκυρο διάστημα ημερομηνίας. + + + Please enter a valid date and time. + Παρακαλούμε εισαγάγετε μια έγκυρη ημερομηνία και ώρα. + + + Please enter a valid date. + Παρακαλούμε εισάγετε μία έγκυρη ημερομηνία. + + + Please select a valid file. + Παρακαλούμε επιλέξτε ένα έγκυρο αρχείο. + + + The hidden field is invalid. + Το κρυφό πεδίο δέν είναι έγκυρο. + + + Please enter an integer. + Παρακαλούμε εισάγετε έναν ακέραιο αριθμό. + + + Please select a valid language. + Παρακαλούμε επιλέξτε μία έγκυρη γλώσσα. + + + Please select a valid locale. + Παρακαλούμε επιλέξτε μία έγκυρη τοπικοποίηση. + + + Please enter a valid money amount. + Παρακαλούμε εισάγετε ένα έγκυρο χρηματικό ποσό. + + + Please enter a number. + Παρακαλούμε εισάγετε έναν αριθμό. + + + The password is invalid. + Ο κωδικός δέν είναι έγκυρος. + + + Please enter a percentage value. + Παρακαλούμε εισάγετε μία ποσοστιαία τιμή. + + + The values do not match. + Οι τιμές δέν ταιριάζουν. + + + Please enter a valid time. + Παρακαλούμε εισάγετε μία έγκυρη ώρα. + + + Please select a valid timezone. + Παρακαλούμε επιλέξτε μία έγυρη ζώνη ώρας. + + + Please enter a valid URL. + Παρακαλούμε εισάγετε μια έγκυρη διεύθυνση URL. + + + Please enter a valid search term. + Παρακαλούμε εισάγετε έναν έγκυρο όρο αναζήτησης. + + + Please provide a valid phone number. + Παρακαλούμε καταχωρίστε έναν έγκυρο αριθμό τηλεφώνου. + + + The checkbox has an invalid value. + Το πλαίσιο ελέγχου έχει μή έγκυρη τιμή. + + + Please enter a valid email address. + Παρακαλούμε εισάγετε μία έγκυρη ηλεκτρονική διεύθυνση. + + + Please select a valid option. + Παρακαλούμε επιλέξτε μία έγκυρη επιλογή. + + + Please select a valid range. + Παρακαλούμε επιλέξτε ένα έγυρο εύρος. + + + Please enter a valid week. + Παρακαλούμε εισάγετε μία έγκυρη εβδομάδα. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf b/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf index 4eb393aee90b1..7ad87b5468261 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf @@ -3,8 +3,8 @@ - This field group should not contain extra fields. - Tämä kenttäryhmä ei voi sisältää ylimääräisiä kenttiä. + This form should not contain extra fields. + Tämä lomake ei voi sisältää ylimääräisiä kenttiä. The uploaded file was too large. Please try to upload a smaller file. @@ -12,7 +12,127 @@ The CSRF token is invalid. Please try to resubmit the form. - CSRF tarkiste on virheellinen. Ole hyvä ja yritä lähettää lomake uudestaan. + CSRF-tarkiste on virheellinen. Ole hyvä ja yritä lähettää lomake uudestaan. + + + This value is not a valid HTML5 color. + Tämä arvo ei ole kelvollinen HTML5-väri. + + + Please enter a valid birthdate. + Syötä kelvollinen syntymäaika. + + + The selected choice is invalid. + Valittu vaihtoehto ei kelpaa. + + + The collection is invalid. + Ryhmä ei kelpaa. + + + Please select a valid color. + Valitse kelvollinen väri. + + + Please select a valid country. + Valitse kelvollinen maa. + + + Please select a valid currency. + Valitse kelvollinen valuutta. + + + Please choose a valid date interval. + Valitse kelvollinen aikaväli. + + + Please enter a valid date and time. + Syötä kelvolliset päivä ja aika. + + + Please enter a valid date. + Syötä kelvollinen päivä. + + + Please select a valid file. + Valitse kelvollinen tiedosto. + + + The hidden field is invalid. + Piilotettu kenttä ei ole kelvollinen. + + + Please enter an integer. + Syötä kokonaisluku. + + + Please select a valid language. + Valitse kelvollinen kieli. + + + Please select a valid locale. + Valitse kelvollinen kielikoodi. + + + Please enter a valid money amount. + Syötä kelvollinen rahasumma. + + + Please enter a number. + Syötä numero. + + + The password is invalid. + Salasana ei kelpaa. + + + Please enter a percentage value. + Syötä prosenttiluku. + + + The values do not match. + Arvot eivät vastaa toisiaan. + + + Please enter a valid time. + Syötä kelvollinen kellonaika. + + + Please select a valid timezone. + Valitse kelvollinen aikavyöhyke. + + + Please enter a valid URL. + Syötä kelvollinen URL. + + + Please enter a valid search term. + Syötä kelvollinen hakusana. + + + Please provide a valid phone number. + Anna kelvollinen puhelinnumero. + + + The checkbox has an invalid value. + Valintaruudun arvo ei kelpaa. + + + Please enter a valid email address. + Syötä kelvollinen sähköpostiosoite. + + + Please select a valid option. + Valitse kelvollinen vaihtoehto. + + + Please select a valid range. + Valitse kelvollinen väli. + + + Please enter a valid week. + Syötä kelvollinen viikko. diff --git a/src/Symfony/Component/Form/Resources/translations/validators.gl.xlf b/src/Symfony/Component/Form/Resources/translations/validators.gl.xlf index 88cc6536ead7f..5ef404a481a45 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.gl.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.gl.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. O token CSRF non é válido. Por favor, probe a enviar novamente o formulario. + + This value is not a valid HTML5 color. + Este valor non é unha cor HTML5 válida. + + + Please enter a valid birthdate. + Insire unha data de aniversario válida. + + + The selected choice is invalid. + A opción seleccionada non é válida. + + + The collection is invalid. + A colección non é válida. + + + Please select a valid color. + Por favor, seleccione unha cor válida. + + + Please select a valid country. + Por favor, seleccione un país válido. + + + Please select a valid currency. + Por favor, seleccione unha moeda válida. + + + Please choose a valid date interval. + Por favor, escolla un intervalo de datas válido. + + + Please enter a valid date and time. + Por favor, introduza unha data e hora válidas. + + + Please enter a valid date. + Por favor, introduce unha data válida. + + + Please select a valid file. + Por favor, seleccione un ficheiro válido. + + + The hidden field is invalid. + O campo oculto non é válido. + + + Please enter an integer. + Por favor, introduza un número enteiro. + + + Please select a valid language. + Por favor, selecciona un idioma válido. + + + Please select a valid locale. + Por favor, seleccione unha configuración rexional válida. + + + Please enter a valid money amount. + Por favor, introduza unha cantidade de diñeiro válida. + + + Please enter a number. + Por favor, introduza un número. + + + The password is invalid. + O contrasinal non é válido. + + + Please enter a percentage value. + Por favor, introduza un valor porcentual. + + + The values do not match. + Os valores non coinciden. + + + Please enter a valid time. + Por favor, introduza unha hora válida. + + + Please select a valid timezone. + Por favor, selecciona unha zona horaria válida. + + + Please enter a valid URL. + Por favor, introduce un URL válido. + + + Please enter a valid search term. + Por favor, introduce un termo de busca válido. + + + Please provide a valid phone number. + Por favor, fornecer un número de teléfono válido. + + + The checkbox has an invalid value. + A caixa de verificación ten un valor non válido. + + + Please enter a valid email address. + Por favor, introduce un enderezo de correo electrónico válido. + + + Please select a valid option. + Por favor, seleccione unha opción válida. + + + Please select a valid range. + Por favor, seleccione un intervalo válido. + + + Please enter a valid week. + Por favor, introduce unha semana válida. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.he.xlf b/src/Symfony/Component/Form/Resources/translations/validators.he.xlf index 74a71d05a31a8..efd68b8807bfd 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.he.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.he.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. אסימון CSRF אינו חוקי. אנא נסה לשלוח שוב את הטופס. + + This value is not a valid HTML5 color. + ערך זה אינו צבע HTML5 חוקי. + + + Please enter a valid birthdate. + נא להזין את תאריך לידה תקני. + + + The selected choice is invalid. + הבחירה שנבחרה אינה חוקית. + + + The collection is invalid. + האוסף אינו חוקי. + + + Please select a valid color. + אנא בחר צבע חוקי. + + + Please select a valid country. + אנא בחר מדינה חוקית. + + + Please select a valid currency. + אנא בחר מטבע חוקי. + + + Please choose a valid date interval. + אנא בחר מרווח תאריכים חוקי. + + + Please enter a valid date and time. + אנא הזן תאריך ושעה תקנים. + + + Please enter a valid date. + נא להזין תאריך חוקי. + + + Please select a valid file. + אנא בחר קובץ חוקי. + + + The hidden field is invalid. + השדה הנסתר אינו חוקי. + + + Please enter an integer. + אנא הזן מספר שלם. + + + Please select a valid language. + אנא בחר שפה חוקי. + + + Please select a valid locale. + אנא בחר שפה מקומית. + + + Please enter a valid money amount. + אנא הזן סכום כסף חוקי. + + + Please enter a number. + אנא הזן מספר. + + + The password is invalid. + הסיסמה אינה חוקית. + + + Please enter a percentage value. + אנא הזן ערך באחוזים. + + + The values do not match. + הערכים אינם תואמים. + + + Please enter a valid time. + אנא הזן שעה חוקי. + + + Please select a valid timezone. + אנא בחר אזור זמן חוקי. + + + Please enter a valid URL. + נא להזין את כתובת אתר חוקית. + + + Please enter a valid search term. + אנא הזן מונח חיפוש חוקי. + + + Please provide a valid phone number. + אנא ספק מספר טלפון חוקי. + + + The checkbox has an invalid value. + לתיבת הסימון יש ערך לא חוקי. + + + Please enter a valid email address. + אנא הזן כתובת דוא"ל תקנית. + + + Please select a valid option. + אנא בחר אפשרות חוקית. + + + Please select a valid range. + אנא בחר טווח חוקי. + + + Please enter a valid week. + אנא הזן שבוע תקף. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Form/Resources/translations/validators.hu.xlf index bc7f6055e4845..3b70461d394b7 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.hu.xlf @@ -18,6 +18,122 @@ This value is not a valid HTML5 color. Ez az érték nem egy érvényes HTML5 szín. + + Please enter a valid birthdate. + Kérjük, adjon meg egy valós születési dátumot. + + + The selected choice is invalid. + A kiválasztott opció érvénytelen. + + + The collection is invalid. + A gyűjtemény érvénytelen. + + + Please select a valid color. + Kérjük, válasszon egy érvényes színt. + + + Please select a valid country. + Kérjük, válasszon egy érvényes országot. + + + Please select a valid currency. + Kérjük, válasszon egy érvényes pénznemet. + + + Please choose a valid date interval. + Kérjük, válasszon egy érvényes dátumintervallumot. + + + Please enter a valid date and time. + Kérjük, adjon meg egy érvényes dátumot és időpontot. + + + Please enter a valid date. + Kérjük, adjon meg egy érvényes dátumot. + + + Please select a valid file. + Kérjük, válasszon egy érvényes fájlt. + + + The hidden field is invalid. + A rejtett mező érvénytelen. + + + Please enter an integer. + Kérjük, adjon meg egy egész számot. + + + Please select a valid language. + Kérjük, válasszon egy érvényes nyelvet. + + + Please select a valid locale. + Kérjük, válasszon egy érvényes területi beállítást. + + + Please enter a valid money amount. + Kérjük, adjon meg egy érvényes pénzösszeget. + + + Please enter a number. + Kérjük, adjon meg egy számot. + + + The password is invalid. + A jelszó érvénytelen. + + + Please enter a percentage value. + Kérjük, adjon meg egy százalékos értéket. + + + The values do not match. + Az értékek nem egyeznek. + + + Please enter a valid time. + Kérjük, adjon meg egy érvényes időpontot. + + + Please select a valid timezone. + Kérjük, válasszon érvényes időzónát. + + + Please enter a valid URL. + Kérjük, adjon meg egy érvényes URL-t. + + + Please enter a valid search term. + Kérjük, adjon meg egy érvényes keresési kifejezést. + + + Please provide a valid phone number. + Kérjük, adjon egy érvényes telefonszámot + + + The checkbox has an invalid value. + A jelölőnégyzet értéke érvénytelen. + + + Please enter a valid email address. + Kérjük valós e-mail címet adjon meg. + + + Please select a valid option. + Kérjük, válasszon egy érvényes beállítást. + + + Please select a valid range. + Kérjük, válasszon egy érvényes tartományt. + + + Please enter a valid week. + Kérjük, adjon meg egy érvényes hetet. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.lt.xlf b/src/Symfony/Component/Form/Resources/translations/validators.lt.xlf index e9eebc7389739..5613c42b5bf16 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.lt.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.lt.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą. + + This value is not a valid HTML5 color. + Ši reikšmė nėra HTML5 spalva. + + + Please enter a valid birthdate. + Prašome įvesti tinkamą gimimo datą. + + + The selected choice is invalid. + Pasirinktas pasirinkimas yra neteisingas. + + + The collection is invalid. + Neteisingas sąrašas. + + + Please select a valid color. + Prašome pasirinkti tinkamą spalvą. + + + Please select a valid country. + Prašome pasirinkti tinkamą šalį. + + + Please select a valid currency. + Prašome pasirinkti tinkamą valiutą. + + + Please choose a valid date interval. + Prašome pasirinkti tinkamą datos intervalą. + + + Please enter a valid date and time. + Prašome įvesti tinkamą datą ir laiką. + + + Please enter a valid date. + Prašome įvesti tinkamą datą. + + + Please select a valid file. + Prašome pasirinkti tinkamą bylą. + + + The hidden field is invalid. + Klaidingas paslėptasis laukas. + + + Please enter an integer. + Prašome įvesti sveiką skaičių. + + + Please select a valid language. + Prašome pasirinkti tinkamą kalbą. + + + Please select a valid locale. + Prašome pasirinkti tinkamą lokalę. + + + Please enter a valid money amount. + Prašome įvesti tinkamą pinigų sumą. + + + Please enter a number. + Prašome įvesti numerį. + + + The password is invalid. + Klaidingas slaptažodis. + + + Please enter a percentage value. + Prašome įvesti procentinę reikšmę. + + + The values do not match. + Reikšmės nesutampa. + + + Please enter a valid time. + Prašome įvesti tinkamą laiką. + + + Please select a valid timezone. + Prašome pasirinkti tinkamą laiko zoną. + + + Please enter a valid URL. + Prašome įvesti tinkamą URL. + + + Please enter a valid search term. + Prašome įvesti tinkamą paieškos terminą. + + + Please provide a valid phone number. + Prašome pateikti tinkamą telefono numerį. + + + The checkbox has an invalid value. + Klaidinga žymimajo langelio reikšmė. + + + Please enter a valid email address. + Prašome įvesti tinkamą el. pašto adresą. + + + Please select a valid option. + Prašome pasirinkti tinkamą parinktį. + + + Please select a valid range. + Prašome pasirinkti tinkamą diapozoną. + + + Please enter a valid week. + Prašome įvesti tinkamą savaitę. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.mn.xlf b/src/Symfony/Component/Form/Resources/translations/validators.mn.xlf index 171df74d63c0c..620112d8814a9 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.mn.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.mn.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF token буруу байна. Формоо дахин илгээнэ үү. + + This value is not a valid HTML5 color. + Энэ утга зөв HTML5 өнгө биш байна. + + + Please enter a valid birthdate. + Зөв төрсөн он сар оруулна уу. + + + The selected choice is invalid. + Сонгосон утга буруу байна. + + + The collection is invalid. + Цуглуулга буруу байна. + + + Please select a valid color. + Үнэн зөв өнгө сонгоно уу. + + + Please select a valid country. + Үнэн зөв улс сонгоно уу. + + + Please select a valid currency. + Үнэн зөв мөнгөн тэмдэгт сонгоно уу. + + + Please choose a valid date interval. + Үнэн зөв цагын зай сонгоно уу. + + + Please enter a valid date and time. + Үнэн зөв он цаг оруулна уу. + + + Please enter a valid date. + Үнэн зөв он цаг өдөр оруулна уу. + + + Please select a valid file. + Үнэн зөв файл сонгоно уу. + + + The hidden field is invalid. + Нууц талбарын утга буруу байна. + + + Please enter an integer. + Бүхэл тоо оруулна уу. + + + Please select a valid language. + Үнэн зөв хэл сонгоно уу. + + + Please select a valid locale. + Үнэн зөв бүс сонгоно уу. + + + Please enter a valid money amount. + Үнэн зөв мөнгөний хэмжээ сонгоно уу. + + + Please enter a number. + Тоо оруулна уу. + + + The password is invalid. + Нууц үг буруу байна. + + + Please enter a percentage value. + Хувь утга оруулна уу. + + + The values do not match. + Утга хоорондоо таарахгүй байна. + + + Please enter a valid time. + Үнэн зөв цаг оруулна уу. + + + Please select a valid timezone. + Үнэн зөв цагын бүс оруулна уу. + + + Please enter a valid URL. + Үнэн зөв URL оруулна уу. + + + Please enter a valid search term. + Үнэн зөв хайх утга оруулна уу. + + + Please provide a valid phone number. + Үнэн зөв утасны дугаар оруулна уу. + + + The checkbox has an invalid value. + Сонгох хайрцаг буруу утгатай байна. + + + Please enter a valid email address. + Үнэн зөв и-мэйл хаяг оруулна уу. + + + Please select a valid option. + Үнэн зөв сонголт сонгоно уу. + + + Please select a valid range. + Үнэн зөв хязгаарын утга сонгоно уу. + + + Please enter a valid week. + Үнэн зөв долоо хоног сонгоно уу. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Form/Resources/translations/validators.nb.xlf index c64266c99189b..1d8385086aa82 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.nb.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.nb.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. CSRF nøkkelen er ugyldig. + + This value is not a valid HTML5 color. + Denne verdien er ikke en gyldig HTML5-farge. + + + Please enter a valid birthdate. + Vennligst oppgi gyldig fødselsdato. + + + The selected choice is invalid. + Det valgte valget er ugyldig. + + + The collection is invalid. + Samlingen er ugyldig. + + + Please select a valid color. + Velg en gyldig farge. + + + Please select a valid country. + Vennligst velg et gyldig land. + + + Please select a valid currency. + Vennligst velg en gyldig valuta. + + + Please choose a valid date interval. + Vennligst velg et gyldig datointervall. + + + Please enter a valid date and time. + Vennligst angi en gyldig dato og tid. + + + Please enter a valid date. + Vennligst oppgi en gyldig dato. + + + Please select a valid file. + Vennligst velg en gyldig fil. + + + The hidden field is invalid. + Det skjulte feltet er ugyldig. + + + Please enter an integer. + Vennligst skriv inn et heltall. + + + Please select a valid language. + Vennligst velg et gyldig språk. + + + Please select a valid locale. + Vennligst velg et gyldig sted. + + + Please enter a valid money amount. + Vennligst angi et gyldig pengebeløp. + + + Please enter a number. + Vennligst skriv inn et nummer. + + + The password is invalid. + Passordet er ugyldig. + + + Please enter a percentage value. + Vennligst angi en prosentverdi. + + + The values do not match. + Verdiene stemmer ikke overens. + + + Please enter a valid time. + Vennligst angi et gyldig tidspunkt. + + + Please select a valid timezone. + Vennligst velg en gyldig tidssone. + + + Please enter a valid URL. + Vennligst skriv inn en gyldig URL. + + + Please enter a valid search term. + Vennligst angi et gyldig søketerm. + + + Please provide a valid phone number. + Vennligst oppgi et gyldig telefonnummer. + + + The checkbox has an invalid value. + Avkrysningsboksen har en ugyldig verdi. + + + Please enter a valid email address. + Vennligst skriv inn en gyldig e-post adresse. + + + Please select a valid option. + Vennligst velg et gyldig alternativ. + + + Please select a valid range. + Vennligst velg et gyldig område. + + + Please enter a valid week. + Vennligst skriv inn en gyldig uke. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.no.xlf b/src/Symfony/Component/Form/Resources/translations/validators.no.xlf index c64266c99189b..1d8385086aa82 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.no.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. CSRF nøkkelen er ugyldig. + + This value is not a valid HTML5 color. + Denne verdien er ikke en gyldig HTML5-farge. + + + Please enter a valid birthdate. + Vennligst oppgi gyldig fødselsdato. + + + The selected choice is invalid. + Det valgte valget er ugyldig. + + + The collection is invalid. + Samlingen er ugyldig. + + + Please select a valid color. + Velg en gyldig farge. + + + Please select a valid country. + Vennligst velg et gyldig land. + + + Please select a valid currency. + Vennligst velg en gyldig valuta. + + + Please choose a valid date interval. + Vennligst velg et gyldig datointervall. + + + Please enter a valid date and time. + Vennligst angi en gyldig dato og tid. + + + Please enter a valid date. + Vennligst oppgi en gyldig dato. + + + Please select a valid file. + Vennligst velg en gyldig fil. + + + The hidden field is invalid. + Det skjulte feltet er ugyldig. + + + Please enter an integer. + Vennligst skriv inn et heltall. + + + Please select a valid language. + Vennligst velg et gyldig språk. + + + Please select a valid locale. + Vennligst velg et gyldig sted. + + + Please enter a valid money amount. + Vennligst angi et gyldig pengebeløp. + + + Please enter a number. + Vennligst skriv inn et nummer. + + + The password is invalid. + Passordet er ugyldig. + + + Please enter a percentage value. + Vennligst angi en prosentverdi. + + + The values do not match. + Verdiene stemmer ikke overens. + + + Please enter a valid time. + Vennligst angi et gyldig tidspunkt. + + + Please select a valid timezone. + Vennligst velg en gyldig tidssone. + + + Please enter a valid URL. + Vennligst skriv inn en gyldig URL. + + + Please enter a valid search term. + Vennligst angi et gyldig søketerm. + + + Please provide a valid phone number. + Vennligst oppgi et gyldig telefonnummer. + + + The checkbox has an invalid value. + Avkrysningsboksen har en ugyldig verdi. + + + Please enter a valid email address. + Vennligst skriv inn en gyldig e-post adresse. + + + Please select a valid option. + Vennligst velg et gyldig alternativ. + + + Please select a valid range. + Vennligst velg et gyldig område. + + + Please enter a valid week. + Vennligst skriv inn en gyldig uke. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.pt.xlf b/src/Symfony/Component/Form/Resources/translations/validators.pt.xlf index 554a810c68673..6ce1c3242cab3 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.pt.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.pt.xlf @@ -4,15 +4,135 @@ This form should not contain extra fields. - Este formulário não deveria conter campos extra. + Este formulário não deveria possuir mais campos. The uploaded file was too large. Please try to upload a smaller file. - O arquivo enviado é muito grande. Por favor, tente enviar um ficheiro mais pequeno. + O ficheiro enviado é muito grande. Por favor, tente enviar um ficheiro menor. The CSRF token is invalid. Please try to resubmit the form. - O token CSRF é inválido. Por favor submeta o formulário novamente. + O token CSRF está inválido. Por favor, tente enviar o formulário novamente. + + + This value is not a valid HTML5 color. + Este valor não é uma cor HTML5 válida. + + + Please enter a valid birthdate. + Por favor, informe uma data de nascimento válida. + + + The selected choice is invalid. + A escolha seleccionada é inválida. + + + The collection is invalid. + A coleção é inválida. + + + Please select a valid color. + Por favor, selecione uma cor válida. + + + Please select a valid country. + Por favor, selecione um país válido. + + + Please select a valid currency. + Por favor, selecione uma moeda válida. + + + Please choose a valid date interval. + Por favor, escolha um intervalo de datas válido. + + + Please enter a valid date and time. + Por favor, informe uma data e horário válidos. + + + Please enter a valid date. + Por favor, informe uma data válida. + + + Please select a valid file. + Por favor, selecione um ficheiro válido. + + + The hidden field is invalid. + O campo oculto é inválido. + + + Please enter an integer. + Por favor, informe um inteiro. + + + Please select a valid language. + Por favor selecione um idioma válido. + + + Please select a valid locale. + Por favor, selecione um locale válido. + + + Please enter a valid money amount. + Por favor, informe um valor monetário válido. + + + Please enter a number. + Por favor, informe um número. + + + The password is invalid. + A palavra-passe é inválida. + + + Please enter a percentage value. + Por favor, informe um valor percentual. + + + The values do not match. + Os valores não correspondem. + + + Please enter a valid time. + Por favor, informe uma hora válida. + + + Please select a valid timezone. + Por favor, selecione um fuso horário válido. + + + Please enter a valid URL. + Por favor, informe uma URL válida. + + + Please enter a valid search term. + Por favor, informe um termo de busca válido. + + + Please provide a valid phone number. + Por favor, infome um número de telefone válido. + + + The checkbox has an invalid value. + O checkbox possui um valor inválido. + + + Please enter a valid email address. + Por favor, informe um endereço de email válido. + + + Please select a valid option. + Por favor, selecione uma opção válida. + + + Please select a valid range. + Por favor, selecione um intervalo válido. + + + Please enter a valid week. + Por favor, selecione uma semana válida. diff --git a/src/Symfony/Component/Form/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Form/Resources/translations/validators.sk.xlf index 638d0cc4a0b3e..06b2bbdbead5f 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.sk.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Prosím skúste znovu odoslať formulár. + + This value is not a valid HTML5 color. + Táto hodnota nie je platná HTML5 farba. + + + Please enter a valid birthdate. + Prosím zadajte platný dátum narodenia. + + + The selected choice is invalid. + Vybraná možnosť je neplatná. + + + The collection is invalid. + Kolekcia je neplatná. + + + Please select a valid color. + Prosím vyberte platnú farbu. + + + Please select a valid country. + Prosím vyberte platnú krajinu. + + + Please select a valid currency. + Prosím vyberte platnú menu. + + + Please choose a valid date interval. + Prosím vyberte platný rozsah dát. + + + Please enter a valid date and time. + Prosím zadajte platný dátum a čas. + + + Please enter a valid date. + Prosím zadajte platný dátum. + + + Please select a valid file. + Prosím vyberte platný súbor. + + + The hidden field is invalid. + Skryté pole je neplatné. + + + Please enter an integer. + Prosím zadajte celé číslo. + + + Please select a valid language. + Prosím vyberte platný jazyk. + + + Please select a valid locale. + Prosím vyberte platné miestne nastavenia. + + + Please enter a valid money amount. + Prosím zadajte platnú čiastku. + + + Please enter a number. + Prosím zadajte číslo. + + + The password is invalid. + Heslo je neprávne. + + + Please enter a percentage value. + Prosím zadajte percentuálnu hodnotu. + + + The values do not match. + Hodnoty nie sú zhodné. + + + Please enter a valid time. + Prosím zadajte platný čas. + + + Please select a valid timezone. + Prosím vyberte platné časové pásmo. + + + Please enter a valid URL. + Prosím zadajte platnú URL. + + + Please enter a valid search term. + Prosím zadajte platný vyhľadávací výraz. + + + Please provide a valid phone number. + Prosím zadajte platné telefónne číslo. + + + The checkbox has an invalid value. + Zaškrtávacie políčko má neplatnú hodnotu. + + + Please enter a valid email address. + Prosím zadajte platnú emailovú adresu. + + + Please select a valid option. + Prosím vyberte platnú možnosť. + + + Please select a valid range. + Prosím vyberte platný rozsah. + + + Please enter a valid week. + Prosím zadajte platný týždeň. + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf b/src/Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf index 1aa242f4186a4..a5610e0ead295 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf @@ -114,6 +114,26 @@ Please provide a valid phone number. Молим наведите исправан број телефона. + + The checkbox has an invalid value. + Поље за потврду садржи неисправну вредност. + + + Please enter a valid email address. + Молим упишите исправну email адресу. + + + Please select a valid option. + Молим изаберите исправну опцију. + + + Please select a valid range. + Молим изаберите исправан опсег. + + + Please enter a valid week. + Молим упишите исправну седмицу. + - \ No newline at end of file + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf b/src/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf index 75a2aaab70e2e..02fb5aa56ead4 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf @@ -114,6 +114,26 @@ Please provide a valid phone number. Molim navedite ispravan broj telefona. + + The checkbox has an invalid value. + Polje za potvrdu sadrži neispravnu vrednost. + + + Please enter a valid email address. + Molim upišite ispravnu email adresu. + + + Please select a valid option. + Molim izaberite ispravnu opciju. + + + Please select a valid range. + Molim izaberite ispravan opseg. + + + Please enter a valid week. + Molim upišite ispravnu sedmicu. + - \ No newline at end of file + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.th.xlf b/src/Symfony/Component/Form/Resources/translations/validators.th.xlf new file mode 100644 index 0000000000000..060dc9ec48094 --- /dev/null +++ b/src/Symfony/Component/Form/Resources/translations/validators.th.xlf @@ -0,0 +1,139 @@ + + + + + + This form should not contain extra fields. + ฟอร์มนี้ไม่ควรมี extra fields + + + The uploaded file was too large. Please try to upload a smaller file. + ไฟล์ที่อัพโหลดมีขนาดใหญ่เกินไป กรุณาลองอัพโหลดใหม่อีกครั้งด้วยไฟล์ที่มีขนาดเล็กลง + + + The CSRF token is invalid. Please try to resubmit the form. + CSRF token ไม่ถูกต้อง กรุณาลองส่งแบบฟอร์มใหม่ + + + This value is not a valid HTML5 color. + ค่านี้ไม่ใช่ค่าที่ถูกต้องของค่าสี HTML5 + + + Please enter a valid birthdate. + กรุณากรอกวันเดือนปีเกิดที่ถูกต้อง + + + The selected choice is invalid. + ตัวเลือกที่เลิอกไม่ถูกต้อง + + + The collection is invalid. + คอเล็กชั่นไม่ถูกต้อง + + + Please select a valid color. + กรุณาเลือกค่าสีที่ถูกต้อง + + + Please select a valid country. + กรุณาเลือกประเทศที่ถูกต้อง + + + Please select a valid currency. + กรุุณาเลิอกค่าสกุลเงินที่ถูกต้อง + + + Please choose a valid date interval. + กรุณณากรอกช่วงวันที่ที่ถูกต้อง + + + Please enter a valid date and time. + กรุณณากรอกค่าเวลาและวันที่ที่ถูกต้อง + + + Please enter a valid date. + กรุณณากรอกค่าวันที่ที่ถูกต้อง + + + Please select a valid file. + กรุณาเลือกไฟล์ที่ถูกต้อง + + + The hidden field is invalid. + ค่า Hidden field ไม่ถูกต้อง + + + Please enter an integer. + กรุณากรอกตัวเลขจำนวนเต็ม + + + Please select a valid language. + กรุณาเลือกภาษาที่ถูกต้อง + + + Please select a valid locale. + กรุณาเลือกท้องถิ่นที่ถูกต้อง + + + Please enter a valid money amount. + กรุณากรอกจำนวนเงินที่ถูกต้อง + + + Please enter a number. + กรุณากรอกตัวเลข + + + The password is invalid. + รหัสผ่านไม่ถูกต้อง + + + Please enter a percentage value. + กรุณากรอกค่าเปอร์เซ็นต์ + + + The values do not match. + ค่าทั้งสองไม่ตรงกัน + + + Please enter a valid time. + กรุณากรอกค่าเวลาที่ถูกต้อง + + + Please select a valid timezone. + กรุณาเลือกค่าเขตเวลาที่ถูกต้อง + + + Please enter a valid URL. + กรุณากรอก URL ที่ถูกต้อง + + + Please enter a valid search term. + กรุณากรอกคำค้นหาที่ถูกต้อง + + + Please provide a valid phone number. + กรุณากรอกเบอร์โทรศัพท์ที่ถูกต้อง + + + The checkbox has an invalid value. + Checkbox มีค่าที่ไม่ถูกต้อง + + + Please enter a valid email address. + กรุณากรอกที่อยู่อีเมล์ที่ถูกต้อง + + + Please select a valid option. + กรุณาเลือกตัวเลือกที่ถูกต้อง + + + Please select a valid range. + กรุณาเลือกค่าช่วงที่ถูกต้อง + + + Please enter a valid week. + กรุณากรอกค่าสัปดาห์ที่ถูกต้อง + + + + diff --git a/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf index 950c4110d880a..272e331298a2f 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf @@ -114,6 +114,26 @@ Please provide a valid phone number. Pakilagay ang balidong numero ng telepono. + + The checkbox has an invalid value. + Ang checkbox ay mayroon hindi balidong halaga. + + + Please enter a valid email address. + Pakilagay ang balidong email address. + + + Please select a valid option. + Pakipiliin ang balidong pagpipilian. + + + Please select a valid range. + Pakipilian ang balidong layo. + + + Please enter a valid week. + Pakilagay ang balidong linggo. + diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 3694e49f4292c..e9f9ea6bdc759 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -16,7 +16,7 @@ class BooleanToStringTransformerTest extends TestCase { - const TRUE_VALUE = '1'; + private const TRUE_VALUE = '1'; /** * @var BooleanToStringTransformer diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index afd6660614b34..89a2c4c57c03d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -34,10 +34,10 @@ */ class ViolationMapperTest extends TestCase { - const LEVEL_0 = 0; - const LEVEL_1 = 1; - const LEVEL_1B = 2; - const LEVEL_2 = 3; + private const LEVEL_0 = 0; + private const LEVEL_1 = 1; + private const LEVEL_1B = 2; + private const LEVEL_2 = 3; /** * @var EventDispatcherInterface diff --git a/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php index 3b0d926c2ee7a..53b2cee448805 100644 --- a/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Resources; use PHPUnit\Framework\TestCase; -use PHPUnit\Util\Xml\Loader; +use Symfony\Component\Translation\Util\XliffUtils; class TranslationFilesTest extends TestCase { @@ -21,13 +21,12 @@ class TranslationFilesTest extends TestCase */ public function testTranslationFileIsValid($filePath) { - $loader = class_exists(Loader::class) - ? [new Loader(), 'loadFile'] - : ['PHPUnit\Util\XML', 'loadfile']; + $document = new \DOMDocument(); + $document->loadXML(file_get_contents($filePath)); - $loader($filePath, false, false, true); + $errors = XliffUtils::validateSchema($document); - $this->addToAssertionCount(1); + $this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php index a33490b8ef9eb..9e1a2d5e0107b 100644 --- a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php +++ b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php @@ -83,18 +83,14 @@ public function getContent(bool $throw = true): string if (false === $this->content) { return $this->response->getContent($throw); } - - $this->content = $this->response->getContent(false); - - if ($throw) { - $this->checkStatusCode($this->response->getStatusCode()); - } - - return $this->content; + return $this->content = $this->response->getContent(false); } finally { if ($this->event && $this->event->isStarted()) { $this->event->stop(); } + if ($throw) { + $this->checkStatusCode($this->response->getStatusCode()); + } } } @@ -104,18 +100,14 @@ public function toArray(bool $throw = true): array if (false === $this->content) { return $this->response->toArray($throw); } - - $this->content = $this->response->toArray(false); - - if ($throw) { - $this->checkStatusCode($this->response->getStatusCode()); - } - - return $this->content; + return $this->content = $this->response->toArray(false); } finally { if ($this->event && $this->event->isStarted()) { $this->event->stop(); } + if ($throw) { + $this->checkStatusCode($this->response->getStatusCode()); + } } } diff --git a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php index 2ba50adfe25aa..544f4509c4680 100755 --- a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpClient\TraceableHttpClient; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\Test\TestHttpServer; @@ -118,6 +119,18 @@ public function testStream() $this->assertSame('Symfony is awesome!', implode('', $chunks)); } + public function testToArrayChecksStatusCodeBeforeDecoding() + { + $this->expectException(ClientExceptionInterface::class); + + $sut = new TraceableHttpClient(new MockHttpClient($responseFactory = function (): MockResponse { + return new MockResponse('Errored.', ['http_code' => 400]); + })); + + $response = $sut->request('GET', 'https://example.com/foo/bar'); + $response->toArray(); + } + public function testStopwatch() { $sw = new Stopwatch(true); diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 4e1b2cf411961..930ea23f39091 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -217,7 +217,7 @@ public function prepare(Request $request) // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); foreach ($parts as $part) { - list($pathPrefix, $location) = $part; + [$pathPrefix, $location] = $part; if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { $path = $location.substr($path, \strlen($pathPrefix)); // Only set X-Accel-Redirect header if a valid URI can be produced @@ -237,7 +237,7 @@ public function prepare(Request $request) $range = $request->headers->get('Range'); if (0 === strpos($range, 'bytes=')) { - list($start, $end) = explode('-', substr($range, 6), 2) + [0]; + [$start, $end] = explode('-', substr($range, 6), 2) + [0]; $end = ('' === $end) ? $fileSize - 1 : (int) $end; diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 17d3804566709..fef21b8723594 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -10,6 +10,9 @@ CHANGELOG * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` * added `Request::toArray()` to parse a JSON request body to an array * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter` + * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. + * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead. + 5.1.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/InputBag.php b/src/Symfony/Component/HttpFoundation/InputBag.php index a45c9529ed5fc..2c21748e08c7d 100644 --- a/src/Symfony/Component/HttpFoundation/InputBag.php +++ b/src/Symfony/Component/HttpFoundation/InputBag.php @@ -103,6 +103,11 @@ public function filter(string $key, $default = null, int $filter = \FILTER_DEFAU } } + if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { + trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); + // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); + } + return filter_var($value, $filter, $options); } } diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 0599ce553ef5f..27fe725929f7d 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -71,7 +71,7 @@ public static function checkIp4(?string $requestIp, string $ip) } if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); + [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { return self::$checkedIps[$cacheKey] = filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); @@ -118,7 +118,7 @@ public static function checkIp6(?string $requestIp, string $ip) } if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); + [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { return (bool) unpack('n*', @inet_pton($address)); diff --git a/src/Symfony/Component/HttpFoundation/ParameterBag.php b/src/Symfony/Component/HttpFoundation/ParameterBag.php index 1de54859a1884..c6e2dff27e397 100644 --- a/src/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/src/Symfony/Component/HttpFoundation/ParameterBag.php @@ -194,6 +194,11 @@ public function filter(string $key, $default = null, int $filter = \FILTER_DEFAU $options['flags'] = \FILTER_REQUIRE_ARRAY; } + if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { + trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); + // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); + } + return filter_var($value, $filter, $options); } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 1e64183a5697e..34cd4924656ff 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -47,9 +47,10 @@ class Request const HEADER_X_FORWARDED_PORT = 0b010000; const HEADER_X_FORWARDED_PREFIX = 0b100000; - const HEADER_X_FORWARDED_ALL = 0b011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy - const HEADER_X_FORWARDED_AWS_ELB = 0b011010; // AWS ELB doesn't send X-Forwarded-Host - const HEADER_X_FORWARDED_TRAEFIK = 0b111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy + /** @deprecated since Symfony 5.2, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead. */ + const HEADER_X_FORWARDED_ALL = 0b1011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy + const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host + const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy const METHOD_HEAD = 'HEAD'; const METHOD_GET = 'GET'; @@ -184,7 +185,7 @@ class Request protected $format; /** - * @var SessionInterface + * @var SessionInterface|callable */ protected $session; @@ -593,6 +594,9 @@ public function overrideGlobals() */ public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) { + if (self::HEADER_X_FORWARDED_ALL === $trustedHeaderSet) { + trigger_deprecation('symfony/http-fundation', '5.2', 'The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.'); + } self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { if ('REMOTE_ADDR' !== $proxy) { $proxies[] = $proxy; diff --git a/src/Symfony/Component/HttpFoundation/ServerBag.php b/src/Symfony/Component/HttpFoundation/ServerBag.php index 02c70911c19f1..ed2d7812ac31b 100644 --- a/src/Symfony/Component/HttpFoundation/ServerBag.php +++ b/src/Symfony/Component/HttpFoundation/ServerBag.php @@ -66,7 +66,7 @@ public function getHeaders() // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); if (2 == \count($exploded)) { - list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; + [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { // In some circumstances PHP_AUTH_DIGEST needs to be set diff --git a/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php index 870057e41bdb1..30c97607a893f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php @@ -45,6 +45,17 @@ public function testFilterArray() $this->assertSame([12, 8], $result); } + /** + * @group legacy + */ + public function testFilterCallback() + { + $bag = new InputBag(['foo' => 'bar']); + + $this->expectDeprecation('Since symfony/http-foundation 5.2: Not passing a Closure together with FILTER_CALLBACK to "Symfony\Component\HttpFoundation\InputBag::filter()" is deprecated. Wrap your filter in a closure instead.'); + $this->assertSame('BAR', $bag->filter('foo', null, \FILTER_CALLBACK, ['options' => 'strtoupper'])); + } + /** * @group legacy */ diff --git a/src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php index e5f436e8e7003..3c83d9e387fbd 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php @@ -12,11 +12,14 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\ParameterBag; class ParameterBagTest extends TestCase { + use ExpectDeprecationTrait; + public function testConstructor() { $this->testAll(); @@ -176,6 +179,17 @@ public function testFilter() $this->assertEquals(['bang'], $bag->filter('array', ''), '->filter() gets a value of parameter as an array'); } + /** + * @group legacy + */ + public function testFilterCallback() + { + $bag = new ParameterBag(['foo' => 'bar']); + + $this->expectDeprecation('Since symfony/http-foundation 5.2: Not passing a Closure together with FILTER_CALLBACK to "Symfony\Component\HttpFoundation\ParameterBag::filter()" is deprecated. Wrap your filter in a closure instead.'); + $this->assertSame('BAR', $bag->filter('foo', null, \FILTER_CALLBACK, ['options' => 'strtoupper'])); + } + public function testGetIterator() { $parameters = ['foo' => 'bar', 'hello' => 'world']; diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 5d466afe25f8b..6b01446c2f611 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\HttpFoundation\Exception\JsonException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\InputBag; @@ -22,6 +23,8 @@ class RequestTest extends TestCase { + use ExpectDeprecationTrait; + protected function tearDown(): void { Request::setTrustedProxies([], -1); @@ -867,7 +870,7 @@ public function testGetPort() $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.'); - Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_PORT); $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '8443', @@ -1091,7 +1094,7 @@ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXFor 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, ]; - Request::setTrustedProxies(['88.88.88.88'], Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED); + Request::setTrustedProxies(['88.88.88.88'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_FORWARDED); $request->initialize([], [], [], [], [], $server); @@ -1349,7 +1352,7 @@ public function testOverrideGlobals() $request->headers->set('X_FORWARDED_PROTO', 'https'); - Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_PROTO); $this->assertFalse($request->isSecure()); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertTrue($request->isSecure()); @@ -1830,7 +1833,7 @@ private function getRequestInstanceForClientIpTests(string $remoteAddr, ?string } if ($trustedProxies) { - Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_FOR); } $request->initialize([], [], [], [], [], $server); @@ -1873,35 +1876,35 @@ public function testTrustedProxiesXForwardedFor() $this->assertFalse($request->isSecure()); // disabling proxy trusting - Request::setTrustedProxies([], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies([], Request::HEADER_X_FORWARDED_FOR); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // request is forwarded by a non-trusted proxy - Request::setTrustedProxies(['2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['2.2.2.2'], Request::HEADER_X_FORWARDED_FOR); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO); $this->assertEquals('1.1.1.1', $request->getClientIp()); $this->assertEquals('foo.example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(['3.3.3.4', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.4', '2.2.2.2'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // check various X_FORWARDED_PROTO header values - Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_PROTO); $request->headers->set('X_FORWARDED_PROTO', 'ssl'); $this->assertTrue($request->isSecure()); @@ -2377,7 +2380,7 @@ public function testTrustedPort() public function testTrustedPortDoesNotDefaultToZero() { - Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_FOR); $request = Request::create('/'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); @@ -2393,7 +2396,7 @@ public function testTrustedPortDoesNotDefaultToZero() public function testTrustedProxiesRemoteAddr($serverRemoteAddr, $trustedProxies, $result) { $_SERVER['REMOTE_ADDR'] = $serverRemoteAddr; - Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_FOR); $this->assertSame($result, Request::getTrustedProxies()); } @@ -2464,6 +2467,23 @@ public function preferSafeContentData() ], ]; } + + /** + * @group legacy + */ + public function testXForwarededAllConstantDeprecated() + { + $this->expectDeprecation('Since symfony/http-fundation 5.2: The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.'); + + Request::setTrustedProxies([], Request::HEADER_X_FORWARDED_ALL); + } + + public function testReservedFlags() + { + foreach ((new \ReflectionClass(Request::class))->getConstants() as $constant => $value) { + $this->assertNotSame(0b10000000, $value, sprintf('The constant "%s" should not use the reserved value "0b10000000".', $constant)); + } + } } class RequestContentProxy extends Request diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index e9c17703a7173..6fe43a0027aef 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -20,8 +20,8 @@ */ class MemcachedSessionHandlerTest extends TestCase { - const PREFIX = 'prefix_'; - const TTL = 1000; + private const PREFIX = 'prefix_'; + private const TTL = 1000; /** * @var MemcachedSessionHandler diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index cffe45904dcf5..300ee020c2854 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -114,7 +114,7 @@ protected function createController(string $controller) return $controller; } - list($class, $method) = explode('::', $controller, 2); + [$class, $method] = explode('::', $controller, 2); try { $controller = [$this->instantiateController($class), $method]; @@ -172,7 +172,7 @@ private function getControllerError($callable): string return 'Invalid array callable, expected [controller, method].'; } - list($controller, $method) = $callable; + [$controller, $method] = $callable; if (\is_string($controller) && !class_exists($controller)) { return sprintf('Class "%s" does not exist.', $controller); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index ba45a2ddce783..33150ed0e1eae 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -75,7 +75,7 @@ public function dump(Data $data) $this->stopwatch->start('dump'); } - list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext(); + ['name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt] = $this->sourceContextProvider->getContext(); if ($this->dumper instanceof Connection) { if (!$this->dumper->write($data)) { diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 286f212f9a182..a2a9a0c71b1c9 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -106,7 +106,7 @@ public function process(ContainerBuilder $container) if (!isset($methods[$action = strtolower($attributes['action'])])) { throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class)); } - list($r, $parameters) = $methods[$action]; + [$r, $parameters] = $methods[$action]; $found = false; foreach ($parameters as $p) { @@ -124,7 +124,7 @@ public function process(ContainerBuilder $container) } } - foreach ($methods as list($r, $parameters)) { + foreach ($methods as [$r, $parameters]) { /** @var \ReflectionMethod $r */ // create a per-method map of argument-names to service/type-references @@ -146,7 +146,7 @@ public function process(ContainerBuilder $container) } elseif (isset($bindings[$bindingName = $type.' $'.$p->name]) || isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { $binding = $bindings[$bindingName]; - list($bindingValue, $bindingId, , $bindingType, $bindingFile) = $binding->getValues(); + [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues(); $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); if (!$bindingValue instanceof Reference) { diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php index f69d37619e446..5f54e9c164d5f 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php @@ -42,14 +42,14 @@ public function process(ContainerBuilder $container) } else { // any methods listed for call-at-instantiation cannot be actions $reason = false; - list($id, $action) = explode('::', $controller); + [$id, $action] = explode('::', $controller); if ($container->hasAlias($id)) { continue; } $controllerDef = $container->getDefinition($id); - foreach ($controllerDef->getMethodCalls() as list($method)) { + foreach ($controllerDef->getMethodCalls() as [$method]) { if (0 === strcasecmp($action, $method)) { $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id); break; diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php index 0208e8dec5371..882574ae2fd0b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php @@ -58,12 +58,9 @@ public function onKernelRequest(RequestEvent $event) $session = null; $request = $event->getRequest(); - if ($request->hasSession()) { - // no-op - } elseif (method_exists($request, 'setSessionFactory')) { - $request->setSessionFactory(function () { return $this->getSession(); }); - } elseif ($session = $this->getSession()) { - $request->setSession($session); + if (!$request->hasSession()) { + $sess = null; + $request->setSessionFactory(function () use (&$sess) { return $sess ?? $sess = $this->getSession(); }); } $session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 5d42e45e6e08d..5f604808da955 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.2.0-BETA3'; + const VERSION = '5.2.0-RC1'; const VERSION_ID = 50200; const MAJOR_VERSION = 5; const MINOR_VERSION = 2; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'BETA3'; + const EXTRA_VERSION = 'RC1'; const END_OF_MAINTENANCE = '07/2021'; const END_OF_LIFE = '07/2021'; @@ -244,7 +244,7 @@ public function locateResource(string $name) $bundleName = substr($name, 1); $path = ''; if (false !== strpos($bundleName, '/')) { - list($bundleName, $path) = explode('/', $bundleName, 2); + [$bundleName, $path] = explode('/', $bundleName, 2); } $bundle = $this->getBundle($bundleName); diff --git a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php index 4f63b41889c25..1d95ead92a978 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php @@ -61,7 +61,7 @@ public function find(?string $ip, ?string $url, ?int $limit, ?string $method, in $result = []; while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { $values = str_getcsv($line); - list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values; + [$csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values; $csvTime = (int) $csvTime; if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) { diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php index 2694d002cf5b6..c95a7fb52468c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php @@ -39,7 +39,7 @@ public function testServicesAreOrderedAccordingToPriority() $container = new ContainerBuilder(); $container->setDefinition('argument_resolver', $definition); - foreach ($services as $id => list($tag)) { + foreach ($services as $id => [$tag]) { $container->register($id)->addTag('controller.argument_value_resolver', $tag); } @@ -72,7 +72,7 @@ public function testInDebugWithStopWatchDefinition() $container->register('debug.stopwatch', Stopwatch::class); $container->setDefinition('argument_resolver', $definition); - foreach ($services as $id => list($tag)) { + foreach ($services as $id => [$tag]) { $container->register($id)->addTag('controller.argument_value_resolver', $tag); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index 36183d3c138be..e1e97c9eb9980 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -28,6 +28,7 @@ use Symfony\Component\HttpKernel\EventListener\SessionListener; use Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelInterface; class SessionListenerTest extends TestCase { @@ -182,6 +183,38 @@ public function testSurrogateMasterRequestIsPublic() $this->assertLessThanOrEqual((new \DateTime('now', new \DateTimeZone('UTC'))), (new \DateTime($response->headers->get('Expires')))); } + public function testGetSessionIsCalledOnce() + { + $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); + $sessionStorage = $this->getMockBuilder(NativeSessionStorage::class)->getMock(); + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + + $sessionStorage->expects($this->once()) + ->method('setOptions') + ->with(['cookie_secure' => true]); + + $requestStack = new RequestStack(); + $requestStack->push($masterRequest = new Request([], [], [], [], [], ['HTTPS' => 'on'])); + + $container = new Container(); + $container->set('session_storage', $sessionStorage); + $container->set('session', $session); + $container->set('request_stack', $requestStack); + + $event = new RequestEvent($kernel, $masterRequest, HttpKernelInterface::MASTER_REQUEST); + + $listener = new SessionListener($container); + $listener->onKernelRequest($event); + + $subRequest = $masterRequest->duplicate(); + // at this point both master and subrequest have a closure to build the session + + $masterRequest->getSession(); + + // calling the factory on the subRequest should not trigger a second call to storage->sesOptions() + $subRequest->getSession(); + } + public function testSessionUsageExceptionIfStatelessAndSessionUsed() { $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index 6ad64e47917a1..0f0a25ef1ccf6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -1361,7 +1361,7 @@ public function testClientIpIsAlwaysLocalhostForForwardedRequests() */ public function testHttpCacheIsSetAsATrustedProxy(array $existing) { - Request::setTrustedProxies($existing, Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies($existing, Request::HEADER_X_FORWARDED_FOR); $this->setNextResponse(); $this->request('GET', '/', ['REMOTE_ADDR' => '10.0.0.1']); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 1f5f472802e7a..fc1ef64663cf7 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -92,7 +92,7 @@ public function testSetsTheXContentDigestResponseHeaderBeforeStoring() { $cacheKey = $this->storeSimpleEntry(); $entries = $this->getStoreMetadata($cacheKey); - list(, $res) = $entries[0]; + [, $res] = $entries[0]; $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $res['x-content-digest'][0]); } @@ -103,7 +103,7 @@ public function testDoesNotTrustXContentDigestFromUpstream() $cacheKey = $this->store->write($this->request, $response); $entries = $this->getStoreMetadata($cacheKey); - list(, $res) = $entries[0]; + [, $res] = $entries[0]; $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $res['x-content-digest'][0]); $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $response->headers->get('X-Content-Digest')); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php index 933ed9b27c8c6..7f05fb8b89307 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php @@ -43,13 +43,13 @@ public function assert(\Closure $callback) { $trustedConfig = [Request::getTrustedProxies(), Request::getTrustedHeaderSet()]; - list($trustedProxies, $trustedHeaderSet, $backendRequest) = $this->backendRequest; + [$trustedProxies, $trustedHeaderSet, $backendRequest] = $this->backendRequest; Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); try { $callback($backendRequest); } finally { - list($trustedProxies, $trustedHeaderSet) = $trustedConfig; + [$trustedProxies, $trustedHeaderSet] = $trustedConfig; Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); } } diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php index 482999c60dd5f..3624295353161 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/BundleEntryReaderTest.php @@ -21,7 +21,7 @@ */ class BundleEntryReaderTest extends TestCase { - const RES_DIR = '/res/dir'; + private const RES_DIR = '/res/dir'; /** * @var BundleEntryReader diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/Verification/IntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/Verification/IntlDateFormatterTest.php index 50cccd993b8fa..ed82ead532fd3 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/Verification/IntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/Verification/IntlDateFormatterTest.php @@ -30,6 +30,18 @@ protected function setUp(): void parent::setUp(); } + /** + * @dataProvider formatProvider + */ + public function testFormat($pattern, $timestamp, $expected) + { + if (\PHP_VERSION_ID < 70105 && $timestamp instanceof \DateTimeImmutable) { + $this->markTestSkipped('PHP >= 7.1.5 required for DateTimeImmutable.'); + } + + parent::testFormat($pattern, $timestamp, $expected); + } + /** * @dataProvider formatTimezoneProvider */ diff --git a/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php b/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php index ecbeb0eb520a5..5868174332def 100644 --- a/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php +++ b/src/Symfony/Component/Intl/Tests/Util/GitRepositoryTest.php @@ -23,7 +23,7 @@ class GitRepositoryTest extends TestCase { private $targetDir; - const REPO_URL = 'https://github.com/symfony/intl.git'; + private const REPO_URL = 'https://github.com/symfony/intl.git'; /** * @before diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php index 0ea9aa3b86dd4..6af544fb5b5c6 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php @@ -174,7 +174,7 @@ public function getResources(): array private function resetPagination() { $con = $this->connection->getResource(); - $this->controlPagedResultResponse($con, 0, ''); + $this->controlPagedResult($con, 0, ''); $this->serverctrls = []; // This is a workaround for a bit of a bug in the above invocation diff --git a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php index d17b47b1fadd9..0c2253ee00142 100644 --- a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php +++ b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php @@ -25,7 +25,7 @@ */ class AdapterTest extends LdapTestCase { - const PAGINATION_REQUIRED_CONFIG = [ + private const PAGINATION_REQUIRED_CONFIG = [ 'options' => [ 'protocol_version' => 3, ], diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index 2f8fd45586e61..e844a35bb6cfc 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -82,7 +82,7 @@ public function putOffExpiration(Key $key, float $ttl) $token = $this->getUniqueToken($key); - list($value, $cas) = $this->getValueAndCas($key); + [$value, $cas] = $this->getValueAndCas($key); $key->reduceLifetime($ttl); // Could happens when we ask a putOff after a timeout but in luck nobody steal the lock @@ -114,7 +114,7 @@ public function delete(Key $key) { $token = $this->getUniqueToken($key); - list($value, $cas) = $this->getValueAndCas($key); + [$value, $cas] = $this->getValueAndCas($key); if ($value !== $token) { // we are not the owner of the lock. Nothing to do. diff --git a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php index 72ffbdcad04b7..a94c7686180f5 100644 --- a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php @@ -61,7 +61,7 @@ private function getOpenedSemaphores() if ('------ Semaphore Status --------' !== $lines[0]) { throw new \Exception('Failed to extract list of opened semaphores. Expected a Semaphore status, got '.implode(\PHP_EOL, $lines)); } - list($key, $value) = explode(' = ', $lines[1]); + [$key, $value] = explode(' = ', $lines[1]); if ('used arrays' !== $key) { throw new \Exception('Failed to extract list of opened semaphores. Expected a "used arrays" key, got '.implode(\PHP_EOL, $lines)); } diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index 760486a8adfb5..8e4bae7faed8d 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -88,7 +88,7 @@ public function fromStrings(array $dsns): Transports public function fromString(string $dsn): TransportInterface { - list($transport, $offset) = $this->parseDsn($dsn); + [$transport, $offset] = $this->parseDsn($dsn); if ($offset !== \strlen($dsn)) { throw new InvalidArgumentException(sprintf('The DSN has some garbage at the end: "%s".', substr($dsn, $offset))); } @@ -116,7 +116,7 @@ private function parseDsn(string $dsn, int $offset = 0): array ++$offset; $args = []; while (true) { - list($arg, $offset) = $this->parseDsn($dsn, $offset); + [$arg, $offset] = $this->parseDsn($dsn, $offset); $args[] = $arg; if (\strlen($dsn) === $offset) { break; diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php index 365bcd1f8ba9a..5ef8a8825509f 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php @@ -290,7 +290,7 @@ private function assertResponseCode(string $response, array $codes): void throw new TransportException(sprintf('Expected response code "%s" but got an empty response.', implode('/', $codes))); } - list($code) = sscanf($response, '%3d'); + [$code] = sscanf($response, '%3d'); $valid = \in_array($code, $codes); if (!$valid) { diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php index 168c28a73cb37..52e716981d647 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/ConnectionTest.php @@ -92,7 +92,7 @@ public function testFromDsnAsQueueUrl() { $httpClient = $this->getMockBuilder(HttpClientInterface::class)->getMock(); $this->assertEquals( - new Connection(['queue_name' => 'ab1-MyQueue-A2BCDEF3GHI4', 'account' => '123456789012'], new SqsClient(['region' => 'us-east-2', 'endpoint' => 'https://sqs.us-east-2.amazonaws.com', 'accessKeyId' => null, 'accessKeySecret' => null], null, $httpClient)), + new Connection(['queue_name' => 'ab1-MyQueue-A2BCDEF3GHI4', 'account' => '123456789012'], new SqsClient(['region' => 'us-east-2', 'endpoint' => 'https://sqs.us-east-2.amazonaws.com', 'accessKeyId' => null, 'accessKeySecret' => null], null, $httpClient), 'https://sqs.us-east-2.amazonaws.com/123456789012/ab1-MyQueue-A2BCDEF3GHI4'), Connection::fromDsn('https://sqs.us-east-2.amazonaws.com/123456789012/ab1-MyQueue-A2BCDEF3GHI4', [], $httpClient) ); } @@ -259,4 +259,57 @@ public function testUnexpectedSqsError() $connection = new Connection(['queue_name' => 'queue', 'account' => 123, 'auto_setup' => false], $client); $connection->get(); } + + /** + * @dataProvider provideQueueUrl + */ + public function testInjectQueueUrl(string $dsn, string $queueUrl) + { + $connection = Connection::fromDsn($dsn); + + $r = new \ReflectionObject($connection); + $queueProperty = $r->getProperty('queueUrl'); + $queueProperty->setAccessible(true); + + $this->assertSame($queueUrl, $queueProperty->getValue($connection)); + } + + public function provideQueueUrl() + { + yield ['https://sqs.us-east-2.amazonaws.com/123456/queue', 'https://sqs.us-east-2.amazonaws.com/123456/queue']; + yield ['https://KEY:SECRET@sqs.us-east-2.amazonaws.com/123456/queue', 'https://sqs.us-east-2.amazonaws.com/123456/queue']; + yield ['https://sqs.us-east-2.amazonaws.com/123456/queue?auto_setup=1', 'https://sqs.us-east-2.amazonaws.com/123456/queue']; + } + + /** + * @dataProvider provideNotQueueUrl + */ + public function testNotInjectQueueUrl(string $dsn) + { + $connection = Connection::fromDsn($dsn); + + $r = new \ReflectionObject($connection); + $queueProperty = $r->getProperty('queueUrl'); + $queueProperty->setAccessible(true); + + $this->assertNull($queueProperty->getValue($connection)); + } + + public function provideNotQueueUrl() + { + yield ['https://sqs.us-east-2.amazonaws.com/queue']; + yield ['https://us-east-2/123456/ab1-MyQueue-A2BCDEF3GHI4']; + yield ['sqs://default/queue']; + } + + public function testGetQueueUrlNotCalled() + { + $client = $this->getMockBuilder(SqsClient::class)->getMock(); + $connection = new Connection(['queue_name' => 'ab1-MyQueue-A2BCDEF3GHI4', 'account' => '123456789012'], $client, 'https://sqs.us-east-2.amazonaws.com/123456789012/ab1-MyQueue-A2BCDEF3GHI4'); + + $client->expects($this->never())->method('getQueueUrl'); + $client->expects($this->once())->method('deleteMessage'); + + $connection->delete('id'); + } } diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php index 96f8d17eb2b60..d4c7053b48f7b 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php @@ -57,10 +57,11 @@ class Connection /** @var string|null */ private $queueUrl; - public function __construct(array $configuration, SqsClient $client = null) + public function __construct(array $configuration, SqsClient $client = null, string $queueUrl = null) { $this->configuration = array_replace_recursive(self::DEFAULT_OPTIONS, $configuration); $this->client = $client ?? new SqsClient([]); + $this->queueUrl = $queueUrl; } public function __destruct() @@ -140,7 +141,18 @@ public static function fromDsn(string $dsn, array $options = [], HttpClientInter } $configuration['account'] = 2 === \count($parsedPath) ? $parsedPath[0] : $options['account'] ?? self::DEFAULT_OPTIONS['account']; - return new self($configuration, new SqsClient($clientConfiguration, null, $client)); + // When the DNS looks like a QueueUrl, we can directly inject it in the connection + // https://sqs.REGION.amazonaws.com/ACCOUNT/QUEUE + $queueUrl = null; + if ( + 'https' === $parsedUrl['scheme'] + && ($parsedUrl['host'] ?? 'default') === "sqs.{$clientConfiguration['region']}.amazonaws.com" + && ($parsedUrl['path'] ?? '/') === "/{$configuration['account']}/{$configuration['queue_name']}" + ) { + $queueUrl = 'https://'.$parsedUrl['host'].$parsedUrl['path']; + } + + return new self($configuration, new SqsClient($clientConfiguration, null, $client), $queueUrl); } public function get(): ?array diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineIntegrationTest.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineIntegrationTest.php index 470d20703d6b0..e99bf76f7733b 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineIntegrationTest.php @@ -62,7 +62,7 @@ public function testSendWithDelay() ->select('m.available_at') ->from('messenger_messages', 'm') ->where('m.body = :body') - ->setParameter(':body', '{"message": "Hi i am delayed"}') + ->setParameter('body', '{"message": "Hi i am delayed"}') ->execute(); $available_at = new \DateTime($stmt instanceof Result || $stmt instanceof DriverResult ? $stmt->fetchOne() : $stmt->fetchColumn()); diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineReceiverTest.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineReceiverTest.php index 6440cf0fe3c79..6e774ec71935e 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineReceiverTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineReceiverTest.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Driver\PDO\Exception; use Doctrine\DBAL\Driver\PDOException; use Doctrine\DBAL\Exception\DeadlockException; +use Doctrine\DBAL\Version; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Bridge\Doctrine\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection; @@ -77,7 +78,14 @@ public function testOccursRetryableExceptionFromConnection() $serializer = $this->createSerializer(); $connection = $this->createMock(Connection::class); $driverException = class_exists(Exception::class) ? Exception::new(new \PDOException('Deadlock', 40001)) : new PDOException(new \PDOException('Deadlock', 40001)); - $connection->method('get')->willThrowException(new DeadlockException('Deadlock', $driverException)); + if (!class_exists(Version::class)) { + // This is doctrine/dbal 3.x + $deadlockException = new DeadlockException($driverException, null); + } else { + $deadlockException = new DeadlockException('Deadlock', $driverException); + } + + $connection->method('get')->willThrowException($deadlockException); $receiver = new DoctrineReceiver($connection, $serializer); $this->assertSame([], $receiver->get()); $this->assertSame([], $receiver->get()); diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php index 49b3d9c573cec..9497353c5d242 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php @@ -341,7 +341,7 @@ private function executeQuery(string $sql, array $parameters = [], array $types return $stmt; } - private function executeStatement(string $sql, array $parameters = [], array $types = []) + protected function executeStatement(string $sql, array $parameters = [], array $types = []) { try { if (method_exists($this->driverConnection, 'executeStatement')) { diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php index 79a1dd68ba411..9dc8b77e38756 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php @@ -64,7 +64,7 @@ public function get(): ?array if (!$this->listening) { // This is secure because the table name must be a valid identifier: // https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS - $this->driverConnection->exec(sprintf('LISTEN "%s"', $this->configuration['table_name'])); + $this->executeStatement(sprintf('LISTEN "%s"', $this->configuration['table_name'])); $this->listening = true; } @@ -87,7 +87,7 @@ public function setup(): void { parent::setup(); - $this->driverConnection->exec(implode("\n", $this->getTriggerSql())); + $this->executeStatement(implode("\n", $this->getTriggerSql())); } /** @@ -134,7 +134,7 @@ private function unlisten() return; } - $this->driverConnection->exec(sprintf('UNLISTEN "%s"', $this->configuration['table_name'])); + $this->executeStatement(sprintf('UNLISTEN "%s"', $this->configuration['table_name'])); $this->listening = false; } } diff --git a/src/Symfony/Component/Messenger/Command/AbstractFailedMessagesCommand.php b/src/Symfony/Component/Messenger/Command/AbstractFailedMessagesCommand.php index 1c480ecdf1579..77a6700500eed 100644 --- a/src/Symfony/Component/Messenger/Command/AbstractFailedMessagesCommand.php +++ b/src/Symfony/Component/Messenger/Command/AbstractFailedMessagesCommand.php @@ -14,6 +14,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Dumper; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Stamp\ErrorDetailsStamp; use Symfony\Component\Messenger\Stamp\RedeliveryStamp; @@ -21,6 +22,11 @@ use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp; use Symfony\Component\Messenger\Transport\Receiver\MessageCountAwareInterface; use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface; +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Caster\TraceStub; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\Stub; +use Symfony\Component\VarDumper\Cloner\VarCloner; /** * @author Ryan Weaver @@ -121,7 +127,7 @@ protected function displaySingleMessage(Envelope $envelope, SymfonyStyle $io) if ($io->isVeryVerbose()) { $io->title('Message:'); - $dump = new Dumper($io); + $dump = new Dumper($io, null, $this->createCloner()); $io->writeln($dump($envelope->getMessage())); $io->title('Exception:'); $flattenException = null; @@ -130,7 +136,7 @@ protected function displaySingleMessage(Envelope $envelope, SymfonyStyle $io) } elseif (null !== $lastRedeliveryStampWithException) { $flattenException = $lastRedeliveryStampWithException->getFlattenException(); } - $io->writeln(null === $flattenException ? '(no data)' : $flattenException->getTraceAsString()); + $io->writeln(null === $flattenException ? '(no data)' : $dump($flattenException)); } else { $io->writeln(' Re-run command with -vv to see more message & error details.'); } @@ -172,4 +178,26 @@ protected function getLastRedeliveryStampWithException(Envelope $envelope): ?Red return null; } + + private function createCloner(): ?ClonerInterface + { + if (!class_exists(VarCloner::class)) { + return null; + } + + $cloner = new VarCloner(); + $cloner->addCasters([FlattenException::class => function (FlattenException $flattenException, array $a, Stub $stub): array { + $stub->class = $flattenException->getClass(); + + return [ + Caster::PREFIX_VIRTUAL.'message' => $flattenException->getMessage(), + Caster::PREFIX_VIRTUAL.'code' => $flattenException->getCode(), + Caster::PREFIX_VIRTUAL.'file' => $flattenException->getFile(), + Caster::PREFIX_VIRTUAL.'line' => $flattenException->getLine(), + Caster::PREFIX_VIRTUAL.'trace' => new TraceStub($flattenException->getTrace()), + ]; + }]); + + return $cloner; + } } diff --git a/src/Symfony/Component/Messenger/EventListener/AddErrorDetailsStampListener.php b/src/Symfony/Component/Messenger/EventListener/AddErrorDetailsStampListener.php index 4a9aaa1d79cee..fd5c9d6fc61c1 100644 --- a/src/Symfony/Component/Messenger/EventListener/AddErrorDetailsStampListener.php +++ b/src/Symfony/Component/Messenger/EventListener/AddErrorDetailsStampListener.php @@ -19,7 +19,7 @@ final class AddErrorDetailsStampListener implements EventSubscriberInterface { public function onMessageFailed(WorkerMessageFailedEvent $event): void { - $stamp = new ErrorDetailsStamp($event->getThrowable()); + $stamp = ErrorDetailsStamp::create($event->getThrowable()); $previousStamp = $event->getEnvelope()->last(ErrorDetailsStamp::class); // Do not append duplicate information diff --git a/src/Symfony/Component/Messenger/Stamp/ErrorDetailsStamp.php b/src/Symfony/Component/Messenger/Stamp/ErrorDetailsStamp.php index e06c3adf3ea41..ae03de5a6c12f 100644 --- a/src/Symfony/Component/Messenger/Stamp/ErrorDetailsStamp.php +++ b/src/Symfony/Component/Messenger/Stamp/ErrorDetailsStamp.php @@ -32,19 +32,29 @@ final class ErrorDetailsStamp implements StampInterface /** @var FlattenException|null */ private $flattenException; - public function __construct(Throwable $throwable) + /** + * @param int|mixed $exceptionCode + */ + public function __construct(string $exceptionClass, $exceptionCode, string $exceptionMessage, FlattenException $flattenException = null) + { + $this->exceptionClass = $exceptionClass; + $this->exceptionCode = $exceptionCode; + $this->exceptionMessage = $exceptionMessage; + $this->flattenException = $flattenException; + } + + public static function create(Throwable $throwable): self { if ($throwable instanceof HandlerFailedException) { $throwable = $throwable->getPrevious(); } - $this->exceptionClass = \get_class($throwable); - $this->exceptionCode = $throwable->getCode(); - $this->exceptionMessage = $throwable->getMessage(); - + $flattenException = null; if (class_exists(FlattenException::class)) { - $this->flattenException = FlattenException::createFromThrowable($throwable); + $flattenException = FlattenException::createFromThrowable($throwable); } + + return new self(\get_class($throwable), $throwable->getCode(), $throwable->getMessage(), $flattenException); } public function getExceptionClass(): string diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php index 884d432abda51..6c6f110f31b88 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Tests\Command; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Messenger\Command\FailedMessagesShowCommand; use Symfony\Component\Messenger\Envelope; @@ -31,7 +32,7 @@ public function testBasicRun() { $sentToFailureStamp = new SentToFailureTransportStamp('async'); $redeliveryStamp = new RedeliveryStamp(0); - $errorStamp = new ErrorDetailsStamp(new \Exception('Things are bad!', 123)); + $errorStamp = ErrorDetailsStamp::create(new \Exception('Things are bad!', 123)); $envelope = new Envelope(new \stdClass(), [ new TransportMessageIdStamp(15), $sentToFailureStamp, @@ -68,7 +69,7 @@ public function testMultipleRedeliveryFails() { $sentToFailureStamp = new SentToFailureTransportStamp('async'); $redeliveryStamp1 = new RedeliveryStamp(0); - $errorStamp = new ErrorDetailsStamp(new \Exception('Things are bad!', 123)); + $errorStamp = ErrorDetailsStamp::create(new \Exception('Things are bad!', 123)); $redeliveryStamp2 = new RedeliveryStamp(0); $envelope = new Envelope(new \stdClass(), [ new TransportMessageIdStamp(15), @@ -153,7 +154,7 @@ public function testListMessages() { $sentToFailureStamp = new SentToFailureTransportStamp('async'); $redeliveryStamp = new RedeliveryStamp(0); - $errorStamp = new ErrorDetailsStamp(new \RuntimeException('Things are bad!')); + $errorStamp = ErrorDetailsStamp::create(new \RuntimeException('Things are bad!')); $envelope = new Envelope(new \stdClass(), [ new TransportMessageIdStamp(15), $sentToFailureStamp, @@ -200,7 +201,7 @@ public function testListMessagesReturnsPaginatedMessages() new TransportMessageIdStamp(15), $sentToFailureStamp, new RedeliveryStamp(0), - new ErrorDetailsStamp(new \RuntimeException('Things are bad!')), + ErrorDetailsStamp::create(new \RuntimeException('Things are bad!')), ]); $receiver = $this->createMock(ListableReceiverInterface::class); $receiver->expects($this->once())->method('all')->with()->willReturn([$envelope]); @@ -234,4 +235,44 @@ public function testInvalidMessagesThrowsException() $tester = new CommandTester($command); $tester->execute(['id' => 15]); } + + public function testVeryVerboseOutputForSingleMessageContainsExceptionWithTrace() + { + $exception = new \RuntimeException('Things are bad!'); + $exceptionLine = __LINE__ - 1; + $envelope = new Envelope(new \stdClass(), [ + new TransportMessageIdStamp(15), + new SentToFailureTransportStamp('async'), + new RedeliveryStamp(0), + ErrorDetailsStamp::create($exception), + ]); + $receiver = $this->createMock(ListableReceiverInterface::class); + $receiver->expects($this->once())->method('find')->with(42)->willReturn($envelope); + + $command = new FailedMessagesShowCommand('failure_receiver', $receiver); + $tester = new CommandTester($command); + $tester->execute(['id' => 42], ['verbosity' => OutputInterface::VERBOSITY_VERY_VERBOSE]); + $this->assertStringMatchesFormat(sprintf(<<<'EOF' +%%A +Exception: +========== + +RuntimeException { + message: "Things are bad!" + code: 0 + file: "%s" + line: %d + trace: { + %%s%%eTests%%eCommand%%eFailedMessagesShowCommandTest.php:%d { + Symfony\Component\Messenger\Tests\Command\FailedMessagesShowCommandTest->testVeryVerboseOutputForSingleMessageContainsExceptionWithTrace() + › { + › $exception = new \RuntimeException('Things are bad!'); + › $exceptionLine = __LINE__ - 1; + } +%%A +EOF + , + __FILE__, $exceptionLine, $exceptionLine), + $tester->getDisplay(true)); + } } diff --git a/src/Symfony/Component/Messenger/Tests/EventListener/AddErrorDetailsStampListenerTest.php b/src/Symfony/Component/Messenger/Tests/EventListener/AddErrorDetailsStampListenerTest.php index 0fb58973071a8..cc01567a3d4b9 100644 --- a/src/Symfony/Component/Messenger/Tests/EventListener/AddErrorDetailsStampListenerTest.php +++ b/src/Symfony/Component/Messenger/Tests/EventListener/AddErrorDetailsStampListenerTest.php @@ -17,7 +17,7 @@ public function testExceptionDetailsAreAdded(): void $envelope = new Envelope(new \stdClass()); $exception = new \Exception('It failed!'); $event = new WorkerMessageFailedEvent($envelope, 'my_receiver', $exception); - $expectedStamp = new ErrorDetailsStamp($exception); + $expectedStamp = ErrorDetailsStamp::create($exception); $listener->onMessageFailed($event); @@ -29,12 +29,12 @@ public function testWorkerAddsNewErrorDetailsStampOnFailure() $listener = new AddErrorDetailsStampListener(); $envelope = new Envelope(new \stdClass(), [ - new ErrorDetailsStamp(new \InvalidArgumentException('First error!')), + ErrorDetailsStamp::create(new \InvalidArgumentException('First error!')), ]); $exception = new \Exception('Second error!'); $event = new WorkerMessageFailedEvent($envelope, 'my_receiver', $exception); - $expectedStamp = new ErrorDetailsStamp($exception); + $expectedStamp = ErrorDetailsStamp::create($exception); $listener->onMessageFailed($event); diff --git a/src/Symfony/Component/Messenger/Tests/Stamp/ErrorDetailsStampTest.php b/src/Symfony/Component/Messenger/Tests/Stamp/ErrorDetailsStampTest.php index c6db1de147fe7..98277931da71f 100644 --- a/src/Symfony/Component/Messenger/Tests/Stamp/ErrorDetailsStampTest.php +++ b/src/Symfony/Component/Messenger/Tests/Stamp/ErrorDetailsStampTest.php @@ -16,6 +16,12 @@ use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\Stamp\ErrorDetailsStamp; +use Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer; +use Symfony\Component\Messenger\Transport\Serialization\Serializer; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; +use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; +use Symfony\Component\Serializer\Serializer as SymfonySerializer; class ErrorDetailsStampTest extends TestCase { @@ -24,7 +30,7 @@ public function testGetters(): void $exception = new \Exception('exception message'); $flattenException = FlattenException::createFromThrowable($exception); - $stamp = new ErrorDetailsStamp($exception); + $stamp = ErrorDetailsStamp::create($exception); $this->assertSame(\Exception::class, $stamp->getExceptionClass()); $this->assertSame('exception message', $stamp->getExceptionMessage()); @@ -38,11 +44,30 @@ public function testUnwrappingHandlerFailedException(): void $exception = new HandlerFailedException($envelope, [$wrappedException]); $flattenException = FlattenException::createFromThrowable($wrappedException); - $stamp = new ErrorDetailsStamp($exception); + $stamp = ErrorDetailsStamp::create($exception); $this->assertSame(\Exception::class, $stamp->getExceptionClass()); $this->assertSame('I am inside', $stamp->getExceptionMessage()); $this->assertSame(123, $stamp->getExceptionCode()); $this->assertEquals($flattenException, $stamp->getFlattenException()); } + + public function testDeserialization(): void + { + $exception = new \Exception('exception message'); + $stamp = ErrorDetailsStamp::create($exception); + $serializer = new Serializer( + new SymfonySerializer([ + new ArrayDenormalizer(), + new FlattenExceptionNormalizer(), + new ObjectNormalizer(), + ], [new JsonEncoder()]) + ); + + $deserializedEnvelope = $serializer->decode($serializer->encode(new Envelope(new \stdClass(), [$stamp]))); + + $deserializedStamp = $deserializedEnvelope->last(ErrorDetailsStamp::class); + $this->assertInstanceOf(ErrorDetailsStamp::class, $deserializedStamp); + $this->assertEquals($stamp, $deserializedStamp); + } } diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/Normalizer/FlattenExceptionNormalizerTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/Normalizer/FlattenExceptionNormalizerTest.php index e73d7b26b24ab..971b0c487ee44 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/Normalizer/FlattenExceptionNormalizerTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/Normalizer/FlattenExceptionNormalizerTest.php @@ -60,6 +60,7 @@ public function testNormalize(FlattenException $exception) $this->assertSame($previous, $normalized['previous']); $this->assertSame($exception->getTrace(), $normalized['trace']); $this->assertSame($exception->getTraceAsString(), $normalized['trace_as_string']); + $this->assertSame($exception->getStatusText(), $normalized['status_text']); } public function provideFlattenException(): array @@ -95,6 +96,7 @@ public function testDenormalizeValidData() 'file' => 'foo.php', 'line' => 123, 'headers' => ['Content-Type' => 'application/json'], + 'status_text' => 'Whoops, looks like something went wrong.', 'trace' => [ [ 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, 'args' => [], @@ -108,6 +110,7 @@ public function testDenormalizeValidData() ], ], 'trace_as_string' => '#0 foo.php(123): foo()'.\PHP_EOL.'#1 bar.php(456): bar()', + 'status_text' => 'Whoops, looks like something went wrong.', ]; $exception = $this->normalizer->denormalize($normalized, FlattenException::class); @@ -121,10 +124,12 @@ public function testDenormalizeValidData() $this->assertSame($normalized['line'], $exception->getLine()); $this->assertSame($normalized['trace'], $exception->getTrace()); $this->assertSame($normalized['trace_as_string'], $exception->getTraceAsString()); + $this->assertSame($normalized['status_text'], $exception->getStatusText()); $this->assertInstanceOf(FlattenException::class, $previous = $exception->getPrevious()); $this->assertSame($normalized['previous']['message'], $previous->getMessage()); $this->assertSame($normalized['previous']['code'], $previous->getCode()); + $this->assertSame($normalized['previous']['status_text'], $previous->getStatusText()); } private function getMessengerContext(): array diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/Normalizer/FlattenExceptionNormalizer.php b/src/Symfony/Component/Messenger/Transport/Serialization/Normalizer/FlattenExceptionNormalizer.php index 6ee46c05a6ab3..344eea7cc743f 100644 --- a/src/Symfony/Component/Messenger/Transport/Serialization/Normalizer/FlattenExceptionNormalizer.php +++ b/src/Symfony/Component/Messenger/Transport/Serialization/Normalizer/FlattenExceptionNormalizer.php @@ -42,6 +42,7 @@ public function normalize($object, $format = null, array $context = []) 'file' => $object->getFile(), 'line' => $object->getLine(), 'previous' => null === $object->getPrevious() ? null : $this->normalize($object->getPrevious(), $format, $context), + 'status_text' => $object->getStatusText(), 'trace' => $object->getTrace(), 'trace_as_string' => $object->getTraceAsString(), ]; @@ -73,6 +74,7 @@ public function denormalize($data, $type, $format = null, array $context = []) $object->setClass($data['class']); $object->setFile($data['file']); $object->setLine($data['line']); + $object->setStatusText($data['status_text']); $object->setHeaders((array) $data['headers']); if (isset($data['previous'])) { diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index b21e99e8961d5..edab34f908f34 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -266,7 +266,7 @@ public function priority(int $priority) */ public function getPriority(): int { - list($priority) = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]'); + [$priority] = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]'); return $priority ?? 3; } diff --git a/src/Symfony/Component/Mime/Part/DataPart.php b/src/Symfony/Component/Mime/Part/DataPart.php index 5d1d91061b35f..213f3c10c8826 100644 --- a/src/Symfony/Component/Mime/Part/DataPart.php +++ b/src/Symfony/Component/Mime/Part/DataPart.php @@ -35,7 +35,7 @@ public function __construct($body, string $filename = null, string $contentType if (null === $contentType) { $contentType = 'application/octet-stream'; } - list($this->mediaType, $subtype) = explode('/', $contentType); + [$this->mediaType, $subtype] = explode('/', $contentType); parent::__construct($body, null, $subtype, $encoding); diff --git a/src/Symfony/Component/Mime/composer.json b/src/Symfony/Component/Mime/composer.json index 58241db64709e..26c8b4a52686f 100644 --- a/src/Symfony/Component/Mime/composer.json +++ b/src/Symfony/Component/Mime/composer.json @@ -17,18 +17,18 @@ ], "require": { "php": ">=7.2.5", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.15", - "symfony/property-access": "^4.4|^5.1", - "symfony/property-info": "^4.4|^5.1", - "symfony/serializer": "^5.2" + "symfony/polyfill-php80": "^1.15" }, "require-dev": { "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^4.4|^5.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.1", + "symfony/property-info": "^4.4|^5.1", + "symfony/serializer": "^5.2" }, "conflict": { "symfony/mailer": "<4.4" diff --git a/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithTransport.php b/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithTransport.php new file mode 100644 index 0000000000000..d46576f46bdca --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithTransport.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Message; + +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\MessageOptionsInterface; + +/** + * @author Jan Schädlich + */ +class DummyMessageWithTransport implements MessageInterface +{ + public function getRecipientId(): ?string + { + return 'recipient_id'; + } + + public function getSubject(): string + { + return 'subject'; + } + + public function getOptions(): ?MessageOptionsInterface + { + return null; + } + + public function getTransport(): ?string + { + return 'transport'; + } +} diff --git a/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithoutTransport.php b/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithoutTransport.php new file mode 100644 index 0000000000000..98d8a98e75014 --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Message/DummyMessageWithoutTransport.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Message; + +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\MessageOptionsInterface; + +/** + * @author Jan Schädlich + */ +class DummyMessageWithoutTransport implements MessageInterface +{ + public function getRecipientId(): ?string + { + return 'recipient_id'; + } + + public function getSubject(): string + { + return 'subject'; + } + + public function getOptions(): ?MessageOptionsInterface + { + return null; + } + + public function getTransport(): ?string + { + return null; + } +} diff --git a/src/Symfony/Component/Notifier/Tests/Message/EmailMessageTest.php b/src/Symfony/Component/Notifier/Tests/Message/EmailMessageTest.php index ae341bfc303bf..44a645aa3b36b 100644 --- a/src/Symfony/Component/Notifier/Tests/Message/EmailMessageTest.php +++ b/src/Symfony/Component/Notifier/Tests/Message/EmailMessageTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Notifier\Tests\Message; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Component/Notifier/Tests/Message/NullMessageTest.php b/src/Symfony/Component/Notifier/Tests/Message/NullMessageTest.php new file mode 100644 index 0000000000000..9213fde3704ff --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Message/NullMessageTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Message; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\NullMessage; + +/** + * @author Jan Schädlich + */ +class NullMessageTest extends TestCase +{ + /** + * @dataProvider messageDataProvider + */ + public function testCanBeConstructed(MessageInterface $message) + { + $nullMessage = new NullMessage($message); + + $this->assertSame($message->getSubject(), $nullMessage->getSubject()); + $this->assertSame($message->getRecipientId(), $nullMessage->getRecipientId()); + $this->assertSame($message->getOptions(), $nullMessage->getOptions()); + + (null === $message->getTransport()) + ? $this->assertSame('null', $nullMessage->getTransport()) + : $this->assertSame($message->getTransport(), $nullMessage->getTransport()); + } + + public function messageDataProvider(): \Generator + { + yield [new DummyMessageWithoutTransport()]; + yield [new DummyMessageWithTransport()]; + } +} diff --git a/src/Symfony/Component/Notifier/Tests/Message/SmsMessageTest.php b/src/Symfony/Component/Notifier/Tests/Message/SmsMessageTest.php index adc3e859cea30..5dd0875a6f86f 100644 --- a/src/Symfony/Component/Notifier/Tests/Message/SmsMessageTest.php +++ b/src/Symfony/Component/Notifier/Tests/Message/SmsMessageTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Notifier\Tests\Message; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Component/Notifier/Tests/Transport/DummyMessage.php b/src/Symfony/Component/Notifier/Tests/Transport/DummyMessage.php new file mode 100644 index 0000000000000..e07592d602844 --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Transport/DummyMessage.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Transport; + +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\MessageOptionsInterface; + +/** + * @author Jan Schädlich + */ +class DummyMessage implements MessageInterface +{ + public function getRecipientId(): ?string + { + return 'recipient_id'; + } + + public function getSubject(): string + { + return 'subject'; + } + + public function getOptions(): ?MessageOptionsInterface + { + return null; + } + + public function getTransport(): ?string + { + return null; + } +} diff --git a/src/Symfony/Component/Notifier/Tests/Transport/NullTransportFactoryTest.php b/src/Symfony/Component/Notifier/Tests/Transport/NullTransportFactoryTest.php new file mode 100644 index 0000000000000..a2682a7957c44 --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Transport/NullTransportFactoryTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; +use Symfony\Component\Notifier\Transport\NullTransport; +use Symfony\Component\Notifier\Transport\NullTransportFactory; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Jan Schädlich + */ +class NullTransportFactoryTest extends TestCase +{ + /** + * @var NullTransportFactory + */ + private $nullTransportFactory; + + protected function setUp(): void + { + $this->nullTransportFactory = new NullTransportFactory( + $this->createMock(EventDispatcherInterface::class), + $this->createMock(HttpClientInterface::class) + ); + } + + public function testCreateThrowsUnsupportedSchemeException() + { + $this->expectException(UnsupportedSchemeException::class); + + $this->nullTransportFactory->create(new Dsn('foo', '')); + } + + public function testCreate() + { + $this->assertInstanceOf( + NullTransport::class, + $this->nullTransportFactory->create(new Dsn('null', '')) + ); + } +} diff --git a/src/Symfony/Component/Notifier/Tests/Transport/NullTransportTest.php b/src/Symfony/Component/Notifier/Tests/Transport/NullTransportTest.php new file mode 100644 index 0000000000000..a1481fb8df119 --- /dev/null +++ b/src/Symfony/Component/Notifier/Tests/Transport/NullTransportTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Transport\NullTransport; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * @author Jan Schädlich + */ +class NullTransportTest extends TestCase +{ + public function testToString() + { + $this->assertEquals('null', (string) (new NullTransport())); + } + + public function testSend() + { + $nullTransport = new NullTransport( + $eventDispatcherMock = $this->createMock(EventDispatcherInterface::class) + ); + + $eventDispatcherMock->expects($this->once())->method('dispatch'); + $nullTransport->send(new DummyMessage()); + } +} diff --git a/src/Symfony/Component/Notifier/composer.json b/src/Symfony/Component/Notifier/composer.json index c0cbbff0199f3..b6e6150d06a24 100644 --- a/src/Symfony/Component/Notifier/composer.json +++ b/src/Symfony/Component/Notifier/composer.json @@ -20,6 +20,10 @@ "symfony/polyfill-php80": "^1.15", "psr/log": "~1.0" }, + "require-dev": { + "symfony/event-dispatcher-contracts": "^2", + "symfony/http-client-contracts": "^2" + }, "conflict": { "symfony/http-kernel": "<4.4", "symfony/firebase-notifier": "<5.2", diff --git a/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php b/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php index 37c1e65846fd1..ae90c6518626d 100755 --- a/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php +++ b/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php @@ -16,7 +16,7 @@ require \dirname(__DIR__).'/vendor/autoload.php'; -list('e' => $php) = getopt('e:') + ['e' => 'php']; +['e' => $php] = getopt('e:') + ['e' => 'php']; try { $process = new Process("exec $php -r \"echo 'ready'; trigger_error('error', E_USER_ERROR);\""); diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 6b525d26846f0..62bffec88f59c 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -476,6 +476,10 @@ public function testTTYCommand() $this->markTestSkipped('Windows does not have /dev/tty support'); } + if (!Process::isTtySupported()) { + $this->markTestSkipped('There is no TTY support'); + } + $process = $this->getProcess('echo "foo" >> /dev/null && '.$this->getProcessForCode('usleep(100000);')->getCommandLine()); $process->setTty(true); $process->start(); @@ -491,6 +495,10 @@ public function testTTYCommandExitCode() $this->markTestSkipped('Windows does have /dev/tty support'); } + if (!Process::isTtySupported()) { + $this->markTestSkipped('There is no TTY support'); + } + $process = $this->getProcess('echo "foo" >> /dev/null'); $process->setTty(true); $process->run(); @@ -1433,16 +1441,7 @@ public function testRawCommandLine() $p = Process::fromShellCommandline(sprintf('"%s" -r %s "a" "" "b"', self::$phpBin, escapeshellarg('print_r($argv);'))); $p->run(); - $expected = << - - [1] => a - [2] => - [3] => b -) - -EOTXT; + $expected = "Array\n(\n [0] => -\n [1] => a\n [2] => \n [3] => b\n)\n"; $this->assertSame($expected, str_replace('Standard input code', '-', $p->getOutput())); } diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 2ed798c98c4d9..d3f046a074ce4 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -224,7 +224,7 @@ private static function throwInvalidArgumentException(string $message, array $tr } if (preg_match('/^\S+::\S+\(\): Argument #\d+ \(\$\S+\) must be of type (\S+), (\S+) given/', $message, $matches)) { - list(, $expectedType, $actualType) = $matches; + [, $expectedType, $actualType] = $matches; throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); } @@ -419,7 +419,7 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid try { $result[self::VALUE] = $object->$name(); } catch (\TypeError $e) { - list($trace) = $e->getTrace(); + [$trace] = $e->getTrace(); // handle uninitialized properties in PHP >= 7 if (__FILE__ === $trace['file'] diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathBuilderTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathBuilderTest.php index 1ae8fdd31d31d..b121a48087df7 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathBuilderTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathBuilderTest.php @@ -20,7 +20,7 @@ */ class PropertyPathBuilderTest extends TestCase { - const PREFIX = 'old1[old2].old3[old4][old5].old6'; + private const PREFIX = 'old1[old2].old3[old4][old5].old6'; /** * @var PropertyPathBuilder diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index f77178a6f0502..5bd733b4e4d6f 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -77,7 +77,7 @@ public function __construct(DocBlockFactoryInterface $docBlockFactory = null, ar public function getShortDescription(string $class, string $property, array $context = []): ?string { /** @var $docBlock DocBlock */ - list($docBlock) = $this->getDocBlock($class, $property); + [$docBlock] = $this->getDocBlock($class, $property); if (!$docBlock) { return null; } @@ -107,7 +107,7 @@ public function getShortDescription(string $class, string $property, array $cont public function getLongDescription(string $class, string $property, array $context = []): ?string { /** @var $docBlock DocBlock */ - list($docBlock) = $this->getDocBlock($class, $property); + [$docBlock] = $this->getDocBlock($class, $property); if (!$docBlock) { return null; } @@ -123,7 +123,7 @@ public function getLongDescription(string $class, string $property, array $conte public function getTypes(string $class, string $property, array $context = []): ?array { /** @var $docBlock DocBlock */ - list($docBlock, $source, $prefix) = $this->getDocBlock($class, $property); + [$docBlock, $source, $prefix] = $this->getDocBlock($class, $property); if (!$docBlock) { return null; } @@ -233,11 +233,11 @@ private function getDocBlock(string $class, string $property): array $data = [$docBlock, self::PROPERTY, null]; break; - case list($docBlock) = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR): + case [$docBlock] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR): $data = [$docBlock, self::ACCESSOR, null]; break; - case list($docBlock, $prefix) = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR): + case [$docBlock, $prefix] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR): $data = [$docBlock, self::MUTATOR, $prefix]; break; diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 4839a691917b2..5287979945af3 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -234,7 +234,7 @@ public function isWritable(string $class, string $property, array $context = []) return true; } - list($reflectionMethod) = $this->getMutatorMethod($class, $property); + [$reflectionMethod] = $this->getMutatorMethod($class, $property); return null !== $reflectionMethod; } @@ -452,7 +452,7 @@ public function getWriteInfo(string $class, string $property, array $context = [ */ private function extractFromMutator(string $class, string $property): ?array { - list($reflectionMethod, $prefix) = $this->getMutatorMethod($class, $property); + [$reflectionMethod, $prefix] = $this->getMutatorMethod($class, $property); if (null === $reflectionMethod) { return null; } @@ -479,7 +479,7 @@ private function extractFromMutator(string $class, string $property): ?array */ private function extractFromAccessor(string $class, string $property): ?array { - list($reflectionMethod, $prefix) = $this->getAccessorMethod($class, $property); + [$reflectionMethod, $prefix] = $this->getAccessorMethod($class, $property); if (null === $reflectionMethod) { return null; } diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index d743299fa02dd..8744a33ce72eb 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -91,7 +91,7 @@ private function createType(DocType $type, bool $nullable, string $docType = nul $docType = $docType ?? (string) $type; if ($type instanceof Collection) { - list($phpType, $class) = $this->getPhpTypeAndClass((string) $type->getFqsen()); + [$phpType, $class] = $this->getPhpTypeAndClass((string) $type->getFqsen()); $key = $this->getTypes($type->getKeyType()); $value = $this->getTypes($type->getValueType()); @@ -133,7 +133,7 @@ private function createType(DocType $type, bool $nullable, string $docType = nul } $docType = $this->normalizeType($docType); - list($phpType, $class) = $this->getPhpTypeAndClass($docType); + [$phpType, $class] = $this->getPhpTypeAndClass($docType); if ('array' === $docType) { return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, null, null); diff --git a/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php b/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php index b10edce4e9249..90ce5b2906880 100644 --- a/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php +++ b/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php @@ -50,7 +50,7 @@ public function generate(string $name, array $parameters = [], int $referenceTyp throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } - list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name]; + [$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes] = $this->compiledRoutes[$name]; if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { if (!\in_array('_locale', $variables, true)) { diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index e64089fb30a9a..dbff4a87b37c0 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -118,7 +118,7 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $node, st $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY); $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY); - list($defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts) = $this->parseConfigs($node, $path); + [$defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts] = $this->parseConfigs($node, $path); if (!$paths && '' === $node->getAttribute('path')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path)); @@ -163,7 +163,7 @@ protected function parseImport(RouteCollection $collection, \DOMElement $node, s $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; $namePrefix = $node->getAttribute('name-prefix') ?: null; - list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts) = $this->parseConfigs($node, $path); + [$defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts] = $this->parseConfigs($node, $path); if ('' !== $prefix && $prefixes) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path)); diff --git a/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php index e15cda7786585..ae13fd7011e37 100644 --- a/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php @@ -26,6 +26,6 @@ class CompiledUrlMatcher extends UrlMatcher public function __construct(array $compiledRoutes, RequestContext $context) { $this->context = $context; - list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes; + [$this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition] = $compiledRoutes; } } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php index 73e2e1e0a06af..e77d24aecf9c1 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php @@ -83,7 +83,7 @@ public function getCompiledRoutes(bool $forDump = false): array $routes = $this->getRoutes(); } - list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); + [$staticRoutes, $dynamicRoutes] = $this->groupStaticRoutes($routes); $conditions = [null]; $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); @@ -131,7 +131,7 @@ static function (\$condition, \$context, \$request) { // \$checkCondition private function generateCompiledRoutes(): string { - list($matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode) = $this->getCompiledRoutes(true); + [$matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode] = $this->getCompiledRoutes(true); $code = self::export($matchHost).', // $matchHost'."\n"; @@ -186,7 +186,7 @@ private function groupStaticRoutes(RouteCollection $collection): array if ($hasTrailingSlash) { $url = substr($url, 0, -1); } - foreach ($dynamicRegex as list($hostRx, $rx, $prefix)) { + foreach ($dynamicRegex as [$hostRx, $rx, $prefix]) { if (('' === $prefix || 0 === strpos($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; $dynamicRoutes->add($name, $route); @@ -221,7 +221,7 @@ private function compileStaticRoutes(array $staticRoutes, array &$conditions): a foreach ($staticRoutes as $url => $routes) { $compiledRoutes[$url] = []; - foreach ($routes as $name => list($route, $hasTrailingSlash)) { + foreach ($routes as $name => [$route, $hasTrailingSlash]) { $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); } } @@ -287,7 +287,7 @@ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHo $routes->add($name, $route); } - foreach ($perModifiers as list($modifiers, $routes)) { + foreach ($perModifiers as [$modifiers, $routes]) { $prev = false; $perHost = []; foreach ($routes->all() as $name => $route) { @@ -306,7 +306,7 @@ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHo $state->mark += \strlen($rx); $state->regex = $rx; - foreach ($perHost as list($hostRegex, $routes)) { + foreach ($perHost as [$hostRegex, $routes]) { if ($matchHost) { if ($hostRegex) { preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); @@ -391,7 +391,7 @@ private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \st continue; } - list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; + [$name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar] = $route; $compiledRoute = $route->compile(); $vars = array_merge($state->hostVars, $vars); diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php index caba4e5c6287c..79cdc2b48ab61 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php @@ -87,7 +87,7 @@ private function doMatch(string $pathinfo, array &$allow = [], array &$allowSche } $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; - foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as list($ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition)) { + foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as [$ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition]) { if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { continue; } @@ -127,7 +127,7 @@ private function doMatch(string $pathinfo, array &$allow = [], array &$allowSche foreach ($this->regexpList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { - foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition)) { + foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as [$ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition]) { if (null !== $condition) { if (0 === $condition) { // marks the last route in the regexp continue 3; diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php index 65b6c0718b316..1c5c5fdeb0c99 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php @@ -65,12 +65,12 @@ public function getRoutes(): array */ public function addRoute(string $prefix, $route) { - list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix); + [$prefix, $staticPrefix] = $this->getCommonPrefix($prefix, $prefix); for ($i = \count($this->items) - 1; 0 <= $i; --$i) { $item = $this->items[$i]; - list($commonPrefix, $commonStaticPrefix) = $this->getCommonPrefix($prefix, $this->prefixes[$i]); + [$commonPrefix, $commonStaticPrefix] = $this->getCommonPrefix($prefix, $this->prefixes[$i]); if ($this->prefix === $commonPrefix) { // the new route and a previous one have no common prefix, let's see if they are exclusive to each others @@ -104,8 +104,8 @@ public function addRoute(string $prefix, $route) } else { // the new route and a previous one have a common prefix, let's merge them $child = new self($commonPrefix); - list($child->prefixes[0], $child->staticPrefixes[0]) = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); - list($child->prefixes[1], $child->staticPrefixes[1]) = $child->getCommonPrefix($prefix, $prefix); + [$child->prefixes[0], $child->staticPrefixes[0]] = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); + [$child->prefixes[1], $child->staticPrefixes[1]] = $child->getCommonPrefix($prefix, $prefix); $child->items = [$this->items[$i], $route]; $this->staticPrefixes[$i] = $commonStaticPrefix; diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php index fe5014fc80007..36b2756690cdb 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php @@ -16,7 +16,7 @@ public function testGrouping(array $routes, $expected) $collection = new StaticPrefixCollection('/'); foreach ($routes as $route) { - list($path, $name) = $route; + [$path, $name] = $route; $staticPrefix = (new Route($path))->compile()->getStaticPrefix(); $collection->addRoute($staticPrefix, [$name]); } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php index 218d750b8e097..779109039bfe6 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php @@ -30,7 +30,7 @@ public function getToken(); /** * Sets the authentication token. * - * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored + * @param TokenInterface|null $token A TokenInterface token, or null if no further authentication information should be stored */ public function setToken(TokenInterface $token = null); } diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.af.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.af.xlf new file mode 100644 index 0000000000000..4fc8b1426e381 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.af.xlf @@ -0,0 +1,75 @@ + + + + + + An authentication exception occurred. + 'n Verifikasie probleem het voorgekom. + + + Authentication credentials could not be found. + Verifikasiebewyse kon nie gevind word nie. + + + Authentication request could not be processed due to a system problem. + Verifikasieversoek kon weens 'n stelselprobleem nie verwerk word nie. + + + Invalid credentials. + Ongedige verifikasiebewyse. + + + Cookie has already been used by someone else. + Die koekie is alreeds deur iemand anders gebruik. + + + Not privileged to request the resource. + Nie bevoorreg om die hulpbron aan te vra nie. + + + Invalid CSRF token. + Ongeldige CSRF-teken. + + + No authentication provider found to support the authentication token. + Geen verifikasieverskaffer is gevind wat die verifikasietoken kan ondersteun nie. + + + No session available, it either timed out or cookies are not enabled. + Geen sessie is beskikbaar, die het verval of koekies is nie geaktiveer nie. + + + No token could be found. + Geen teken kon gevind word nie. + + + Username could not be found. + Gebruikersnaam kon nie gevind word nie. + + + Account has expired. + Rekening het verval. + + + Credentials have expired. + Verifikasiebewyse het verval. + + + Account is disabled. + Rekening is deaktiveer. + + + Account is locked. + Rekening is gesluit. + + + Too many failed login attempts, please try again later. + Te veel mislukte aanmeldpogings, probeer asseblief later weer. + + + Invalid or expired login link. + Ongeldige of vervalde aanmeldskakel. + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf index d9d5425cefb9c..735de0786567c 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf @@ -62,6 +62,14 @@ Account is locked. Hesab kilitlənib. + + Too many failed login attempts, please try again later. + Çoxlu uğursuz giriş təşəbbüsü, zəhmət olmasa daha sonra yeniden yoxlayın. + + + Invalid or expired login link. + Yanlış və ya müddəti keçmiş giriş keçidi. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.bs.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.bs.xlf new file mode 100644 index 0000000000000..2eae0ff22ec62 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.bs.xlf @@ -0,0 +1,75 @@ + + + + + + An authentication exception occurred. + Došlo je do autentifikacijskog izuzetka (exception). + + + Authentication credentials could not be found. + Autentifikacijski podaci nisu pronađeni. + + + Authentication request could not be processed due to a system problem. + Autentifikacijski zahtjev ne može biti obrađen zbog sistemskog problema. + + + Invalid credentials. + Autentifikacijski podaci su neispravni. + + + Cookie has already been used by someone else. + Neko drugi je već iskoristio ovaj kolačić (cookie). + + + Not privileged to request the resource. + Nemate privilegije potrebne za pristup ovom resursu. + + + Invalid CSRF token. + CSRF žeton (token) je neispravan. + + + No authentication provider found to support the authentication token. + Nije pronađen autentifikacijski provajder koji bi podržao dati autentifikacijski žeton (token). + + + No session available, it either timed out or cookies are not enabled. + Nema dostupnih sesija; ili je istekla ili su kolačići (cookies) iksljučeni. + + + No token could be found. + Nije pronađen nijedan žeton (token). + + + Username could not be found. + Korisničko ime nije pronađeno. + + + Account has expired. + Nalog je istekao. + + + Credentials have expired. + Autentifikacijski podaci su istekli. + + + Account is disabled. + Nalog je onemogućen. + + + Account is locked. + Nalog je zaključan. + + + Too many failed login attempts, please try again later. + Previše neuspješnih pokušaja prijavljivanja, molim pokušajte ponovo kasnije. + + + Invalid or expired login link. + Link za prijavljivanje je istekao ili je neispravan. + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf index b009c6205c362..5a8d0c7d84880 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf @@ -62,6 +62,14 @@ Account is locked. El compte està bloquejat. + + Too many failed login attempts, please try again later. + Massa intents d'inici de sessió fallits, torneu-ho a provar més tard. + + + Invalid or expired login link. + Enllaç d'inici de sessió no vàlid o caducat. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf index 183ebe83e71dd..c83d27c5e0b59 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf @@ -8,7 +8,7 @@ Authentication credentials could not be found. - Loginoplysninger kan findes. + Loginoplysninger kan ikke findes. Authentication request could not be processed due to a system problem. @@ -62,6 +62,14 @@ Account is locked. Brugerkonto er låst. + + Too many failed login attempts, please try again later. + For mange fejlede login forsøg, prøv venligst senere. + + + Invalid or expired login link. + Ugyldigt eller udløbet login link. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf index 02393d0805252..724cc4e5d1603 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf @@ -62,6 +62,14 @@ Account is locked. Ο λογαριασμός είναι κλειδωμένος. + + Too many failed login attempts, please try again later. + Πολλαπλές αποτυχημένες απόπειρες σύνδεσης, παρακαλούμε ξαναδοκιμάστε αργότερα. + + + Invalid or expired login link. + Μη έγκυρος ή ληγμένος σύνδεσμος σύνδεσης. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.fi.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.fi.xlf index d5358a6c1700c..7b8d232cdd9a9 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.fi.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.fi.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Virheellinen CSRF tunnus. - - Digest nonce has expired. - Digest nonce on vanhentunut. - No authentication provider found to support the authentication token. Autentikointi tunnukselle ei löydetty tuettua autentikointi tarjoajaa. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf index ddc838e66af8b..651810d452cb6 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf @@ -62,6 +62,14 @@ Account is locked. A conta está bloqueada. + + Too many failed login attempts, please try again later. + Demasiados intentos de inicio de sesión fallados. Téntao de novo máis tarde. + + + Invalid or expired login link. + Ligazón de inicio de sesión non válida ou caducada. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf index f30b68eddf1fc..adbb6cfd6ae00 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf @@ -8,7 +8,7 @@ Authentication credentials could not be found. - Authentication credentials could not be found. + פרטי זיהוי לא נמצאו. Authentication request could not be processed due to a system problem. @@ -16,23 +16,23 @@ Invalid credentials. - שם משתמש או סיסמא שגויים + שם משתמש או סיסמא שגויים. Cookie has already been used by someone else. - Cookie has already been used by someone else. + עוגיה כבר שומשה. Not privileged to request the resource. - Not privileged to request the resource. + אין הרשאה מתאימה. Invalid CSRF token. - Invalid CSRF token. + אסימון CSRF לא חוקי. No authentication provider found to support the authentication token. - No authentication provider found to support the authentication token. + לא נמצא ספק אימות המתאימה לבקשה. No session available, it either timed out or cookies are not enabled. @@ -40,11 +40,11 @@ No token could be found. - No token could be found. + הטוקן לא נמצא. Username could not be found. - שם משתמש לא נמצא במערכת + שם משתמש לא נמצא. Account has expired. @@ -52,7 +52,7 @@ Credentials have expired. - פרטי התחברות פקעו תוקף + פרטי התחברות פקעו תוקף. Account is disabled. @@ -62,6 +62,14 @@ Account is locked. החשבון נעול. + + Too many failed login attempts, please try again later. + יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב מאוחר יותר. + + + Invalid or expired login link. + קישור כניסה לא חוקי או שפג תוקפו. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf index f3a163904d367..e27a7b4505c53 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf @@ -62,6 +62,14 @@ Account is locked. Zárolt fiók. + + Too many failed login attempts, please try again later. + Túl sok sikertelen bejelentkezési kísérlet, kérjük próbálja újra később. + + + Invalid or expired login link. + Érvénytelen vagy lejárt bejelentkezési link. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf index b7909033a6e67..37487b79d71b4 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf @@ -62,6 +62,14 @@ Account is locked. Paskyra yra užblokuota. + + Too many failed login attempts, please try again later. + Per daug nepavykusių prisijungimo bandymų, pabandykite dar kartą vėliau. + + + Invalid or expired login link. + Netinkama arba pasibaigusio galiojimo laiko prisijungimo nuoroda. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.mn.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.mn.xlf new file mode 100644 index 0000000000000..7310e660a4479 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.mn.xlf @@ -0,0 +1,75 @@ + + + + + + An authentication exception occurred. + Нэвтрэх хүсэлтийн алдаа гарав. + + + Authentication credentials could not be found. + Нэвтрэх эрхийн мэдээлэл олдсонгүй. + + + Authentication request could not be processed due to a system problem. + Системийн алдаанаас болон нэвтрэх хүсэлтийг гүйцэтгэх боломжгүй байна. + + + Invalid credentials. + Буруу нэвтрэх эрхийн мэдээлэл. + + + Cookie has already been used by someone else. + Күүки файлыг аль хэдийн өөр хүн хэрэглэж байна. + + + Not privileged to request the resource. + Энэхүү мэдээллийг авах эрх хүрэхгүй байна. + + + Invalid CSRF token. + Тохиромжгүй CSRF токен. + + + No authentication provider found to support the authentication token. + Нэвтрэх токенг дэмжих нэвтрэх эрхийн хангагч олдсонгүй. + + + No available, it either timed out or cookies are not enabled. + Хэрэглэгчийн session олдсонгүй, хугацаа нь дууссан эсвэл күүки идэвхижүүлээгүй байна. + + + No token could be found. + Токен олдсонгүй. + + + Username could not be found. + Нэвтрэх нэр олсонгүй. + + + Account has expired. + Бүртгэлийн хугацаа дууссан байна. + + + Credentials have expired. + Нэвтрэх эрхийн хугацаа дууссан байна. + + + Account is disabled. + Бүртгэлийг хаасан байна. + + + Account is locked. + Бүртгэлийг цоожилсон байна. + + + Too many failed login attempts, please try again later. + Хэтэрхий олон амжилтгүй оролдлого, түр хүлээгээд дахин оролдоно уу. + + + Invalid or expired login link. + Буруу эсвэл хугацаа нь дууссан нэвтрэх зам. + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.nb.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.nb.xlf index 57016a4a4c23f..2d3a87c793ddf 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.nb.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.nb.xlf @@ -62,6 +62,14 @@ Account is locked. Brukerkonto er sperret. + + Too many failed login attempts, please try again later. + For mange mislykkede påloggingsforsøk. Prøv igjen senere. + + + Invalid or expired login link. + Ugyldig eller utløpt påloggingskobling. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf index 57016a4a4c23f..2d3a87c793ddf 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf @@ -62,6 +62,14 @@ Account is locked. Brukerkonto er sperret. + + Too many failed login attempts, please try again later. + For mange mislykkede påloggingsforsøk. Prøv igjen senere. + + + Invalid or expired login link. + Ugyldig eller utløpt påloggingskobling. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.pt.xlf similarity index 100% rename from src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf rename to src/Symfony/Component/Security/Core/Resources/translations/security.pt.xlf diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sq.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sq.xlf index 4f4bc6d4cbc61..03e13708af4b9 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sq.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sq.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Identifikues i pavlefshëm CSRF. - - Digest nonce has expired. - Numeri një perdorimësh i verifikimit Digest ka skaduar. - No authentication provider found to support the authentication token. Asnjë ofrues i vërtetimit nuk u gjet që të mbështesë simbolin e vërtetimit. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf index f677254cce202..92ba9004aa8b1 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf @@ -62,6 +62,14 @@ Account is locked. Налог је закључан. + + Too many failed login attempts, please try again later. + Превише неуспешних покушаја пријављивања, молим покушајте поново касније. + + + Invalid or expired login link. + Линк за пријављивање је истекао или је неисправан. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf index a38c75a9f810f..219281d66ecc7 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf @@ -62,6 +62,14 @@ Account is locked. Nalog je zaključan. + + Too many failed login attempts, please try again later. + Previše neuspešnih pokušaja prijavljivanja, molim pokušajte ponovo kasnije. + + + Invalid or expired login link. + Link za prijavljivanje je istekao ili je neispravan. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf index 84ae66769c611..2b2f1e068ba76 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf @@ -62,6 +62,14 @@ Account is locked. บัญชีถูกล็อกแล้ว + + Too many failed login attempts, please try again later. + มีความพยายามเข้าสู่ระบบล้มเหลวมากเกินไป กรุณาลองใหม่ภายหลัง + + + Invalid or expired login link. + ลิงค์เข้าสู่ระบบไม่ถูกต้องหรือหมดอายุไปแล้ว + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf index d80cf88de1c8a..5bf5304b5cae1 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf @@ -48,19 +48,27 @@ Account has expired. - Ang akawnt ay nag-expire na. + Ang account ay nag-expire na. Credentials have expired. - .ng mga kinakailangang dokumento ay nag expire na. + Ang mga kinakailangang dokumento ay nag expire na. Account is disabled. - Ang akawnt ay hindi pinagana. + Ang account ay hindi pinagana. Account is locked. - ng akawnt ay nakasara. + Ang account ay nakasara. + + + Too many failed login attempts, please try again later. + Madaming bagsak na pagtatangka, pakisubukan ulit mamaya. + + + Invalid or expired login link. + Inbalido o nagexpire na ang link para makapaglogin. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.zh_TW.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.zh_TW.xlf index 7085206440528..86310473180b1 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.zh_TW.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.zh_TW.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. 無效的 CSRF token 。 - - Digest nonce has expired. - 摘要隨機串(digest nonce)已過期。 - No authentication provider found to support the authentication token. 沒有找到支持此 token 的身份驗證服務提供方。 diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php index f9e157c6978e0..cad08eb9e8753 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php @@ -40,7 +40,7 @@ public function testDecideLog(array $expectedLog, array $attributes, $object, ar ->with($token, $attributes, $object) ->willReturnCallback(function ($token, $attributes, $object) use ($voterVotes, $adm, $result) { foreach ($voterVotes as $voterVote) { - list($voter, $vote) = $voterVote; + [$voter, $vote] = $voterVote; $adm->addVoterVote($voter, $attributes, $vote); } diff --git a/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php index c45b5a0d36338..2402b0199824f 100644 --- a/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Tests\Resources; use PHPUnit\Framework\TestCase; -use PHPUnit\Util\Xml\Loader; +use Symfony\Component\Translation\Util\XliffUtils; class TranslationFilesTest extends TestCase { @@ -21,13 +21,12 @@ class TranslationFilesTest extends TestCase */ public function testTranslationFileIsValid($filePath) { - $loader = class_exists(Loader::class) - ? [new Loader(), 'loadFile'] - : ['PHPUnit\Util\XML', 'loadfile']; + $document = new \DOMDocument(); + $document->loadXML(file_get_contents($filePath)); - $loader($filePath, false, false, true); + $errors = XliffUtils::validateSchema($document); - $this->addToAssertionCount(1); + $this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php index 9fd1438446544..8e956c3848bbf 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php @@ -57,12 +57,12 @@ public function testAttributes() $metadata = new ClassMetadata(UserPasswordDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UserPasswordDummy'], $bConstraint->groups); self::assertNull($bConstraint->payload); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php index f5d29e96dfc0e..460e118ece308 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php @@ -23,8 +23,8 @@ */ abstract class UserPasswordValidatorTest extends ConstraintValidatorTestCase { - const PASSWORD = 's3Cr3t'; - const SALT = '^S4lt$'; + private const PASSWORD = 's3Cr3t'; + private const SALT = '^S4lt$'; /** * @var TokenStorageInterface diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index de5b855a54b2e..3d74c1c73dcea 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -28,6 +28,7 @@ "symfony/expression-language": "^4.4|^5.0", "symfony/http-foundation": "^4.4|^5.0", "symfony/ldap": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", "symfony/validator": "^5.2", "psr/log": "~1.0" }, diff --git a/src/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php b/src/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php index 34dc1698b9695..1703397274433 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php @@ -177,28 +177,28 @@ public function getManagerGeneratorAndStorage() { $data = []; - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['', new CsrfTokenManager($generator, $storage, ''), $storage, $generator]; - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['https-', new CsrfTokenManager($generator, $storage), $storage, $generator]; - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['aNamespace-', new CsrfTokenManager($generator, $storage, 'aNamespace-'), $storage, $generator]; $requestStack = new RequestStack(); $requestStack->push(new Request([], [], [], [], [], ['HTTPS' => 'on'])); - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['https-', new CsrfTokenManager($generator, $storage, $requestStack), $storage, $generator]; - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['generated-', new CsrfTokenManager($generator, $storage, function () { return 'generated-'; }), $storage, $generator]; $requestStack = new RequestStack(); $requestStack->push(new Request()); - list($generator, $storage) = $this->getGeneratorAndStorage(); + [$generator, $storage] = $this->getGeneratorAndStorage(); $data[] = ['', new CsrfTokenManager($generator, $storage, $requestStack), $storage, $generator]; return $data; diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php index dc97acc239ddc..ad545aa784bcc 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php @@ -19,7 +19,7 @@ */ class UriSafeTokenGeneratorTest extends TestCase { - const ENTROPY = 1000; + private const ENTROPY = 1000; /** * A non alpha-numeric byte string. diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php index ead39789979b1..5acbedc6e9335 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php @@ -22,7 +22,7 @@ */ class NativeSessionTokenStorageTest extends TestCase { - const SESSION_NAMESPACE = 'foobar'; + private const SESSION_NAMESPACE = 'foobar'; /** * @var NativeSessionTokenStorage diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php index 7ddd965e51d7b..af5b0ebc8b779 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php @@ -21,7 +21,7 @@ */ class SessionTokenStorageTest extends TestCase { - const SESSION_NAMESPACE = 'foobar'; + private const SESSION_NAMESPACE = 'foobar'; /** * @var Session diff --git a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php index 3d1fc8a4bcfb3..1e6d9d89952c4 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php @@ -29,9 +29,8 @@ class FormLoginAuthenticatorTest extends TestCase private $requestWithSession; private $authenticator; - const LOGIN_URL = 'http://login'; - const DEFAULT_SUCCESS_URL = 'http://defaultsuccess'; - const CUSTOM_SUCCESS_URL = 'http://customsuccess'; + private const LOGIN_URL = 'http://login'; + private const DEFAULT_SUCCESS_URL = 'http://defaultsuccess'; public function testAuthenticationFailureWithoutSession() { diff --git a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php index 243faecbc083b..9c89d4376d0f9 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php @@ -43,7 +43,7 @@ public function __construct(AccessMapInterface $map, AuthenticationEntryPointInt */ public function supports(Request $request): ?bool { - list(, $channel) = $this->map->getPatterns($request); + [, $channel] = $this->map->getPatterns($request); if ('https' === $channel && !$request->isSecure()) { if (null !== $this->logger) { diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 50d14a4f70f8d..59737af176cc8 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -84,7 +84,7 @@ public function setCurrentFirewall(?string $key, string $context = null) */ private function generateLogoutUrl(?string $key, int $referenceType): string { - list($logoutPath, $csrfTokenId, $csrfParameter, $csrfTokenManager) = $this->getListener($key); + [$logoutPath, $csrfTokenId, $csrfParameter, $csrfTokenManager] = $this->getListener($key); if (null === $logoutPath) { throw new \LogicException('Unable to generate the logout URL without a path.'); @@ -152,7 +152,7 @@ private function getListener(?string $key): array } // Fetch from injected current firewall information, if possible - list($key, $context) = $this->currentFirewall; + [$key, $context] = $this->currentFirewall; if (isset($this->listeners[$key])) { return $this->listeners[$key]; diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index bd51ca4cae651..5711f0f5acca8 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -52,7 +52,7 @@ protected function cancelCookie(Request $request) if (null !== ($cookie = $request->cookies->get($this->options['name'])) && 2 === \count($parts = $this->decodeCookie($cookie)) ) { - list($series) = $parts; + [$series] = $parts; $this->tokenProvider->deleteTokenBySeries($series); } } @@ -66,7 +66,7 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request) throw new AuthenticationException('The cookie is invalid.'); } - list($series, $tokenValue) = $cookieParts; + [$series, $tokenValue] = $cookieParts; $persistentToken = $this->tokenProvider->loadTokenBySeries($series); if (!$this->isTokenValueValid($persistentToken, $tokenValue)) { diff --git a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php index 38d3a4cce2af9..80e0b058157e2 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php @@ -35,7 +35,7 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request) throw new AuthenticationException('The cookie is invalid.'); } - list($class, $username, $expires, $hash) = $cookieParts; + [$class, $username, $expires, $hash] = $cookieParts; if (false === $username = base64_decode($username, true)) { throw new AuthenticationException('$username contains a character from outside the base64 alphabet.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php index 76a975d0baeaf..109c841af76d3 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php @@ -28,9 +28,9 @@ class LogoutListenerTest extends TestCase public function testHandleUnmatchedPath() { $dispatcher = $this->getEventDispatcher(); - list($listener, , $httpUtils, $options) = $this->getListener($dispatcher); + [$listener, , $httpUtils, $options] = $this->getListener($dispatcher); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $logoutEventDispatched = false; $dispatcher->addListener(LogoutEvent::class, function (LogoutEvent $event) use (&$logoutEventDispatched) { @@ -52,9 +52,9 @@ public function testHandleMatchedPathWithCsrfValidation() $tokenManager = $this->getTokenManager(); $dispatcher = $this->getEventDispatcher(); - list($listener, $tokenStorage, $httpUtils, $options) = $this->getListener($dispatcher, $tokenManager); + [$listener, $tokenStorage, $httpUtils, $options] = $this->getListener($dispatcher, $tokenManager); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $request->query->set('_csrf_token', 'token'); @@ -90,9 +90,9 @@ public function testHandleMatchedPathWithCsrfValidation() public function testHandleMatchedPathWithoutCsrfValidation() { $dispatcher = $this->getEventDispatcher(); - list($listener, $tokenStorage, $httpUtils, $options) = $this->getListener($dispatcher); + [$listener, $tokenStorage, $httpUtils, $options] = $this->getListener($dispatcher); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') @@ -123,9 +123,9 @@ public function testNoResponseSet() { $this->expectException('RuntimeException'); - list($listener, , $httpUtils, $options) = $this->getListener(); + [$listener, , $httpUtils, $options] = $this->getListener(); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') @@ -140,9 +140,9 @@ public function testCsrfValidationFails() $this->expectException('Symfony\Component\Security\Core\Exception\LogoutException'); $tokenManager = $this->getTokenManager(); - list($listener, , $httpUtils, $options) = $this->getListener(null, $tokenManager); + [$listener, , $httpUtils, $options] = $this->getListener(null, $tokenManager); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $request->query->set('_csrf_token', 'token'); @@ -168,12 +168,12 @@ public function testLegacyLogoutHandlers() $this->expectDeprecation('Since symfony/security-http 5.1: Calling "%s::addHandler" is deprecated, register a listener on the "%s" event instead.'); $logoutSuccessHandler = $this->createMock(LogoutSuccessHandlerInterface::class); - list($listener, $tokenStorage, $httpUtils, $options) = $this->getListener($logoutSuccessHandler); + [$listener, $tokenStorage, $httpUtils, $options] = $this->getListener($logoutSuccessHandler); $token = $this->getToken(); $tokenStorage->expects($this->any())->method('getToken')->willReturn($token); - list($event, $request) = $this->getGetResponseEvent(); + [$event, $request] = $this->getGetResponseEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php index d321ed68921bd..2dccec5b9acff 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php @@ -25,7 +25,7 @@ class RememberMeListenerTest extends TestCase { public function testOnCoreSecurityDoesNotTryToPopulateNonEmptyTokenStorage() { - list($listener, $tokenStorage) = $this->getListener(); + [$listener, $tokenStorage] = $this->getListener(); $tokenStorage ->expects($this->any()) @@ -43,7 +43,7 @@ public function testOnCoreSecurityDoesNotTryToPopulateNonEmptyTokenStorage() public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() { - list($listener, $tokenStorage, $service) = $this->getListener(); + [$listener, $tokenStorage, $service] = $this->getListener(); $tokenStorage ->expects($this->any()) @@ -64,7 +64,7 @@ public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation() { - list($listener, $tokenStorage, $service, $manager) = $this->getListener(); + [$listener, $tokenStorage, $service, $manager] = $this->getListener(); $request = new Request(); $exception = new AuthenticationException('Authentication failed.'); @@ -101,7 +101,7 @@ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExcepti { $this->expectException('Symfony\Component\Security\Core\Exception\AuthenticationException'); $this->expectExceptionMessage('Authentication failed.'); - list($listener, $tokenStorage, $service, $manager) = $this->getListener(false, false); + [$listener, $tokenStorage, $service, $manager] = $this->getListener(false, false); $tokenStorage ->expects($this->any()) @@ -134,7 +134,7 @@ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExcepti public function testOnCoreSecurityAuthenticationExceptionDuringAutoLoginTriggersLoginFail() { - list($listener, $tokenStorage, $service, $manager) = $this->getListener(); + [$listener, $tokenStorage, $service, $manager] = $this->getListener(); $tokenStorage ->expects($this->any()) @@ -166,7 +166,7 @@ public function testOnCoreSecurityAuthenticationExceptionDuringAutoLoginTriggers public function testOnCoreSecurity() { - list($listener, $tokenStorage, $service, $manager) = $this->getListener(); + [$listener, $tokenStorage, $service, $manager] = $this->getListener(); $tokenStorage ->expects($this->any()) @@ -200,7 +200,7 @@ public function testOnCoreSecurity() public function testSessionStrategy() { - list($listener, $tokenStorage, $service, $manager, , , $sessionStrategy) = $this->getListener(false, true, true); + [$listener, $tokenStorage, $service, $manager, , , $sessionStrategy] = $this->getListener(false, true, true); $tokenStorage ->expects($this->any()) @@ -250,7 +250,7 @@ public function testSessionStrategy() public function testSessionIsMigratedByDefault() { - list($listener, $tokenStorage, $service, $manager) = $this->getListener(false, true, false); + [$listener, $tokenStorage, $service, $manager] = $this->getListener(false, true, false); $tokenStorage ->expects($this->any()) @@ -298,7 +298,7 @@ public function testSessionIsMigratedByDefault() public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent() { - list($listener, $tokenStorage, $service, $manager, , $dispatcher) = $this->getListener(true); + [$listener, $tokenStorage, $service, $manager, , $dispatcher] = $this->getListener(true); $tokenStorage ->expects($this->any()) diff --git a/src/Symfony/Component/Security/Http/Tests/FirewallMapTest.php b/src/Symfony/Component/Security/Http/Tests/FirewallMapTest.php index c464a4da3ccaf..50675a6003425 100644 --- a/src/Symfony/Component/Security/Http/Tests/FirewallMapTest.php +++ b/src/Symfony/Component/Security/Http/Tests/FirewallMapTest.php @@ -53,7 +53,7 @@ public function testGetListeners() $map->add($tooLateMatcher, [function () {}]); - list($listeners, $exception) = $map->getListeners($request); + [$listeners, $exception] = $map->getListeners($request); $this->assertEquals([$theListener], $listeners); $this->assertEquals($theException, $exception); @@ -88,7 +88,7 @@ public function testGetListenersWithAnEntryHavingNoRequestMatcher() $map->add($tooLateMatcher, [function () {}]); - list($listeners, $exception) = $map->getListeners($request); + [$listeners, $exception] = $map->getListeners($request); $this->assertEquals([$theListener], $listeners); $this->assertEquals($theException, $exception); @@ -110,7 +110,7 @@ public function testGetListenersWithNoMatchingEntry() $map->add($notMatchingMatcher, [function () {}]); - list($listeners, $exception) = $map->getListeners($request); + [$listeners, $exception] = $map->getListeners($request); $this->assertEquals([], $listeners); $this->assertNull($exception); diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 523bbdaa47d6b..631defab32764 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -81,7 +81,7 @@ public function encode($data, string $format, array $context = []) } } - list($delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom) = $this->getCsvOptions($context); + [$delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom] = $this->getCsvOptions($context); foreach ($data as &$value) { $flattened = []; @@ -142,7 +142,7 @@ public function decode(string $data, string $format, array $context = []) $headerCount = []; $result = []; - list($delimiter, $enclosure, $escapeChar, $keySeparator, , , , $asCollection) = $this->getCsvOptions($context); + [$delimiter, $enclosure, $escapeChar, $keySeparator, , , , $asCollection] = $this->getCsvOptions($context); while (false !== ($cols = fgetcsv($handle, 0, $delimiter, $enclosure, $escapeChar))) { $nbCols = \count($cols); diff --git a/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php b/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php index a515b2002d9ca..63c3479a74ebe 100644 --- a/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php @@ -28,9 +28,17 @@ class YamlEncoder implements EncoderInterface, DecoderInterface public const PRESERVE_EMPTY_OBJECTS = 'preserve_empty_objects'; + public const YAML_INLINE = 'yaml_inline'; + public const YAML_INDENT = 'yaml_indent'; + public const YAML_FLAGS = 'yaml_flags'; + private $dumper; private $parser; - private $defaultContext = ['yaml_inline' => 0, 'yaml_indent' => 0, 'yaml_flags' => 0]; + private $defaultContext = [ + self::YAML_INLINE => 0, + self::YAML_INDENT => 0, + self::YAML_FLAGS => 0, + ]; public function __construct(Dumper $dumper = null, Parser $parser = null, array $defaultContext = []) { @@ -51,10 +59,10 @@ public function encode($data, string $format, array $context = []) $context = array_merge($this->defaultContext, $context); if (isset($context[self::PRESERVE_EMPTY_OBJECTS])) { - $context['yaml_flags'] |= Yaml::DUMP_OBJECT_AS_MAP; + $context[self::YAML_FLAGS] |= Yaml::DUMP_OBJECT_AS_MAP; } - return $this->dumper->dump($data, $context['yaml_inline'], $context['yaml_indent'], $context['yaml_flags']); + return $this->dumper->dump($data, $context[self::YAML_INLINE], $context[self::YAML_INDENT], $context[self::YAML_FLAGS]); } /** @@ -72,7 +80,7 @@ public function decode(string $data, string $format, array $context = []) { $context = array_merge($this->defaultContext, $context); - return $this->parser->parse($data, $context['yaml_flags']); + return $this->parser->parse($data, $context[self::YAML_FLAGS]); } /** diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php index 301b43586970a..215e73386176a 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php @@ -16,9 +16,9 @@ class ChainDecoderTest extends TestCase { - const FORMAT_1 = 'format1'; - const FORMAT_2 = 'format2'; - const FORMAT_3 = 'format3'; + private const FORMAT_1 = 'format1'; + private const FORMAT_2 = 'format2'; + private const FORMAT_3 = 'format3'; private $chainDecoder; private $decoder1; diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php index f2e41ad28d4b6..e1f029b7157e9 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php @@ -18,9 +18,9 @@ class ChainEncoderTest extends TestCase { - const FORMAT_1 = 'format1'; - const FORMAT_2 = 'format2'; - const FORMAT_3 = 'format3'; + private const FORMAT_1 = 'format1'; + private const FORMAT_2 = 'format2'; + private const FORMAT_3 = 'format3'; private $chainEncoder; private $encoder1; diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php index 27b98eabb9c76..708d3dc62d15f 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php @@ -60,7 +60,7 @@ public function testSupportsDecoding() public function testContext() { - $encoder = new YamlEncoder(new Dumper(), new Parser(), ['yaml_inline' => 1, 'yaml_indent' => 4, 'yaml_flags' => Yaml::DUMP_OBJECT | Yaml::PARSE_OBJECT]); + $encoder = new YamlEncoder(new Dumper(), new Parser(), [YamlEncoder::YAML_INLINE => 1, YamlEncoder::YAML_INDENT => 4, YamlEncoder::YAML_FLAGS => Yaml::DUMP_OBJECT | Yaml::PARSE_OBJECT]); $obj = new \stdClass(); $obj->bar = 2; @@ -68,8 +68,8 @@ public function testContext() $legacyTag = " foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n"; $spacedTag = " foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'\n"; $this->assertThat($encoder->encode(['foo' => $obj], 'yaml'), $this->logicalOr($this->equalTo($legacyTag), $this->equalTo($spacedTag))); - $this->assertEquals(' { foo: null }', $encoder->encode(['foo' => $obj], 'yaml', ['yaml_inline' => 0, 'yaml_indent' => 2, 'yaml_flags' => 0])); + $this->assertEquals(' { foo: null }', $encoder->encode(['foo' => $obj], 'yaml', [YamlEncoder::YAML_INLINE => 0, YamlEncoder::YAML_INDENT => 2, YamlEncoder::YAML_FLAGS => 0])); $this->assertEquals(['foo' => $obj], $encoder->decode("foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'", 'yaml')); - $this->assertEquals(['foo' => null], $encoder->decode("foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'", 'yaml', ['yaml_flags' => 0])); + $this->assertEquals(['foo' => null], $encoder->decode("foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'", 'yaml', [YamlEncoder::YAML_FLAGS => 0])); } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php index d1829f759ddac..f1a906b593836 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php @@ -20,9 +20,9 @@ */ class DataUriNormalizerTest extends TestCase { - const TEST_GIF_DATA = 'data:image/gif;base64,R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs='; - const TEST_TXT_DATA = 'data:text/plain,K%C3%A9vin%20Dunglas%0A'; - const TEST_TXT_CONTENT = "Kévin Dunglas\n"; + private const TEST_GIF_DATA = 'data:image/gif;base64,R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs='; + private const TEST_TXT_DATA = 'data:text/plain,K%C3%A9vin%20Dunglas%0A'; + private const TEST_TXT_CONTENT = "Kévin Dunglas\n"; /** * @var DataUriNormalizer diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php index f55ab508dc5f2..f2aa3e7273fe1 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php @@ -23,7 +23,7 @@ */ class StopwatchEventTest extends TestCase { - const DELTA = 37; + private const DELTA = 37; public function testGetOrigin() { diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php index b8efa373b4cd1..5dd0c3c2d8a19 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php @@ -23,7 +23,7 @@ */ class StopwatchTest extends TestCase { - const DELTA = 20; + private const DELTA = 20; public function testStart() { diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php index 04975b171f563..80071eee74a74 100644 --- a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPathsPass.php @@ -48,7 +48,7 @@ public function process(ContainerBuilder $container) foreach ($this->findControllerArguments($container) as $controller => $argument) { $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller)); if ($container->hasDefinition($id)) { - list($locatorRef) = $argument->getValues(); + [$locatorRef] = $argument->getValues(); $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true; } } diff --git a/src/Symfony/Component/Translation/Loader/MoFileLoader.php b/src/Symfony/Component/Translation/Loader/MoFileLoader.php index d344c6e21af1c..1d90136bdb40c 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -90,7 +90,7 @@ protected function loadResource($resource) $singularId = fread($stream, $length); if (false !== strpos($singularId, "\000")) { - list($singularId, $pluralId) = explode("\000", $singularId); + [$singularId, $pluralId] = explode("\000", $singularId); } fseek($stream, $offsetTranslated + $i * 8); diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 41de63da396e3..69fc8a1b3fa0c 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -34,6 +34,7 @@ CHANGELOG * added support for UUIDv6 in `Uuid` constraint * enabled the validator to load constraints from PHP attributes * deprecated the `NumberConstraintTrait` trait + * deprecated setting or creating a Doctrine annotation reader via `ValidatorBuilder::enableAnnotationMapping()`, pass `true` as first parameter and additionally call `setDoctrineAnnotationReader()` or `addDefaultDoctrineAnnotationReader()` to set up the annotation reader 5.1.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 0d7a2b7deba67..86d199f8671a7 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/Constraints/Choice.php @@ -69,7 +69,7 @@ public function __construct( if (\is_array($choices) && \is_string(key($choices))) { $options = array_merge($choices, $options); } elseif (null !== $choices) { - $options['choices'] = $choices; + $options['value'] = $choices; } parent::__construct($options, $groups, $payload); diff --git a/src/Symfony/Component/Validator/Constraints/FileValidator.php b/src/Symfony/Component/Validator/Constraints/FileValidator.php index 3c946ff96ce8b..e5a756d893c8f 100644 --- a/src/Symfony/Component/Validator/Constraints/FileValidator.php +++ b/src/Symfony/Component/Validator/Constraints/FileValidator.php @@ -63,7 +63,7 @@ public function validate($value, Constraint $constraint) $binaryFormat = null === $constraint->binaryFormat ? true : $constraint->binaryFormat; } - list(, $limitAsString, $suffix) = $this->factorizeSizes(0, $limitInBytes, $binaryFormat); + [, $limitAsString, $suffix] = $this->factorizeSizes(0, $limitInBytes, $binaryFormat); $this->context->buildViolation($constraint->uploadIniSizeErrorMessage) ->setParameter('{{ limit }}', $limitAsString) ->setParameter('{{ suffix }}', $suffix) @@ -157,7 +157,7 @@ public function validate($value, Constraint $constraint) $limitInBytes = $constraint->maxSize; if ($sizeInBytes > $limitInBytes) { - list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat); + [$sizeAsString, $limitAsString, $suffix] = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat); $this->context->buildViolation($constraint->maxSizeMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setParameter('{{ size }}', $sizeAsString) diff --git a/src/Symfony/Component/Validator/Constraints/NotCompromisedPasswordValidator.php b/src/Symfony/Component/Validator/Constraints/NotCompromisedPasswordValidator.php index 7b8dd423532ba..adcdb7a59ff54 100644 --- a/src/Symfony/Component/Validator/Constraints/NotCompromisedPasswordValidator.php +++ b/src/Symfony/Component/Validator/Constraints/NotCompromisedPasswordValidator.php @@ -91,7 +91,7 @@ public function validate($value, Constraint $constraint) } foreach (explode("\r\n", $result) as $line) { - list($hashSuffix, $count) = explode(':', $line); + [$hashSuffix, $count] = explode(':', $line); if ($hashPrefix.$hashSuffix === $hash && $constraint->threshold <= (int) $count) { $this->context->buildViolation($constraint->message) diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php index 1055f41e381b3..deb356eb64d30 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php @@ -69,7 +69,7 @@ protected function newConstraint(string $name, $options = null) if (false !== strpos($name, '\\') && class_exists($name)) { $className = (string) $name; } elseif (false !== strpos($name, ':')) { - list($prefix, $className) = explode(':', $name, 2); + [$prefix, $className] = explode(':', $name, 2); if (!isset($this->namespaces[$prefix])) { throw new MappingException(sprintf('Undefined namespace prefix "%s".', $prefix)); diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf index 731e64aa7f2a4..cbee3bb9d31b8 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf @@ -334,6 +334,58 @@ This value should be valid JSON. Hierdie waarde moet geldige JSON wees. + + This collection should contain only unique elements. + Hierdie versameling moet net unieke elemente bevat. + + + This value should be positive. + Hierdie waarde moet positief wees. + + + This value should be either positive or zero. + Hierdie waarde moet positief of nul wees. + + + This value should be negative. + Hierdie waarde moet negatief wees. + + + This value should be either negative or zero. + Hierdie waarde moet negatief of nul wees. + + + This value is not a valid timezone. + Hierdie waarde is nie 'n geldige tydsone nie. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + This password has been leaked in a data breach, it must not be used. Please use another password. + + + This value should be between {{ min }} and {{ max }}. + Hierdie waarde moet tussen {{ min }} en {{ max }} wees. + + + This value is not a valid hostname. + Hierdie waarde is nie 'n geldige gasheernaam nie. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Die hoeveelheid elemente in hierdie versameling moet 'n meelvoud van {{ compared_value }} wees. + + + This value should satisfy at least one of the following constraints: + Hierdie waarde moet voldoen aan ten minste een van hierdie beperkings: + + + Each element of this collection should satisfy its own set of constraints. + Elke element van hierdie versameling moet voldoen aan hulle eie beperkings. + + + This value is not a valid International Securities Identification Number (ISIN). + Hierdie waarde is nie 'n geldige Internasionale veiligheidsidentifikasienommer (ISIN) nie. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf index c3420f3db2a94..59480874fd387 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Bu dəyər {{ min }} və {{ max }} arasında olmaldır. + + This value is not a valid hostname. + Bu dəyər doğru bir host adı deyil. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Bu kolleksiyadakı elementlerin sayı {{ compared_value }} tam bölünəni olmalıdır. + + + This value should satisfy at least one of the following constraints: + Bu dəyər aşağıdakı məcburiyyətlərdən birini qarşılamalıdır: + + + Each element of this collection should satisfy its own set of constraints. + Bu kolleksiyadakı hər element öz məcburiyyətlərini qarşılamalıdır. + + + This value is not a valid International Securities Identification Number (ISIN). + Bu dəyər doğru bir Qiymətli Kağızın Beynəlxalq İdentifikasiya Kodu (ISIN) deyil. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf index d6ae6e91bce2a..80e5364c1d756 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf @@ -330,6 +330,62 @@ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. Aquest Codi d'identificació bancari (BIC) no està associat amb l'IBAN {{ iban }}. + + This value should be valid JSON. + Aquest valor hauria de ser JSON vàlid. + + + This collection should contain only unique elements. + Aquesta col·lecció només hauria de contenir elements únics. + + + This value should be positive. + Aquest valor hauria de ser positiu. + + + This value should be either positive or zero. + Aquest valor ha de ser positiu o zero. + + + This value should be negative. + Aquest valor ha de ser negatiu. + + + This value should be either negative or zero. + Aquest valor ha de ser negatiu o zero. + + + This value is not a valid timezone. + Aquest valor no és una zona horària vàlida. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Aquesta contrasenya s'ha filtrat en cas de violació de dades, no s'ha d'utilitzar. Utilitzeu una altra contrasenya. + + + This value should be between {{ min }} and {{ max }}. + Aquest valor ha d'estar entre {{ min }} i {{ max }}. + + + This value is not a valid hostname. + Aquest valor no és un nom d'amfitrió vàlid. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + El nombre d'elements d'aquesta col·lecció ha de ser múltiple de {{compared_value}}. + + + This value should satisfy at least one of the following constraints: + Aquest valor ha de satisfer almenys una de les restriccions següents: + + + Each element of this collection should satisfy its own set of constraints. + Cada element d'aquesta col·lecció hauria de satisfer el seu propi conjunt de restriccions. + + + This value is not a valid International Securities Identification Number (ISIN). + Aquest valor no és un número d'identificació de valors internacionals (ISIN) vàlid. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf index 2bc33a7b437cd..6716585e7c9e3 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf @@ -124,7 +124,7 @@ The file could not be uploaded. - Filen kunne ikke blive uploadet. + Filen kunne ikke uploades. This value should be a valid number. @@ -324,7 +324,7 @@ This value should be a multiple of {{ compared_value }}. - Denne værdi skal være et flertal af {{ compared_value }}. + Denne værdi skal være et multiplikation af {{ compared_value }}. This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Værdien skal være mellem {{ min }} og {{ max }}. + + This value is not a valid hostname. + Værdien er ikke et gyldigt værtsnavn. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Antallet af elementer i denne samling skal være en multiplikation af {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Værdien skal overholde mindst én af følgende krav:: + + + Each element of this collection should satisfy its own set of constraints. + Hvert element i denne samling skal overholde dens egne krav. + + + This value is not a valid International Securities Identification Number (ISIN). + Værdien er ikke et gyldig International Securities Identification Number (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf index 3b9bbef66e5a4..c8882d2ae6667 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf @@ -24,11 +24,11 @@ You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. - Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές. + Πρέπει να επιλέξτε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξτε τουλάχιστον {{ limit }} επιλογές. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. - Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές. + Πρέπει να επιλέξτε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξτε το πολύ {{ limit }} επιλογές. One or more of the given values is invalid. @@ -330,6 +330,62 @@ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. Αυτός ο κωδικός BIC δεν σχετίζεται με το IBAN {{ iban }}. + + This value should be valid JSON. + Αυτή η τιμή θα πρέπει να είναι έγκυρο JSON. + + + This collection should contain only unique elements. + Αυτή η συλλογή θα πρέπει να περιέχει μόνο μοναδικά στοιχεία. + + + This value should be positive. + Αυτή η τιμή θα πρέπει να είναι θετική. + + + This value should be either positive or zero. + Αυτή η τιμή θα πρέπει να είναι θετική ή μηδενική. + + + This value should be negative. + Αυτή η τιμή θα πρέπει να είναι αρνητική. + + + This value should be either negative or zero. + Αυτή η τιμή θα πρέπει να είναι αρνητική ή μηδενική. + + + This value is not a valid timezone. + Αυτή η τιμή θα δέν είναι έγκυρη ζώνη ώρας. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Αυτός ο κωδικός πρόσβασης έχει διερρεύσει σε παραβίαση δεδομένων. Παρακαλούμε να χρησιμοποιήσετε έναν άλλο κωδικό. + + + This value should be between {{ min }} and {{ max }}. + Αυτή η τιμή θα πρέπει να είναι μεταξύ {{ min }} και {{ max }}. + + + This value is not a valid hostname. + Αυτή η τιμή δέν είναι έγκυρο όνομα υποδοχής. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Το νούμερο των στοιχείων σε αυτή τη συλλογή θα πρέπει να είναι πολλαπλάσιο του {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Αυτή η τιμή θα πρέπει να ικανοποιεί τουλάχιστον έναν απο τους παρακάτω περιορισμούς: + + + Each element of this collection should satisfy its own set of constraints. + Κάθε στοιχείο σε αυτή τη συλλογή θα πρέπει να ικανοποιεί το δικό του σύνολο περιορισμών. + + + This value is not a valid International Securities Identification Number (ISIN). + Αυτή η τιμή δέν είναι έγυρο International Securities Identification Number (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf index d35bff2c6e8e7..423775903d6c4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf @@ -336,7 +336,7 @@ This collection should contain only unique elements. - Tämä ryhmä tulisi sisältää vain yksilöllisiä arvoja. + Tämän ryhmän tulisi sisältää vain yksilöllisiä arvoja. This value should be positive. @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Arvon tulisi olla välillä {{ min }} - {{ max }}. + + This value is not a valid hostname. + Arvo ei ole kelvollinen laitenimi (hostname). + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Ryhmässä olevien elementtien määrän pitää olla monikerta luvulle {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Tämän arvon tulee läpäistä vähintään yksi seuraavista tarkistuksista: + + + Each element of this collection should satisfy its own set of constraints. + Ryhmän jokaisen elementin tulee läpäistä omat tarkistuksensa. + + + This value is not a valid International Securities Identification Number (ISIN). + Tämä arvo ei ole kelvollinen ISIN-koodi (International Securities Identification Number). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf index 71df1d240bde7..4bfd7a09c23f5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf @@ -330,6 +330,62 @@ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. Este Código de identificación bancaria (BIC) non está asociado co IBAN {{ iban }}. + + This value should be valid JSON. + Este valor debería ser un JSON válido. + + + This collection should contain only unique elements. + Esta colección só debería ter elementos únicos. + + + This value should be positive. + Este valor debería ser positivo. + + + This value should be either positive or zero. + Este valor debe ser positivo ou igual a cero. + + + This value should be negative. + Este valor debe ser negativo. + + + This value should be either negative or zero. + Este valor debe ser negativo ou igual a cero. + + + This value is not a valid timezone. + Este valor non é unha zona horaria válida. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Este contrasinal non se pode usar porque está incluído nunha lista de contrasinais públicos obtidos grazas a fallos de seguridade noutros sitios e aplicacións. Utiliza outro contrasinal. + + + This value should be between {{ min }} and {{ max }}. + Este valor debe estar comprendido entre {{min}} e {{max}}. + + + This value is not a valid hostname. + Este valor non é un nome de host válido. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + O número de elementos desta colección debería ser múltiplo de {{compare_value}}. + + + This value should satisfy at least one of the following constraints: + Este valor debe cumprir polo menos unha das seguintes restricións: + + + Each element of this collection should satisfy its own set of constraints. + Cada elemento desta colección debe satisfacer o seu propio conxunto de restricións. + + + This value is not a valid International Securities Identification Number (ISIN). + Este valor non é un número de identificación de valores internacionais (ISIN) válido. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf index 6f9ab0a1cfa64..dfaed73d2f6da 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. הערך חייב להיות בין {{ min }} ו- {{ max }}. + + This value is not a valid hostname. + ערך זה אינו שם מארח חוקי. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + מספר האלמנטים באוסף זה צריך להיות מכפיל של {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + ערך זה אמור לעמוד לפחות באחד התנאים הבאים: + + + Each element of this collection should satisfy its own set of constraints. + כל אלמנט באוסף זה אמור לעמוד בקבוצת התנאים שלו. + + + This value is not a valid International Securities Identification Number (ISIN). + ערך זה אינו מספר זיהוי ניירות ערך בינלאומי תקף (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf index 23ca5618097c5..acd69a1009c13 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf @@ -382,6 +382,10 @@ Each element of this collection should satisfy its own set of constraints. A gyűjtemény minden elemének meg kell felelni a saját feltételeinek. + + This value is not a valid International Securities Identification Number (ISIN). + Ez az érték nem egy érvényes nemzetközi értékpapír-azonosító szám (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf index b1458eee1ac0b..b767dc87c8452 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf @@ -131,20 +131,20 @@ Энэ утга зөвхөн тоо байна. - This value is not a valid country. - Энэ утга үнэн бодит улс биш байна. - - This file is not a valid image. Файл зураг биш байна. - + This is not a valid IP address. IP хаяг зөв биш байна. - + This value is not a valid language. - Энэ утга үнэн зөв хэл биш байна . + Энэ утга үнэн зөв хэл биш байна. + + + This value is not a valid locale. + Энэ утга үнэн зөв байршил биш байна. This value is not a valid country. @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Энэ утга {{ min }} -с {{ max }} хооронд байх ёстой. + + This value is not a valid hostname. + Энэ утга буруу hostname байна. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Энэхүү цуглуулган дахь элемэнтийн тоо, {{ compared_value }}-н үржвэр байх ёстой. + + + This value should satisfy at least one of the following constraints: + Энэ утга доорх болзолуудын ядаж нэгийг хангах ёстой: + + + Each element of this collection should satisfy its own set of constraints. + Энэхүү цуглуулган дахь элемэнтүүд өөр өөрсдийн болзолуудаа хангах ёстой. + + + This value is not a valid International Securities Identification Number (ISIN). + Энэ утга зөв International Securities Identification Number (ISIN) биш байна. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf index bfa9b1284e8d9..93132ec57cdfc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Verdien må være mellom {{ min }} og {{ max }}. + + This value is not a valid hostname. + Denne verdien er ikke et gyldig vertsnavn. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Antall elementer i denne samlingen bør være et multiplum av {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Denne verdien skal tilfredsstille minst en av følgende begrensninger: + + + Each element of this collection should satisfy its own set of constraints. + Hvert element i denne samlingen skal tilfredsstille sitt eget sett med begrensninger. + + + This value is not a valid International Securities Identification Number (ISIN). + Denne verdien er ikke et gyldig International Securities Identification Number (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf index bfa9b1284e8d9..93132ec57cdfc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. Verdien må være mellom {{ min }} og {{ max }}. + + This value is not a valid hostname. + Denne verdien er ikke et gyldig vertsnavn. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Antall elementer i denne samlingen bør være et multiplum av {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Denne verdien skal tilfredsstille minst en av følgende begrensninger: + + + Each element of this collection should satisfy its own set of constraints. + Hvert element i denne samlingen skal tilfredsstille sitt eget sett med begrensninger. + + + This value is not a valid International Securities Identification Number (ISIN). + Denne verdien er ikke et gyldig International Securities Identification Number (ISIN). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf index 31aa00cfac011..31453ff15736d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf @@ -366,6 +366,26 @@ This value should be between {{ min }} and {{ max }}. ค่านี้ควรอยู่ระหว่าง {{ min }} ถึง {{ max }} + + This value is not a valid hostname. + ค่าโฮสต์เนมไม่ถูกต้อง + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + จำนวนของสมาชิกในคอเล็กชั่นควรเป็นพหุคูณของ {{ compared_value }} + + + This value should satisfy at least one of the following constraints: + ค่านี้ควรเป็นไปตามข้อจำกัดอย่างน้อยหนึ่งข้อจากข้อจำกัดเหล่านี้: + + + Each element of this collection should satisfy its own set of constraints. + สมากชิกแต่ละตัวในคอเล็กชั่นควรเป็นไปตามเซ็ตข้อจำกัดของคอเล็กชั่น + + + This value is not a valid International Securities Identification Number (ISIN). + ค่า​รหัสหลักทรัพย์สากล (ISIN) ไม่ถูกต้อง + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf index 34754b1e9bb8d..e930e59014191 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf @@ -68,7 +68,7 @@ The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. - Ang uri ng file ng mime ay hindi balido ({{ type }}).Ang mga pinapayagang uri ng mime ay ang {{ types }}. + Ang uri ng file ng mime ay hindi balido ({{ type }}). Ang mga pinapayagang uri ng mime ay ang {{ types }}. This value should be {{ limit }} or less. @@ -76,7 +76,7 @@ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Ang halaga nito ay masyadong mahaba.Ito ay dapat na {{ limit }} karakter o maliit pa.|Ang halaga nito ay masyadong mahaba. Ito ay dapat na {{ limit }} mga karakter o maliit pa. + Ang halaga nito ay masyadong mahaba. Ito ay dapat na {{ limit }} karakter o maliit pa.|Ang halaga nito ay masyadong mahaba. Ito ay dapat na {{ limit }} mga karakter o maliit pa. This value should be {{ limit }} or more. @@ -268,7 +268,7 @@ This value should be less than or equal to {{ compared_value }}. - Ang halagang ito ay dapat mas mmaliit o magkapareha sa {{ compared_value }}. + Ang halagang ito ay dapat mas maliit o magkapareha sa {{ compared_value }}. This value should not be equal to {{ compared_value }}. @@ -284,7 +284,7 @@ The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - ng ratio ng imahe ay masyadong maliit ({{ ratio }}). Ang pinamaliit na ratio ay {{ min_ratio }}. + Ang ratio ng imahe ay masyadong maliit ({{ ratio }}). Ang pinakamaliit na ratio ay {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. @@ -296,7 +296,7 @@ The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. - Ang orientasyon ng imahe ay nakaportrait ({{ width }}x{{ height }}px). PAng mga imaheng nakaportrait ang orientasyon ay hindi pwede. + Ang orientasyon ng imahe ay nakaportrait ({{ width }}x{{ height }}px). Ang mga imaheng nakaportrait ang orientasyon ay hindi pwede. An empty file is not allowed. @@ -374,6 +374,14 @@ The number of elements in this collection should be a multiple of {{ compared_value }}. Ang bilang ng mga elemento sa koleksyon na ito ay dapat multiple ng {{ compared_value }}. + + This value should satisfy at least one of the following constraints: + Ang halagang ito ay dapat masunod ang kahit na isang sumusunod na batayan. + + + Each element of this collection should satisfy its own set of constraints. + Ang bawat elemento sa koleksyon na ito ay dapat masunod ang nararapat na batayan. + This value is not a valid International Securities Identification Number (ISIN). Ang halagang ito ay hindi wastong International Securities Identification Number (ISIN). diff --git a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php index cce35db0dd0b9..7a5518c699152 100644 --- a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php @@ -473,7 +473,7 @@ public function doValidate($value, $constraints = null, $groups = null) return $this; } - list($expectedValue, $expectedGroup, $expectedConstraints, $violation) = $this->expectedValidate[$this->validateCalls]; + [$expectedValue, $expectedGroup, $expectedConstraints, $violation] = $this->expectedValidate[$this->validateCalls]; Assert::assertSame($expectedValue, $value); $expectedConstraints($constraints); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php index efc79b0b78c97..38d7076cf2882 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -202,7 +202,7 @@ public function testInvalidComparisonToValue($dirtyValue, $dirtyValueAsString, $ public function testInvalidComparisonToPropertyPathAddsPathAsParameter() { - list($dirtyValue, $dirtyValueAsString, $comparedValue, $comparedValueString, $comparedValueType) = current($this->provideAllInvalidComparisons()); + [$dirtyValue, $dirtyValueAsString, $comparedValue, $comparedValueString, $comparedValueType] = current($this->provideAllInvalidComparisons()); $constraint = $this->createConstraint(['propertyPath' => 'value']); $constraint->message = 'Constraint Message'; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php index 5c1cacbc4c12b..de47bd39daf74 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame([CardScheme::MASTERCARD, CardScheme::VISA], $aConstraint->schemes); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame([CardScheme::AMEX], $bConstraint->schemes); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'CardSchemeDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame([CardScheme::DINERS], $cConstraint->schemes); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php new file mode 100644 index 0000000000000..8b5879aedcb42 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Tests\Fixtures\ConstraintChoiceWithPreset; + +class ChoiceTest extends TestCase +{ + public function testSetDefaultPropertyChoice() + { + $constraint = new ConstraintChoiceWithPreset('A'); + + self::assertEquals(['A', 'B', 'C'], $constraint->choices); + } +} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CountTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CountTest.php index fe84d8eb0f735..ebf1e2891f22f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CountTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CountTest.php @@ -27,12 +27,12 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(42, $aConstraint->min); self::assertSame(42, $aConstraint->max); self::assertNull($aConstraint->divisibleBy); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(1, $bConstraint->min); self::assertSame(4711, $bConstraint->max); self::assertNull($bConstraint->divisibleBy); @@ -40,7 +40,7 @@ public function testAttributes() self::assertSame('myMaxMessage', $bConstraint->maxMessage); self::assertSame(['Default', 'CountDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->min); self::assertNull($cConstraint->max); self::assertSame(10, $cConstraint->divisibleBy); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CountryTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CountryTest.php index 6db035710ed14..9e49adbe936a4 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CountryTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CountryTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertFalse($aConstraint->alpha3); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->alpha3); self::assertSame(['Default', 'CountryDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CurrencyTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CurrencyTest.php index 1276a1b7ec532..ccac27d2942b9 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CurrencyTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CurrencyTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'CurrencyDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateTest.php index 911be3f0c9e9a..151304e59aeec 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DateTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DateTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DateDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeTest.php index 6c76a3a8907f0..75de91dd84875 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame('Y-m-d H:i:s', $aConstraint->format); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('d.m.Y', $bConstraint->format); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DateTimeDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame('m/d/Y', $cConstraint->format); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByTest.php index 74edb15566881..9d8482961bad2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DivisibleByDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EmailTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EmailTest.php index 8697a855288cb..84da112693f54 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EmailTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EmailTest.php @@ -70,7 +70,7 @@ public function testAttribute() self::assertSame(Email::VALIDATION_MODE_HTML5, $bConstraint->mode); self::assertSame('trim', $bConstraint->normalizer); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EqualToTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EqualToTest.php index a37c8a3d313ff..baa1e0a9079fd 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EqualToTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EqualToTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'EqualToDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionLanguageSyntaxTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionLanguageSyntaxTest.php index f6c1457a0badb..1c57d56f0e6a6 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionLanguageSyntaxTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionLanguageSyntaxTest.php @@ -58,16 +58,16 @@ public function testAttributes() $metadata = new ClassMetadata(ExpressionLanguageSyntaxDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertNull($aConstraint->service); self::assertNull($aConstraint->allowedVariables); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('my_service', $bConstraint->service); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'ExpressionLanguageSyntaxDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['foo', 'bar'], $cConstraint->allowedVariables); self::assertSame(['my_group'], $cConstraint->groups); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php index a22b9df0de7bf..bd3ab5b0ed2a7 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php @@ -26,16 +26,16 @@ public function testAttributes() $metadata = new ClassMetadata(ExpressionDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame('value == "1"', $aConstraint->expression); self::assertSame([], $aConstraint->values); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('value == "1"', $bConstraint->expression); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'ExpressionDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame('value == someVariable', $cConstraint->expression); self::assertSame(['someVariable' => 42], $cConstraint->values); self::assertSame(['foo'], $cConstraint->groups); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php b/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php index 1e1b522c2452a..aea824cfdaa95 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php @@ -149,15 +149,15 @@ public function testAttributes() $metadata = new ClassMetadata(FileDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertNull($aConstraint->maxSize); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(100, $bConstraint->maxSize); self::assertSame('myMessage', $bConstraint->notFoundMessage); self::assertSame(['Default', 'FileDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(100000, $cConstraint->maxSize); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php index b8f1663ca9098..9894bf266c41a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php @@ -503,7 +503,7 @@ public function uploadedFileErrorProvider() $reflection = new \ReflectionClass(\get_class(new FileValidator())); $method = $reflection->getMethod('factorizeSizes'); $method->setAccessible(true); - list(, $limit, $suffix) = $method->invokeArgs(new FileValidator(), [0, UploadedFile::getMaxFilesize(), false]); + [, $limit, $suffix] = $method->invokeArgs(new FileValidator(), [0, UploadedFile::getMaxFilesize(), false]); // it correctly parses the maxSize option and not only uses simple string comparison // 1000M should be bigger than the ini value diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualTest.php index f1df038f8b25a..c5d2dbac5fcfd 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'GreaterThanOrEqualDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanTest.php index 446895ea65fff..5fb7df2d859f8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'GreaterThanDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/HostnameTest.php b/src/Symfony/Component/Validator/Tests/Constraints/HostnameTest.php index cafa7d442a58a..6169362b5a761 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/HostnameTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/HostnameTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertTrue($aConstraint->requireTld); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertFalse($bConstraint->requireTld); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'HostnameDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToTest.php index d2c6e00e91bb1..afe17270d0330 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IdenticalToDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php index 80a6e0505536f..0b4e4dd0b1d02 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php @@ -27,20 +27,20 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertNull($aConstraint->minWidth); self::assertNull($aConstraint->maxWidth); self::assertNull($aConstraint->minHeight); self::assertNull($aConstraint->maxHeight); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(50, $bConstraint->minWidth); self::assertSame(200, $bConstraint->maxWidth); self::assertSame(50, $bConstraint->minHeight); self::assertSame(200, $bConstraint->maxHeight); self::assertSame(['Default', 'ImageDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(100000, $cConstraint->maxSize); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IpTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IpTest.php index 65d7573a33ce7..f9313f998565b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IpTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IpTest.php @@ -51,16 +51,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(Ip::V4, $aConstraint->version); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(Ip::V6, $bConstraint->version); self::assertSame('myMessage', $bConstraint->message); self::assertSame('trim', $bConstraint->normalizer); self::assertSame(['Default', 'IpDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsbnTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsbnTest.php index e9dc7c38b0dbf..39d2ce8ce67ad 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsbnTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsbnTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertNull($aConstraint->type); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(Isbn::ISBN_13, $bConstraint->type); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IsbnDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsinTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsinTest.php index 4979a1ae7428f..09f4e9dca1d58 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsinTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsinTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IsinDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IssnTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IssnTest.php index 1ee6ec9ee76f9..ca342ea1ad08b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IssnTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IssnTest.php @@ -27,17 +27,17 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertFalse($aConstraint->caseSensitive); self::assertFalse($aConstraint->requireHyphen); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->caseSensitive); self::assertTrue($bConstraint->requireHyphen); self::assertSame(['Default', 'IssnDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/JsonTest.php b/src/Symfony/Component/Validator/Tests/Constraints/JsonTest.php index 9a23170312f8c..63315780ab20f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/JsonTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/JsonTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'JsonDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LanguageTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LanguageTest.php index 3fec1f952b100..88f712b4e74eb 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LanguageTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LanguageTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertFalse($aConstraint->alpha3); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->alpha3); self::assertSame(['Default', 'LanguageDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php index a8c9922662227..7748b3063f3c4 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php @@ -90,11 +90,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(42, $aConstraint->min); self::assertSame(42, $aConstraint->max); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(1, $bConstraint->min); self::assertSame(4711, $bConstraint->max); self::assertSame('myMinMessage', $bConstraint->minMessage); @@ -103,7 +103,7 @@ public function testAttributes() self::assertSame('ISO-8859-15', $bConstraint->charset); self::assertSame(['Default', 'LengthDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualTest.php index 921ccb2b661ec..a41b4f80bbc2c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LessThanOrEqualDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanTest.php index 41c1b1cc580dd..c67453b7e12e1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LessThanDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LocaleTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LocaleTest.php index edd56f5cca957..eede89aca02a0 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LocaleTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LocaleTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertTrue($aConstraint->canonicalize); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertFalse($bConstraint->canonicalize); self::assertSame(['Default', 'LocaleDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LuhnTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LuhnTest.php index 2aea6e98ecb58..798dc0d19d348 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LuhnTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LuhnTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LuhnDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NegativeOrZeroTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NegativeOrZeroTest.php index ab46b658343c5..ffb3d7e64e50d 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NegativeOrZeroTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NegativeOrZeroTest.php @@ -27,12 +27,12 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'NegativeOrZeroDummy'], $aConstraint->groups); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NegativeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NegativeTest.php index 2e35ea50eb52c..30cf5ff71335e 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NegativeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NegativeTest.php @@ -27,12 +27,12 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'NegativeDummy'], $aConstraint->groups); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php index f4781f1577a1f..0a3ae6b346618 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php @@ -37,11 +37,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertFalse($aConstraint->allowNull); self::assertNull($aConstraint->normalizer); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertTrue($bConstraint->allowNull); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotCompromisedPasswordTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotCompromisedPasswordTest.php index 84c9ef6b4b413..9f7062c17bb88 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotCompromisedPasswordTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotCompromisedPasswordTest.php @@ -37,17 +37,17 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(1, $aConstraint->threshold); self::assertFalse($aConstraint->skipOnError); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(42, $bConstraint->threshold); self::assertTrue($bConstraint->skipOnError); self::assertSame(['Default', 'NotCompromisedPasswordDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToTest.php index f00e8dcfbd02c..be04a870a6776 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'NotEqualToDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToTest.php index bb213cf02be68..e676dffa90205 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToTest.php @@ -27,16 +27,16 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'NotIdenticalToDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/PositiveOrZeroTest.php b/src/Symfony/Component/Validator/Tests/Constraints/PositiveOrZeroTest.php index 5c8e9df8e59db..520366eb5eca4 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/PositiveOrZeroTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/PositiveOrZeroTest.php @@ -27,12 +27,12 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'PositiveOrZeroDummy'], $aConstraint->groups); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/PositiveTest.php b/src/Symfony/Component/Validator/Tests/Constraints/PositiveTest.php index f14f9be14cce4..076eb0d40b1c0 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/PositiveTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/PositiveTest.php @@ -27,12 +27,12 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'PositiveDummy'], $aConstraint->groups); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php index f71ae135fcb65..909f3e1f2e46c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php @@ -118,19 +118,19 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame('/^[0-9]+$/', $aConstraint->pattern); self::assertTrue($aConstraint->match); self::assertNull($aConstraint->normalizer); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame('/^[0-9]+$/', $bConstraint->pattern); self::assertSame('[0-9]+', $bConstraint->htmlPattern); self::assertFalse($bConstraint->match); self::assertSame(['Default', 'RegexDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimeTest.php index 30cf3a13d779c..17b88d9511224 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimeTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TimeDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TimezoneTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TimezoneTest.php index b6c98c697081c..cc4666f170981 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TimezoneTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TimezoneTest.php @@ -73,16 +73,16 @@ public function testAttributes() $metadata = new ClassMetadata(TimezoneDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(\DateTimeZone::ALL, $aConstraint->zone); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(\DateTimeZone::PER_COUNTRY, $bConstraint->zone); self::assertSame('DE', $bConstraint->countryCode); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TimezoneDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php index 0e5163705d4bc..92a8c06ca3650 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php @@ -26,15 +26,15 @@ public function testAttributes() $metadata = new ClassMetadata(TypeDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame('integer', $aConstraint->type); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(\DateTime::class, $bConstraint->type); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TypeDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['string', 'array'], $cConstraint->type); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UlidTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UlidTest.php index b6cc9c807ac37..2e60f80968146 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UlidTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UlidTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UlidDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UniqueTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UniqueTest.php index f34721f64efd5..54494b465695d 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UniqueTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UniqueTest.php @@ -27,11 +27,11 @@ public function testAttributes() $loader = new AnnotationLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UniqueDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php index 2fce08bd53bf0..6fad1a832f499 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlTest.php @@ -50,18 +50,18 @@ public function testAttributes() $metadata = new ClassMetadata(UrlDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(['http', 'https'], $aConstraint->protocols); self::assertFalse($aConstraint->relativeProtocol); self::assertNull($aConstraint->normalizer); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame(['ftp', 'gopher'], $bConstraint->protocols); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UrlDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertTrue($cConstraint->relativeProtocol); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UuidTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UuidTest.php index 4c172ec617df3..d5843d569b731 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UuidTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UuidTest.php @@ -50,19 +50,19 @@ public function testAttributes() $metadata = new ClassMetadata(UuidDummy::class); self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); - list($aConstraint) = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->properties['a']->getConstraints(); self::assertSame(Uuid::ALL_VERSIONS, $aConstraint->versions); self::assertTrue($aConstraint->strict); self::assertNull($aConstraint->normalizer); - list($bConstraint) = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->properties['b']->getConstraints(); self::assertSame([Uuid::V4_RANDOM, Uuid::V6_SORTABLE], $bConstraint->versions); self::assertFalse($bConstraint->strict); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UuidDummy'], $bConstraint->groups); - list($cConstraint) = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->properties['c']->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ValidValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ValidValidatorTest.php index 0ec1d421378ea..93de4244cc696 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ValidValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ValidValidatorTest.php @@ -12,7 +12,7 @@ class ValidValidatorTest extends TestCase public function testPropertyPathsArePassedToNestedContexts() { $validatorBuilder = new ValidatorBuilder(); - $validator = $validatorBuilder->enableAnnotationMapping()->getValidator(); + $validator = $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader()->getValidator(); $violations = $validator->validate(new Foo(), null, ['nested']); @@ -23,7 +23,7 @@ public function testPropertyPathsArePassedToNestedContexts() public function testNullValues() { $validatorBuilder = new ValidatorBuilder(); - $validator = $validatorBuilder->enableAnnotationMapping()->getValidator(); + $validator = $validatorBuilder->enableAnnotationMapping(true)->addDefaultDoctrineAnnotationReader()->getValidator(); $foo = new Foo(); $foo->fooBar = null; diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintChoiceWithPreset.php b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintChoiceWithPreset.php new file mode 100644 index 0000000000000..9e0cc37e231ea --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintChoiceWithPreset.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +use Symfony\Component\Validator\Constraints\Choice; + +class ConstraintChoiceWithPreset extends Choice +{ + public $type; + + public function __construct(string $type) { + parent::__construct($type); + + if ($this->type === 'A') { + $this->choices = ['A', 'B', 'C']; + } else { + $this->choices = ['D', 'E', 'F']; + } + } + + public function getDefaultOption(): ?string + { + return 'type'; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index 44218fde1d67f..16cce5fbb1100 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -30,10 +30,10 @@ class ClassMetadataTest extends TestCase { - const CLASSNAME = Entity::class; - const PARENTCLASS = EntityParent::class; - const PROVIDERCLASS = GroupSequenceProviderEntity::class; - const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity'; + private const CLASSNAME = Entity::class; + private const PARENTCLASS = EntityParent::class; + private const PROVIDERCLASS = GroupSequenceProviderEntity::class; + private const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity'; protected $metadata; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index dde0dcc0d7a7f..9795e211cfa9e 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -27,11 +27,9 @@ class LazyLoadingMetadataFactoryTest extends TestCase { - const CLASS_NAME = Entity::class; - const PARENT_CLASS = EntityParent::class; - const INTERFACE_A_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA'; - const INTERFACE_B_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB'; - const PARENT_INTERFACE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParentInterface'; + private const CLASS_NAME = Entity::class; + private const PARENT_CLASS = EntityParent::class; + private const INTERFACE_A_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA'; public function testLoadClassMetadataWithInterface() { diff --git a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php index cc188f07ac656..6a83816aaa66f 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php @@ -17,7 +17,7 @@ class GetterMetadataTest extends TestCase { - const CLASSNAME = Entity::class; + private const CLASSNAME = Entity::class; public function testInvalidPropertyName() { diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index c1f147a802a79..767a5ab5c6978 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -89,7 +89,8 @@ public function testLoadClassMetadata() $propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, '{.*}'); $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader($propertyInfoLoader) ->getValidator() ; @@ -220,7 +221,8 @@ public function testClassNoAutoMapping() $propertyInfoLoader = new PropertyInfoLoader($propertyInfoStub, $propertyInfoStub, $propertyInfoStub, '{.*}'); $validator = Validation::createValidatorBuilder() - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader($propertyInfoLoader) ->getValidator() ; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php index f00e0c63acb57..abeb2c5bf123d 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php @@ -20,10 +20,10 @@ class PropertyMetadataTest extends TestCase { - const CLASSNAME = Entity::class; - const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74'; - const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy'; - const PARENTCLASS = EntityParent::class; + private const CLASSNAME = Entity::class; + private const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74'; + private const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy'; + private const PARENTCLASS = EntityParent::class; public function testInvalidPropertyName() { diff --git a/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php index 9779f43727222..894ae55f10567 100644 --- a/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Validator\Tests\Resources; use PHPUnit\Framework\TestCase; -use PHPUnit\Util\Xml\Loader; +use Symfony\Component\Translation\Util\XliffUtils; class TranslationFilesTest extends TestCase { @@ -21,13 +21,12 @@ class TranslationFilesTest extends TestCase */ public function testTranslationFileIsValid($filePath) { - $loader = class_exists(Loader::class) - ? [new Loader(), 'loadFile'] - : ['PHPUnit\Util\XML', 'loadfile']; + $document = new \DOMDocument(); + $document->loadXML(file_get_contents($filePath)); - $loader($filePath, false, false, true); + $errors = XliffUtils::validateSchema($document); - $this->addToAssertionCount(1); + $this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php deleted file mode 100644 index b836a11e812bb..0000000000000 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php +++ /dev/null @@ -1,804 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Validator; - -use Symfony\Component\Validator\Constraints\Callback; -use Symfony\Component\Validator\Constraints\Cascade; -use Symfony\Component\Validator\Constraints\Collection; -use Symfony\Component\Validator\Constraints\Expression; -use Symfony\Component\Validator\Constraints\GroupSequence; -use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\Constraints\NotNull; -use Symfony\Component\Validator\Constraints\Traverse; -use Symfony\Component\Validator\Constraints\Valid; -use Symfony\Component\Validator\ConstraintViolationInterface; -use Symfony\Component\Validator\Context\ExecutionContextInterface; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; -use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; -use Symfony\Component\Validator\Tests\Fixtures\CascadedChild; -use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; -use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint; -use Symfony\Component\Validator\Tests\Fixtures\Reference; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * @author Bernhard Schussek - */ -abstract class AbstractTest extends AbstractValidatorTest -{ - /** - * @var ValidatorInterface - */ - protected $validator; - - abstract protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = []): ValidatorInterface; - - protected function setUp(): void - { - parent::setUp(); - - $this->validator = $this->createValidator($this->metadataFactory); - } - - protected function validate($value, $constraints = null, $groups = null) - { - return $this->validator->validate($value, $constraints, $groups); - } - - protected function validateProperty($object, $propertyName, $groups = null) - { - return $this->validator->validateProperty($object, $propertyName, $groups); - } - - protected function validatePropertyValue($object, $propertyName, $value, $groups = null) - { - return $this->validator->validatePropertyValue($object, $propertyName, $value, $groups); - } - - public function testValidateConstraintWithoutGroup() - { - $violations = $this->validator->validate(null, new NotNull()); - - $this->assertCount(1, $violations); - } - - public function testValidateWithEmptyArrayAsConstraint() - { - $violations = $this->validator->validate('value', []); - $this->assertCount(0, $violations); - } - - public function testGroupSequenceAbortsAfterFailedGroup() - { - $entity = new Entity(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message 1'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message 2'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => function () {}, - 'groups' => 'Group 1', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group 2', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 3', - ])); - - $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3']); - $violations = $this->validator->validate($entity, new Valid(), $sequence); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message 1', $violations[0]->getMessage()); - } - - public function testGroupSequenceIncludesReferences() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Reference violation 1'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Reference violation 2'); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group 1', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 2', - ])); - - $sequence = new GroupSequence(['Group 1', 'Entity']); - $violations = $this->validator->validate($entity, new Valid(), $sequence); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Reference violation 1', $violations[0]->getMessage()); - } - - public function testValidateInSeparateContext() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { - $violations = $context - ->getValidator() - // Since the validator is not context aware, the group must - // be passed explicitly - ->validate($value->reference, new Valid(), 'Group') - ; - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('', $violations[0]->getPropertyPath()); - - // The root is different as we're in a new context - $this->assertSame($entity->reference, $violations[0]->getRoot()); - $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - - // Verify that this method is called - $context->addViolation('Separate violation'); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity->reference, $context->getRoot()); - $this->assertSame($entity->reference, $context->getValue()); - $this->assertSame($entity->reference, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validator->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Separate violation', $violations[0]->getMessage()); - } - - public function testValidateInContext() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $previousValue = $context->getValue(); - $previousObject = $context->getObject(); - $previousMetadata = $context->getMetadata(); - $previousPath = $context->getPropertyPath(); - $previousGroup = $context->getGroup(); - - $context - ->getValidator() - ->inContext($context) - ->atPath('subpath') - ->validate($value->reference) - ; - - // context changes shouldn't leak out of the validate() call - $this->assertSame($previousValue, $context->getValue()); - $this->assertSame($previousObject, $context->getObject()); - $this->assertSame($previousMetadata, $context->getMetadata()); - $this->assertSame($previousPath, $context->getPropertyPath()); - $this->assertSame($previousGroup, $context->getGroup()); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('subpath', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference, $context->getValue()); - $this->assertSame($entity->reference, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validator->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('subpath', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testValidateArrayInContext() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $previousValue = $context->getValue(); - $previousObject = $context->getObject(); - $previousMetadata = $context->getMetadata(); - $previousPath = $context->getPropertyPath(); - $previousGroup = $context->getGroup(); - - $context - ->getValidator() - ->inContext($context) - ->atPath('subpath') - ->validate(['key' => $value->reference]) - ; - - // context changes shouldn't leak out of the validate() call - $this->assertSame($previousValue, $context->getValue()); - $this->assertSame($previousObject, $context->getObject()); - $this->assertSame($previousMetadata, $context->getMetadata()); - $this->assertSame($previousPath, $context->getPropertyPath()); - $this->assertSame($previousGroup, $context->getGroup()); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('subpath[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference, $context->getValue()); - $this->assertSame($entity->reference, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validator->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('subpath[key]', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testTraverseTraversableByDefault() - { - $entity = new Entity(); - $traversable = new \ArrayIterator(['key' => $entity]); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($traversable, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($traversable, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('[key]', $violations[0]->getPropertyPath()); - $this->assertSame($traversable, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testTraversalEnabledOnClass() - { - $entity = new Entity(); - $traversable = new \ArrayIterator(['key' => $entity]); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $traversableMetadata = new ClassMetadata('ArrayIterator'); - $traversableMetadata->addConstraint(new Traverse(true)); - - $this->metadataFactory->addMetadata($traversableMetadata); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($traversable, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - public function testTraversalDisabledOnClass() - { - $entity = new Entity(); - $traversable = new \ArrayIterator(['key' => $entity]); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $traversableMetadata = new ClassMetadata('ArrayIterator'); - $traversableMetadata->addConstraint(new Traverse(false)); - - $this->metadataFactory->addMetadata($traversableMetadata); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($traversable, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testExpectTraversableIfTraversalEnabledOnClass() - { - $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); - $entity = new Entity(); - - $this->metadata->addConstraint(new Traverse(true)); - - $this->validator->validate($entity); - } - - public function testReferenceTraversalDisabledOnClass() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator(['key' => new Reference()]); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $traversableMetadata = new ClassMetadata('ArrayIterator'); - $traversableMetadata->addConstraint(new Traverse(false)); - - $this->metadataFactory->addMetadata($traversableMetadata); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('reference', new Valid()); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testReferenceTraversalEnabledOnReferenceDisabledOnClass() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator(['key' => new Reference()]); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $traversableMetadata = new ClassMetadata('ArrayIterator'); - $traversableMetadata->addConstraint(new Traverse(false)); - - $this->metadataFactory->addMetadata($traversableMetadata); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('reference', new Valid([ - 'traverse' => true, - ])); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testReferenceTraversalDisabledOnReferenceEnabledOnClass() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator(['key' => new Reference()]); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $traversableMetadata = new ClassMetadata('ArrayIterator'); - $traversableMetadata->addConstraint(new Traverse(true)); - - $this->metadataFactory->addMetadata($traversableMetadata); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('reference', new Valid([ - 'traverse' => false, - ])); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testReferenceCascadeDisabledByDefault() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - /** - * @requires PHP 7.4 - */ - public function testReferenceCascadeEnabledIgnoresUntyped() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $this->metadata->addConstraint(new Cascade()); - - $callback = function ($value, ExecutionContextInterface $context) { - $this->fail('Should not be called'); - }; - - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - /** - * @requires PHP 7.4 - */ - public function testTypedReferenceCascadeEnabled() - { - $entity = new CascadingEntity(); - $entity->requiredChild = new CascadedChild(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->buildViolation('Invalid child') - ->atPath('name') - ->addViolation() - ; - }; - - $cascadingMetadata = new ClassMetadata(CascadingEntity::class); - $cascadingMetadata->addConstraint(new Cascade()); - - $cascadedMetadata = new ClassMetadata(CascadedChild::class); - $cascadedMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $this->metadataFactory->addMetadata($cascadingMetadata); - $this->metadataFactory->addMetadata($cascadedMetadata); - - $violations = $this->validate($entity, new Valid(), 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertInstanceOf(Callback::class, $violations->get(0)->getConstraint()); - } - - public function testAddCustomizedViolation() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->buildViolation('Message %param%') - ->setParameter('%param%', 'value') - ->setInvalidValue('Invalid value') - ->setPlural(2) - ->setCode('42') - ->addViolation(); - }; - - $this->metadata->addConstraint(new Callback($callback)); - - $violations = $this->validator->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Invalid value', $violations[0]->getInvalidValue()); - $this->assertSame(2, $violations[0]->getPlural()); - $this->assertSame('42', $violations[0]->getCode()); - } - - public function testNoDuplicateValidationIfClassConstraintInMultipleGroups() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => ['Group 1', 'Group 2'], - ])); - - $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - public function testNoDuplicateValidationIfPropertyConstraintInMultipleGroups() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addPropertyConstraint('firstName', new Callback([ - 'callback' => $callback, - 'groups' => ['Group 1', 'Group 2'], - ])); - - $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - public function testValidateFailsIfNoConstraintsAndNoObjectOrArray() - { - $this->expectException('Symfony\Component\Validator\Exception\RuntimeException'); - $this->validate('Foobar'); - } - - public function testAccessCurrentObject() - { - $called = false; - $entity = new Entity(); - $entity->firstName = 'Bernhard'; - $entity->data = ['firstName' => 'Bernhard']; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, &$called) { - $called = true; - $this->assertSame($entity, $context->getObject()); - }; - - $this->metadata->addConstraint(new Callback($callback)); - $this->metadata->addPropertyConstraint('firstName', new Callback($callback)); - $this->metadata->addPropertyConstraint('data', new Collection(['firstName' => new Expression('value == this.firstName')])); - - $this->validator->validate($entity); - - $this->assertTrue($called); - } - - public function testInitializeObjectsOnFirstValidation() - { - $entity = new Entity(); - $entity->initialized = false; - - // prepare initializers that set "initialized" to true - $initializer1 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock(); - $initializer2 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock(); - - $initializer1->expects($this->once()) - ->method('initialize') - ->with($entity) - ->willReturnCallback(function ($object) { - $object->initialized = true; - }); - - $initializer2->expects($this->once()) - ->method('initialize') - ->with($entity); - - $this->validator = $this->createValidator($this->metadataFactory, [ - $initializer1, - $initializer2, - ]); - - // prepare constraint which - // * checks that "initialized" is set to true - // * validates the object again - $callback = function ($object, ExecutionContextInterface $context) { - $this->assertTrue($object->initialized); - - // validate again in same group - $validator = $context->getValidator()->inContext($context); - - $validator->validate($object); - - // validate again in other group - $validator->validate($object, null, 'SomeGroup'); - }; - - $this->metadata->addConstraint(new Callback($callback)); - - $this->validate($entity); - - $this->assertTrue($entity->initialized); - } - - public function testPassConstraintToViolation() - { - $constraint = new FailingConstraint(); - $violations = $this->validate('Foobar', $constraint); - - $this->assertCount(1, $violations); - $this->assertSame($constraint, $violations[0]->getConstraint()); - } - - public function testCollectionConstraitViolationHasCorrectContext() - { - $data = [ - 'foo' => 'fooValue', - ]; - - // Missing field must not be the first in the collection validation - $constraint = new Collection([ - 'foo' => new NotNull(), - 'bar' => new NotNull(), - ]); - - $violations = $this->validate($data, $constraint); - - $this->assertCount(1, $violations); - $this->assertSame($constraint, $violations[0]->getConstraint()); - } - - public function testNestedObjectIsNotValidatedIfGroupInValidConstraintIsNotValidated() - { - $entity = new Entity(); - $entity->firstName = ''; - $reference = new Reference(); - $reference->value = ''; - $entity->childA = $reference; - - $this->metadata->addPropertyConstraint('firstName', new NotBlank(['groups' => 'group1'])); - $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => 'group1'])); - $this->referenceMetadata->addPropertyConstraint('value', new NotBlank()); - - $violations = $this->validator->validate($entity, null, []); - - $this->assertCount(0, $violations); - } - - public function testNestedObjectIsValidatedIfGroupInValidConstraintIsValidated() - { - $entity = new Entity(); - $entity->firstName = ''; - $reference = new Reference(); - $reference->value = ''; - $entity->childA = $reference; - - $this->metadata->addPropertyConstraint('firstName', new NotBlank(['groups' => 'group1'])); - $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => 'group1'])); - $this->referenceMetadata->addPropertyConstraint('value', new NotBlank(['groups' => 'group1'])); - - $violations = $this->validator->validate($entity, null, ['Default', 'group1']); - - $this->assertCount(2, $violations); - } - - public function testNestedObjectIsValidatedInMultipleGroupsIfGroupInValidConstraintIsValidated() - { - $entity = new Entity(); - $entity->firstName = null; - - $reference = new Reference(); - $reference->value = null; - - $entity->childA = $reference; - - $this->metadata->addPropertyConstraint('firstName', new NotBlank()); - $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => ['group1', 'group2']])); - - $this->referenceMetadata->addPropertyConstraint('value', new NotBlank(['groups' => 'group1'])); - $this->referenceMetadata->addPropertyConstraint('value', new NotNull(['groups' => 'group2'])); - - $violations = $this->validator->validate($entity, null, ['Default', 'group1', 'group2']); - - $this->assertCount(3, $violations); - } -} diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php deleted file mode 100644 index 57a374915c952..0000000000000 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php +++ /dev/null @@ -1,1281 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Validator; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Validator\Constraints\Callback; -use Symfony\Component\Validator\Constraints\GroupSequence; -use Symfony\Component\Validator\Constraints\Valid; -use Symfony\Component\Validator\ConstraintViolationInterface; -use Symfony\Component\Validator\Context\ExecutionContextInterface; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; -use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; -use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; -use Symfony\Component\Validator\Tests\Fixtures\Reference; - -/** - * @author Bernhard Schussek - */ -abstract class AbstractValidatorTest extends TestCase -{ - const ENTITY_CLASS = Entity::class; - - const REFERENCE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\Reference'; - - const LAZY_PROPERTY = 'Symfony\Component\Validator\Validator\LazyProperty'; - - /** - * @var FakeMetadataFactory - */ - public $metadataFactory; - - /** - * @var ClassMetadata - */ - public $metadata; - - /** - * @var ClassMetadata - */ - public $referenceMetadata; - - protected function setUp(): void - { - $this->metadataFactory = new FakeMetadataFactory(); - $this->metadata = new ClassMetadata(self::ENTITY_CLASS); - $this->referenceMetadata = new ClassMetadata(self::REFERENCE_CLASS); - $this->metadataFactory->addMetadata($this->metadata); - $this->metadataFactory->addMetadata($this->referenceMetadata); - $this->metadataFactory->addMetadata(new ClassMetadata(self::LAZY_PROPERTY)); - } - - protected function tearDown(): void - { - $this->metadataFactory = null; - $this->metadata = null; - $this->referenceMetadata = null; - } - - abstract protected function validate($value, $constraints = null, $groups = null); - - abstract protected function validateProperty($object, $propertyName, $groups = null); - - abstract protected function validatePropertyValue($object, $propertyName, $value, $groups = null); - - public function testValidate() - { - $callback = function ($value, ExecutionContextInterface $context) { - $this->assertNull($context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame('Bernhard', $context->getRoot()); - $this->assertSame('Bernhard', $context->getValue()); - $this->assertSame('Bernhard', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $constraint = new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ]); - - $violations = $this->validate('Bernhard', $constraint, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('', $violations[0]->getPropertyPath()); - $this->assertSame('Bernhard', $violations[0]->getRoot()); - $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testClassConstraint() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testPropertyConstraint() - { - $entity = new Entity(); - $entity->firstName = 'Bernhard'; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); - - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertSame('firstName', $context->getPropertyName()); - $this->assertSame('firstName', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Bernhard', $context->getValue()); - $this->assertSame('Bernhard', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('firstName', new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('firstName', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testGetterConstraint() - { - $entity = new Entity(); - $entity->setLastName('Schussek'); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->metadata->getPropertyMetadata('lastName'); - - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertSame('lastName', $context->getPropertyName()); - $this->assertSame('lastName', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Schussek', $context->getValue()); - $this->assertSame('Schussek', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addGetterConstraint('lastName', new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('lastName', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Schussek', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testArray() - { - $entity = new Entity(); - $array = ['key' => $entity]; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, $array) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($array, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($array, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('[key]', $violations[0]->getPropertyPath()); - $this->assertSame($array, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testRecursiveArray() - { - $entity = new Entity(); - $array = [2 => ['key' => $entity]]; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, $array) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('[2][key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($array, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($array, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('[2][key]', $violations[0]->getPropertyPath()); - $this->assertSame($array, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testTraversable() - { - $entity = new Entity(); - $traversable = new \ArrayIterator(['key' => $entity]); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($traversable, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($traversable, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('[key]', $violations[0]->getPropertyPath()); - $this->assertSame($traversable, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testRecursiveTraversable() - { - $entity = new Entity(); - $traversable = new \ArrayIterator([ - 2 => new \ArrayIterator(['key' => $entity]), - ]); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('[2][key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->metadata, $context->getMetadata()); - $this->assertSame($traversable, $context->getRoot()); - $this->assertSame($entity, $context->getValue()); - $this->assertSame($entity, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($traversable, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('[2][key]', $violations[0]->getPropertyPath()); - $this->assertSame($traversable, $violations[0]->getRoot()); - $this->assertSame($entity, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testReferenceClassConstraint() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('reference', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference, $context->getValue()); - $this->assertSame($entity->reference, $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testReferencePropertyConstraint() - { - $entity = new Entity(); - $entity->reference = new Reference(); - $entity->reference->value = 'Foobar'; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->referenceMetadata->getPropertyMetadata('value'); - - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertSame('value', $context->getPropertyName()); - $this->assertSame('reference.value', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Foobar', $context->getValue()); - $this->assertSame('Foobar', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addPropertyConstraint('value', new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference.value', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Foobar', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testReferenceGetterConstraint() - { - $entity = new Entity(); - $entity->reference = new Reference(); - $entity->reference->setPrivateValue('Bamboo'); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->referenceMetadata->getPropertyMetadata('privateValue'); - - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertSame('privateValue', $context->getPropertyName()); - $this->assertSame('reference.privateValue', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Bamboo', $context->getValue()); - $this->assertSame('Bamboo', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addPropertyConstraint('privateValue', new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference.privateValue', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Bamboo', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testsIgnoreNullReference() - { - $entity = new Entity(); - $entity->reference = null; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testFailOnScalarReferences() - { - $this->expectException('Symfony\Component\Validator\Exception\NoSuchMetadataException'); - $entity = new Entity(); - $entity->reference = 'string'; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - - $this->validate($entity); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testArrayReference($constraintMethod) - { - $entity = new Entity(); - $entity->reference = ['key' => new Reference()]; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('reference[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference['key'], $context->getValue()); - $this->assertSame($entity->reference['key'], $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->$constraintMethod('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference[key]', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testRecursiveArrayReference($constraintMethod) - { - $entity = new Entity(); - $entity->reference = [2 => ['key' => new Reference()]]; - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('reference[2][key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference[2]['key'], $context->getValue()); - $this->assertSame($entity->reference[2]['key'], $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->$constraintMethod('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testOnlyCascadedArraysAreTraversed() - { - $entity = new Entity(); - $entity->reference = ['key' => new Reference()]; - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Callback([ - 'callback' => function () {}, - 'groups' => 'Group', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testArrayTraversalCannotBeDisabled($constraintMethod) - { - $entity = new Entity(); - $entity->reference = ['key' => new Reference()]; - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->$constraintMethod('reference', new Valid([ - 'traverse' => false, - ])); - $this->referenceMetadata->addConstraint(new Callback($callback)); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testRecursiveArrayTraversalCannotBeDisabled($constraintMethod) - { - $entity = new Entity(); - $entity->reference = [2 => ['key' => new Reference()]]; - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->$constraintMethod('reference', new Valid([ - 'traverse' => false, - ])); - - $this->referenceMetadata->addConstraint(new Callback($callback)); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testIgnoreScalarsDuringArrayTraversal($constraintMethod) - { - $entity = new Entity(); - $entity->reference = ['string', 1234]; - - $this->metadata->$constraintMethod('reference', new Valid()); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - /** - * @dataProvider getConstraintMethods - */ - public function testIgnoreNullDuringArrayTraversal($constraintMethod) - { - $entity = new Entity(); - $entity->reference = [null]; - - $this->metadata->$constraintMethod('reference', new Valid()); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testTraversableReference() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator(['key' => new Reference()]); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('reference[key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference['key'], $context->getValue()); - $this->assertSame($entity->reference['key'], $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference[key]', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testDisableTraversableTraversal() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator(['key' => new Reference()]); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); - $this->metadata->addPropertyConstraint('reference', new Valid([ - 'traverse' => false, - ])); - $this->referenceMetadata->addConstraint(new Callback($callback)); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(0, $violations); - } - - public function testMetadataMustExistIfTraversalIsDisabled() - { - $this->expectException('Symfony\Component\Validator\Exception\NoSuchMetadataException'); - $entity = new Entity(); - $entity->reference = new \ArrayIterator(); - - $this->metadata->addPropertyConstraint('reference', new Valid([ - 'traverse' => false, - ])); - - $this->validate($entity); - } - - public function testEnableRecursiveTraversableTraversal() - { - $entity = new Entity(); - $entity->reference = new \ArrayIterator([ - 2 => new \ArrayIterator(['key' => new Reference()]), - ]); - - $callback = function ($value, ExecutionContextInterface $context) use ($entity) { - $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); - $this->assertNull($context->getPropertyName()); - $this->assertSame('reference[2][key]', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($this->referenceMetadata, $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame($entity->reference[2]['key'], $context->getValue()); - $this->assertSame($entity->reference[2]['key'], $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid([ - 'traverse' => true, - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group', - ])); - - $violations = $this->validate($entity, null, 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testValidateProperty() - { - $entity = new Entity(); - $entity->firstName = 'Bernhard'; - $entity->setLastName('Schussek'); - - $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); - - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertSame('firstName', $context->getPropertyName()); - $this->assertSame('firstName', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Bernhard', $context->getValue()); - $this->assertSame('Bernhard', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Other violation'); - }; - - $this->metadata->addPropertyConstraint('firstName', new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('lastName', new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validateProperty($entity, 'firstName', 'Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('firstName', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - /** - * https://github.com/symfony/symfony/issues/11604. - */ - public function testValidatePropertyWithoutConstraints() - { - $entity = new Entity(); - $violations = $this->validateProperty($entity, 'lastName'); - - $this->assertCount(0, $violations, '->validateProperty() returns no violations if no constraints have been configured for the property being validated'); - } - - public function testValidatePropertyValue() - { - $entity = new Entity(); - $entity->setLastName('Schussek'); - - $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { - $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); - - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertSame('firstName', $context->getPropertyName()); - $this->assertSame('firstName', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame($entity, $context->getRoot()); - $this->assertSame('Bernhard', $context->getValue()); - $this->assertSame('Bernhard', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Other violation'); - }; - - $this->metadata->addPropertyConstraint('firstName', new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('lastName', new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validatePropertyValue( - $entity, - 'firstName', - 'Bernhard', - 'Group' - ); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('firstName', $violations[0]->getPropertyPath()); - $this->assertSame($entity, $violations[0]->getRoot()); - $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - public function testValidatePropertyValueWithClassName() - { - $callback1 = function ($value, ExecutionContextInterface $context) { - $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); - - $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); - $this->assertSame('firstName', $context->getPropertyName()); - $this->assertSame('', $context->getPropertyPath()); - $this->assertSame('Group', $context->getGroup()); - $this->assertSame($propertyMetadatas[0], $context->getMetadata()); - $this->assertSame('Bernhard', $context->getRoot()); - $this->assertSame('Bernhard', $context->getValue()); - $this->assertSame('Bernhard', $value); - - $context->addViolation('Message %param%', ['%param%' => 'value']); - }; - - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Other violation'); - }; - - $this->metadata->addPropertyConstraint('firstName', new Callback([ - 'callback' => $callback1, - 'groups' => 'Group', - ])); - $this->metadata->addPropertyConstraint('lastName', new Callback([ - 'callback' => $callback2, - 'groups' => 'Group', - ])); - - $violations = $this->validatePropertyValue( - self::ENTITY_CLASS, - 'firstName', - 'Bernhard', - 'Group' - ); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Message value', $violations[0]->getMessage()); - $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); - $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); - $this->assertSame('', $violations[0]->getPropertyPath()); - $this->assertSame('Bernhard', $violations[0]->getRoot()); - $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); - $this->assertNull($violations[0]->getPlural()); - $this->assertNull($violations[0]->getCode()); - } - - /** - * https://github.com/symfony/symfony/issues/11604. - */ - public function testValidatePropertyValueWithoutConstraints() - { - $entity = new Entity(); - $violations = $this->validatePropertyValue($entity, 'lastName', 'foo'); - - $this->assertCount(0, $violations, '->validatePropertyValue() returns no violations if no constraints have been configured for the property being validated'); - } - - public function testValidateObjectOnlyOncePerGroup() - { - $entity = new Entity(); - $entity->reference = new Reference(); - $entity->reference2 = $entity->reference; - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->metadata->addPropertyConstraint('reference2', new Valid()); - $this->referenceMetadata->addConstraint(new Callback($callback)); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - public function testValidateDifferentObjectsSeparately() - { - $entity = new Entity(); - $entity->reference = new Reference(); - $entity->reference2 = new Reference(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->metadata->addPropertyConstraint('reference2', new Valid()); - $this->referenceMetadata->addConstraint(new Callback($callback)); - - $violations = $this->validate($entity); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(2, $violations); - } - - public function testValidateSingleGroup() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group 1', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group 2', - ])); - - $violations = $this->validate($entity, null, 'Group 2'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - } - - public function testValidateMultipleGroups() - { - $entity = new Entity(); - - $callback = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Message'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group 1', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback, - 'groups' => 'Group 2', - ])); - - $violations = $this->validate($entity, null, ['Group 1', 'Group 2']); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(2, $violations); - } - - public function testReplaceDefaultGroupByGroupSequenceObject() - { - $entity = new Entity(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 2'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 3'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => function () {}, - 'groups' => 'Group 1', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group 2', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 3', - ])); - - $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3', 'Entity']); - $this->metadata->setGroupSequence($sequence); - - $violations = $this->validate($entity, null, 'Default'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); - } - - public function testReplaceDefaultGroupByGroupSequenceArray() - { - $entity = new Entity(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 2'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 3'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => function () {}, - 'groups' => 'Group 1', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group 2', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 3', - ])); - - $sequence = ['Group 1', 'Group 2', 'Group 3', 'Entity']; - $this->metadata->setGroupSequence($sequence); - - $violations = $this->validate($entity, null, 'Default'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); - } - - public function testPropagateDefaultGroupToReferenceWhenReplacingDefaultGroup() - { - $entity = new Entity(); - $entity->reference = new Reference(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Default group'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in group sequence'); - }; - - $this->metadata->addPropertyConstraint('reference', new Valid()); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Default', - ])); - $this->referenceMetadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 1', - ])); - - $sequence = new GroupSequence(['Group 1', 'Entity']); - $this->metadata->setGroupSequence($sequence); - - $violations = $this->validate($entity, null, 'Default'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Violation in Default group', $violations[0]->getMessage()); - } - - public function testValidateCustomGroupWhenDefaultGroupWasReplaced() - { - $entity = new Entity(); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in other group'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in group sequence'); - }; - - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Other Group', - ])); - $this->metadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 1', - ])); - - $sequence = new GroupSequence(['Group 1', 'Entity']); - $this->metadata->setGroupSequence($sequence); - - $violations = $this->validate($entity, null, 'Other Group'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(1, $violations); - $this->assertSame('Violation in other group', $violations[0]->getMessage()); - } - - /** - * @dataProvider getTestReplaceDefaultGroup - */ - public function testReplaceDefaultGroup($sequence, array $assertViolations) - { - $entity = new GroupSequenceProviderEntity($sequence); - - $callback1 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 2'); - }; - $callback2 = function ($value, ExecutionContextInterface $context) { - $context->addViolation('Violation in Group 3'); - }; - - $metadata = new ClassMetadata(\get_class($entity)); - $metadata->addConstraint(new Callback([ - 'callback' => function () {}, - 'groups' => 'Group 1', - ])); - $metadata->addConstraint(new Callback([ - 'callback' => $callback1, - 'groups' => 'Group 2', - ])); - $metadata->addConstraint(new Callback([ - 'callback' => $callback2, - 'groups' => 'Group 3', - ])); - $metadata->setGroupSequenceProvider(true); - - $this->metadataFactory->addMetadata($metadata); - - $violations = $this->validate($entity, null, 'Default'); - - /* @var ConstraintViolationInterface[] $violations */ - $this->assertCount(\count($assertViolations), $violations); - foreach ($assertViolations as $key => $message) { - $this->assertSame($message, $violations[$key]->getMessage()); - } - } - - public function getConstraintMethods() - { - return [ - ['addPropertyConstraint'], - ['addGetterConstraint'], - ]; - } - - public function getTestReplaceDefaultGroup() - { - return [ - [ - 'sequence' => new GroupSequence(['Group 1', 'Group 2', 'Group 3', 'Entity']), - 'assertViolations' => [ - 'Violation in Group 2', - ], - ], - [ - 'sequence' => ['Group 1', 'Group 2', 'Group 3', 'Entity'], - 'assertViolations' => [ - 'Violation in Group 2', - ], - ], - [ - 'sequence' => new GroupSequence(['Group 1', ['Group 2', 'Group 3'], 'Entity']), - 'assertViolations' => [ - 'Violation in Group 2', - 'Violation in Group 3', - ], - ], - [ - 'sequence' => ['Group 1', ['Group 2', 'Group 3'], 'Entity'], - 'assertViolations' => [ - 'Violation in Group 2', - 'Violation in Group 3', - ], - ], - ]; - } -} diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index c7e26680f3c9b..f543ddf7d6c86 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -11,10 +11,13 @@ namespace Symfony\Component\Validator\Tests\Validator; +use PHPUnit\Framework\TestCase; use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Cascade; use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Length; @@ -22,24 +25,2033 @@ use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Required; +use Symfony\Component\Validator\Constraints\Traverse; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintValidatorFactory; +use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\Validator\Context\ExecutionContextFactory; +use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB; use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\CascadedChild; use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods; +use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint; +use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; +use Symfony\Component\Validator\Tests\Fixtures\Reference; +use Symfony\Component\Validator\Validator\LazyProperty; use Symfony\Component\Validator\Validator\RecursiveValidator; use Symfony\Component\Validator\Validator\ValidatorInterface; -class RecursiveValidatorTest extends AbstractTest +class RecursiveValidatorTest extends TestCase { + private const ENTITY_CLASS = Entity::class; + private const REFERENCE_CLASS = Reference::class; + + /** + * @var FakeMetadataFactory + */ + private $metadataFactory; + + /** + * @var ClassMetadata + */ + private $metadata; + + /** + * @var ClassMetadata + */ + private $referenceMetadata; + + /** + * @var ValidatorInterface + */ + private $validator; + + protected function setUp(): void + { + $this->metadataFactory = new FakeMetadataFactory(); + $this->metadata = new ClassMetadata(self::ENTITY_CLASS); + $this->referenceMetadata = new ClassMetadata(self::REFERENCE_CLASS); + $this->metadataFactory->addMetadata($this->metadata); + $this->metadataFactory->addMetadata($this->referenceMetadata); + $this->metadataFactory->addMetadata(new ClassMetadata(LazyProperty::class)); + + $this->validator = $this->createValidator($this->metadataFactory); + } + + protected function tearDown(): void + { + $this->metadataFactory = null; + $this->metadata = null; + $this->referenceMetadata = null; + } + + protected function validate($value, $constraints = null, $groups = null) + { + return $this->validator->validate($value, $constraints, $groups); + } + + protected function validateProperty($object, $propertyName, $groups = null) + { + return $this->validator->validateProperty($object, $propertyName, $groups); + } + + protected function validatePropertyValue($object, $propertyName, $value, $groups = null) + { + return $this->validator->validatePropertyValue($object, $propertyName, $value, $groups); + } + + public function testValidate() + { + $callback = function ($value, ExecutionContextInterface $context) { + $this->assertNull($context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame('Bernhard', $context->getRoot()); + $this->assertSame('Bernhard', $context->getValue()); + $this->assertSame('Bernhard', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $constraint = new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ]); + + $violations = $this->validate('Bernhard', $constraint, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('', $violations[0]->getPropertyPath()); + $this->assertSame('Bernhard', $violations[0]->getRoot()); + $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testClassConstraint() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testPropertyConstraint() + { + $entity = new Entity(); + $entity->firstName = 'Bernhard'; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); + + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertSame('firstName', $context->getPropertyName()); + $this->assertSame('firstName', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Bernhard', $context->getValue()); + $this->assertSame('Bernhard', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('firstName', new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('firstName', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testGetterConstraint() + { + $entity = new Entity(); + $entity->setLastName('Schussek'); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->metadata->getPropertyMetadata('lastName'); + + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertSame('lastName', $context->getPropertyName()); + $this->assertSame('lastName', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Schussek', $context->getValue()); + $this->assertSame('Schussek', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addGetterConstraint('lastName', new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('lastName', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Schussek', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testArray() + { + $entity = new Entity(); + $array = ['key' => $entity]; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, $array) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($array, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($array, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('[key]', $violations[0]->getPropertyPath()); + $this->assertSame($array, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testRecursiveArray() + { + $entity = new Entity(); + $array = [2 => ['key' => $entity]]; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, $array) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('[2][key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($array, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($array, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('[2][key]', $violations[0]->getPropertyPath()); + $this->assertSame($array, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testTraversable() + { + $entity = new Entity(); + $traversable = new \ArrayIterator(['key' => $entity]); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($traversable, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($traversable, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('[key]', $violations[0]->getPropertyPath()); + $this->assertSame($traversable, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testRecursiveTraversable() + { + $entity = new Entity(); + $traversable = new \ArrayIterator([ + 2 => new \ArrayIterator(['key' => $entity]), + ]); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('[2][key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($traversable, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($traversable, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('[2][key]', $violations[0]->getPropertyPath()); + $this->assertSame($traversable, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testReferenceClassConstraint() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('reference', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference, $context->getValue()); + $this->assertSame($entity->reference, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testReferencePropertyConstraint() + { + $entity = new Entity(); + $entity->reference = new Reference(); + $entity->reference->value = 'Foobar'; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->referenceMetadata->getPropertyMetadata('value'); + + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertSame('value', $context->getPropertyName()); + $this->assertSame('reference.value', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Foobar', $context->getValue()); + $this->assertSame('Foobar', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addPropertyConstraint('value', new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference.value', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Foobar', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testReferenceGetterConstraint() + { + $entity = new Entity(); + $entity->reference = new Reference(); + $entity->reference->setPrivateValue('Bamboo'); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->referenceMetadata->getPropertyMetadata('privateValue'); + + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertSame('privateValue', $context->getPropertyName()); + $this->assertSame('reference.privateValue', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Bamboo', $context->getValue()); + $this->assertSame('Bamboo', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addPropertyConstraint('privateValue', new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference.privateValue', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Bamboo', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testsIgnoreNullReference() + { + $entity = new Entity(); + $entity->reference = null; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testFailOnScalarReferences() + { + $this->expectException('Symfony\Component\Validator\Exception\NoSuchMetadataException'); + $entity = new Entity(); + $entity->reference = 'string'; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + + $this->validate($entity); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testArrayReference($constraintMethod) + { + $entity = new Entity(); + $entity->reference = ['key' => new Reference()]; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('reference[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference['key'], $context->getValue()); + $this->assertSame($entity->reference['key'], $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->$constraintMethod('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference[key]', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testRecursiveArrayReference($constraintMethod) + { + $entity = new Entity(); + $entity->reference = [2 => ['key' => new Reference()]]; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('reference[2][key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference[2]['key'], $context->getValue()); + $this->assertSame($entity->reference[2]['key'], $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->$constraintMethod('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testOnlyCascadedArraysAreTraversed() + { + $entity = new Entity(); + $entity->reference = ['key' => new Reference()]; + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Callback([ + 'callback' => function () {}, + 'groups' => 'Group', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testArrayTraversalCannotBeDisabled($constraintMethod) + { + $entity = new Entity(); + $entity->reference = ['key' => new Reference()]; + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->$constraintMethod('reference', new Valid([ + 'traverse' => false, + ])); + $this->referenceMetadata->addConstraint(new Callback($callback)); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testRecursiveArrayTraversalCannotBeDisabled($constraintMethod) + { + $entity = new Entity(); + $entity->reference = [2 => ['key' => new Reference()]]; + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->$constraintMethod('reference', new Valid([ + 'traverse' => false, + ])); + + $this->referenceMetadata->addConstraint(new Callback($callback)); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testIgnoreScalarsDuringArrayTraversal($constraintMethod) + { + $entity = new Entity(); + $entity->reference = ['string', 1234]; + + $this->metadata->$constraintMethod('reference', new Valid()); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + /** + * @dataProvider getConstraintMethods + */ + public function testIgnoreNullDuringArrayTraversal($constraintMethod) + { + $entity = new Entity(); + $entity->reference = [null]; + + $this->metadata->$constraintMethod('reference', new Valid()); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testTraversableReference() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator(['key' => new Reference()]); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('reference[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference['key'], $context->getValue()); + $this->assertSame($entity->reference['key'], $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference[key]', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference['key'], $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testDisableTraversableTraversal() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator(['key' => new Reference()]); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); + $this->metadata->addPropertyConstraint('reference', new Valid([ + 'traverse' => false, + ])); + $this->referenceMetadata->addConstraint(new Callback($callback)); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testMetadataMustExistIfTraversalIsDisabled() + { + $this->expectException('Symfony\Component\Validator\Exception\NoSuchMetadataException'); + $entity = new Entity(); + $entity->reference = new \ArrayIterator(); + + $this->metadata->addPropertyConstraint('reference', new Valid([ + 'traverse' => false, + ])); + + $this->validate($entity); + } + + public function testEnableRecursiveTraversableTraversal() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator([ + 2 => new \ArrayIterator(['key' => new Reference()]), + ]); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('reference[2][key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference[2]['key'], $context->getValue()); + $this->assertSame($entity->reference[2]['key'], $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid([ + 'traverse' => true, + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, null, 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('reference[2][key]', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference[2]['key'], $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testValidateProperty() + { + $entity = new Entity(); + $entity->firstName = 'Bernhard'; + $entity->setLastName('Schussek'); + + $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); + + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertSame('firstName', $context->getPropertyName()); + $this->assertSame('firstName', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Bernhard', $context->getValue()); + $this->assertSame('Bernhard', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Other violation'); + }; + + $this->metadata->addPropertyConstraint('firstName', new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('lastName', new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validateProperty($entity, 'firstName', 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('firstName', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + /** + * https://github.com/symfony/symfony/issues/11604. + */ + public function testValidatePropertyWithoutConstraints() + { + $entity = new Entity(); + $violations = $this->validateProperty($entity, 'lastName'); + + $this->assertCount(0, $violations, '->validateProperty() returns no violations if no constraints have been configured for the property being validated'); + } + + public function testValidatePropertyValue() + { + $entity = new Entity(); + $entity->setLastName('Schussek'); + + $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { + $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); + + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertSame('firstName', $context->getPropertyName()); + $this->assertSame('firstName', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame('Bernhard', $context->getValue()); + $this->assertSame('Bernhard', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Other violation'); + }; + + $this->metadata->addPropertyConstraint('firstName', new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('lastName', new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validatePropertyValue( + $entity, + 'firstName', + 'Bernhard', + 'Group' + ); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('firstName', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testValidatePropertyValueWithClassName() + { + $callback1 = function ($value, ExecutionContextInterface $context) { + $propertyMetadatas = $this->metadata->getPropertyMetadata('firstName'); + + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertSame('firstName', $context->getPropertyName()); + $this->assertSame('', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($propertyMetadatas[0], $context->getMetadata()); + $this->assertSame('Bernhard', $context->getRoot()); + $this->assertSame('Bernhard', $context->getValue()); + $this->assertSame('Bernhard', $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Other violation'); + }; + + $this->metadata->addPropertyConstraint('firstName', new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('lastName', new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validatePropertyValue( + self::ENTITY_CLASS, + 'firstName', + 'Bernhard', + 'Group' + ); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('', $violations[0]->getPropertyPath()); + $this->assertSame('Bernhard', $violations[0]->getRoot()); + $this->assertSame('Bernhard', $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + /** + * https://github.com/symfony/symfony/issues/11604. + */ + public function testValidatePropertyValueWithoutConstraints() + { + $entity = new Entity(); + $violations = $this->validatePropertyValue($entity, 'lastName', 'foo'); + + $this->assertCount(0, $violations, '->validatePropertyValue() returns no violations if no constraints have been configured for the property being validated'); + } + + public function testValidateObjectOnlyOncePerGroup() + { + $entity = new Entity(); + $entity->reference = new Reference(); + $entity->reference2 = $entity->reference; + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->metadata->addPropertyConstraint('reference2', new Valid()); + $this->referenceMetadata->addConstraint(new Callback($callback)); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + public function testValidateDifferentObjectsSeparately() + { + $entity = new Entity(); + $entity->reference = new Reference(); + $entity->reference2 = new Reference(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->metadata->addPropertyConstraint('reference2', new Valid()); + $this->referenceMetadata->addConstraint(new Callback($callback)); + + $violations = $this->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(2, $violations); + } + + public function testValidateSingleGroup() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group 1', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group 2', + ])); + + $violations = $this->validate($entity, null, 'Group 2'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + public function testValidateMultipleGroups() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group 1', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group 2', + ])); + + $violations = $this->validate($entity, null, ['Group 1', 'Group 2']); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(2, $violations); + } + + public function testReplaceDefaultGroupByGroupSequenceObject() + { + $entity = new Entity(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 2'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 3'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => function () {}, + 'groups' => 'Group 1', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group 2', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 3', + ])); + + $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3', 'Entity']); + $this->metadata->setGroupSequence($sequence); + + $violations = $this->validate($entity, null, 'Default'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); + } + + public function testReplaceDefaultGroupByGroupSequenceArray() + { + $entity = new Entity(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 2'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 3'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => function () {}, + 'groups' => 'Group 1', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group 2', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 3', + ])); + + $sequence = ['Group 1', 'Group 2', 'Group 3', 'Entity']; + $this->metadata->setGroupSequence($sequence); + + $violations = $this->validate($entity, null, 'Default'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); + } + + public function testPropagateDefaultGroupToReferenceWhenReplacingDefaultGroup() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Default group'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in group sequence'); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Default', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 1', + ])); + + $sequence = new GroupSequence(['Group 1', 'Entity']); + $this->metadata->setGroupSequence($sequence); + + $violations = $this->validate($entity, null, 'Default'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Violation in Default group', $violations[0]->getMessage()); + } + + public function testValidateCustomGroupWhenDefaultGroupWasReplaced() + { + $entity = new Entity(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in other group'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in group sequence'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Other Group', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 1', + ])); + + $sequence = new GroupSequence(['Group 1', 'Entity']); + $this->metadata->setGroupSequence($sequence); + + $violations = $this->validate($entity, null, 'Other Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Violation in other group', $violations[0]->getMessage()); + } + + /** + * @dataProvider getTestReplaceDefaultGroup + */ + public function testReplaceDefaultGroup($sequence, array $assertViolations) + { + $entity = new GroupSequenceProviderEntity($sequence); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 2'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Violation in Group 3'); + }; + + $metadata = new ClassMetadata(\get_class($entity)); + $metadata->addConstraint(new Callback([ + 'callback' => function () {}, + 'groups' => 'Group 1', + ])); + $metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group 2', + ])); + $metadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 3', + ])); + $metadata->setGroupSequenceProvider(true); + + $this->metadataFactory->addMetadata($metadata); + + $violations = $this->validate($entity, null, 'Default'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(\count($assertViolations), $violations); + foreach ($assertViolations as $key => $message) { + $this->assertSame($message, $violations[$key]->getMessage()); + } + } + + public function getConstraintMethods() + { + return [ + ['addPropertyConstraint'], + ['addGetterConstraint'], + ]; + } + + public function getTestReplaceDefaultGroup() + { + return [ + [ + 'sequence' => new GroupSequence(['Group 1', 'Group 2', 'Group 3', 'Entity']), + 'assertViolations' => [ + 'Violation in Group 2', + ], + ], + [ + 'sequence' => ['Group 1', 'Group 2', 'Group 3', 'Entity'], + 'assertViolations' => [ + 'Violation in Group 2', + ], + ], + [ + 'sequence' => new GroupSequence(['Group 1', ['Group 2', 'Group 3'], 'Entity']), + 'assertViolations' => [ + 'Violation in Group 2', + 'Violation in Group 3', + ], + ], + [ + 'sequence' => ['Group 1', ['Group 2', 'Group 3'], 'Entity'], + 'assertViolations' => [ + 'Violation in Group 2', + 'Violation in Group 3', + ], + ], + ]; + } + + public function testValidateConstraintWithoutGroup() + { + $violations = $this->validator->validate(null, new NotNull()); + + $this->assertCount(1, $violations); + } + + public function testValidateWithEmptyArrayAsConstraint() + { + $violations = $this->validator->validate('value', []); + $this->assertCount(0, $violations); + } + + public function testGroupSequenceAbortsAfterFailedGroup() + { + $entity = new Entity(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message 1'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message 2'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => function () {}, + 'groups' => 'Group 1', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group 2', + ])); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 3', + ])); + + $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3']); + $violations = $this->validator->validate($entity, new Valid(), $sequence); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message 1', $violations[0]->getMessage()); + } + + public function testGroupSequenceIncludesReferences() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Reference violation 1'); + }; + $callback2 = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Reference violation 2'); + }; + + $this->metadata->addPropertyConstraint('reference', new Valid()); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group 1', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group 2', + ])); + + $sequence = new GroupSequence(['Group 1', 'Entity']); + $violations = $this->validator->validate($entity, new Valid(), $sequence); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Reference violation 1', $violations[0]->getMessage()); + } + + public function testValidateInSeparateContext() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback1 = function ($value, ExecutionContextInterface $context) use ($entity) { + $violations = $context + ->getValidator() + // Since the validator is not context aware, the group must + // be passed explicitly + ->validate($value->reference, new Valid(), 'Group') + ; + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('', $violations[0]->getPropertyPath()); + + // The root is different as we're in a new context + $this->assertSame($entity->reference, $violations[0]->getRoot()); + $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + + // Verify that this method is called + $context->addViolation('Separate violation'); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity->reference, $context->getRoot()); + $this->assertSame($entity->reference, $context->getValue()); + $this->assertSame($entity->reference, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validator->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Separate violation', $violations[0]->getMessage()); + } + + public function testValidateInContext() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $previousValue = $context->getValue(); + $previousObject = $context->getObject(); + $previousMetadata = $context->getMetadata(); + $previousPath = $context->getPropertyPath(); + $previousGroup = $context->getGroup(); + + $context + ->getValidator() + ->inContext($context) + ->atPath('subpath') + ->validate($value->reference) + ; + + // context changes shouldn't leak out of the validate() call + $this->assertSame($previousValue, $context->getValue()); + $this->assertSame($previousObject, $context->getObject()); + $this->assertSame($previousMetadata, $context->getMetadata()); + $this->assertSame($previousPath, $context->getPropertyPath()); + $this->assertSame($previousGroup, $context->getGroup()); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('subpath', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference, $context->getValue()); + $this->assertSame($entity->reference, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validator->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('subpath', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testValidateArrayInContext() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback1 = function ($value, ExecutionContextInterface $context) { + $previousValue = $context->getValue(); + $previousObject = $context->getObject(); + $previousMetadata = $context->getMetadata(); + $previousPath = $context->getPropertyPath(); + $previousGroup = $context->getGroup(); + + $context + ->getValidator() + ->inContext($context) + ->atPath('subpath') + ->validate(['key' => $value->reference]) + ; + + // context changes shouldn't leak out of the validate() call + $this->assertSame($previousValue, $context->getValue()); + $this->assertSame($previousObject, $context->getObject()); + $this->assertSame($previousMetadata, $context->getMetadata()); + $this->assertSame($previousPath, $context->getPropertyPath()); + $this->assertSame($previousGroup, $context->getGroup()); + }; + + $callback2 = function ($value, ExecutionContextInterface $context) use ($entity) { + $this->assertSame($this::REFERENCE_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('subpath[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->referenceMetadata, $context->getMetadata()); + $this->assertSame($entity, $context->getRoot()); + $this->assertSame($entity->reference, $context->getValue()); + $this->assertSame($entity->reference, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback1, + 'groups' => 'Group', + ])); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback2, + 'groups' => 'Group', + ])); + + $violations = $this->validator->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('subpath[key]', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame($entity->reference, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testTraverseTraversableByDefault() + { + $entity = new Entity(); + $traversable = new \ArrayIterator(['key' => $entity]); + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, $traversable) { + $this->assertSame($this::ENTITY_CLASS, $context->getClassName()); + $this->assertNull($context->getPropertyName()); + $this->assertSame('[key]', $context->getPropertyPath()); + $this->assertSame('Group', $context->getGroup()); + $this->assertSame($this->metadata, $context->getMetadata()); + $this->assertSame($traversable, $context->getRoot()); + $this->assertSame($entity, $context->getValue()); + $this->assertSame($entity, $value); + + $context->addViolation('Message %param%', ['%param%' => 'value']); + }; + + $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($traversable, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('[key]', $violations[0]->getPropertyPath()); + $this->assertSame($traversable, $violations[0]->getRoot()); + $this->assertSame($entity, $violations[0]->getInvalidValue()); + $this->assertNull($violations[0]->getPlural()); + $this->assertNull($violations[0]->getCode()); + } + + public function testTraversalEnabledOnClass() + { + $entity = new Entity(); + $traversable = new \ArrayIterator(['key' => $entity]); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $traversableMetadata = new ClassMetadata('ArrayIterator'); + $traversableMetadata->addConstraint(new Traverse(true)); + + $this->metadataFactory->addMetadata($traversableMetadata); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($traversable, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + public function testTraversalDisabledOnClass() + { + $entity = new Entity(); + $traversable = new \ArrayIterator(['key' => $entity]); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $traversableMetadata = new ClassMetadata('ArrayIterator'); + $traversableMetadata->addConstraint(new Traverse(false)); + + $this->metadataFactory->addMetadata($traversableMetadata); + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($traversable, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testExpectTraversableIfTraversalEnabledOnClass() + { + $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); + $entity = new Entity(); + + $this->metadata->addConstraint(new Traverse(true)); + + $this->validator->validate($entity); + } + + public function testReferenceTraversalDisabledOnClass() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator(['key' => new Reference()]); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $traversableMetadata = new ClassMetadata('ArrayIterator'); + $traversableMetadata->addConstraint(new Traverse(false)); + + $this->metadataFactory->addMetadata($traversableMetadata); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('reference', new Valid()); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testReferenceTraversalEnabledOnReferenceDisabledOnClass() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator(['key' => new Reference()]); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $traversableMetadata = new ClassMetadata('ArrayIterator'); + $traversableMetadata->addConstraint(new Traverse(false)); + + $this->metadataFactory->addMetadata($traversableMetadata); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('reference', new Valid([ + 'traverse' => true, + ])); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testReferenceTraversalDisabledOnReferenceEnabledOnClass() + { + $entity = new Entity(); + $entity->reference = new \ArrayIterator(['key' => new Reference()]); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $traversableMetadata = new ClassMetadata('ArrayIterator'); + $traversableMetadata->addConstraint(new Traverse(true)); + + $this->metadataFactory->addMetadata($traversableMetadata); + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + $this->metadata->addPropertyConstraint('reference', new Valid([ + 'traverse' => false, + ])); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + public function testReferenceCascadeDisabledByDefault() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + /** + * @requires PHP 7.4 + */ + public function testReferenceCascadeEnabledIgnoresUntyped() + { + $entity = new Entity(); + $entity->reference = new Reference(); + + $this->metadata->addConstraint(new Cascade()); + + $callback = function ($value, ExecutionContextInterface $context) { + $this->fail('Should not be called'); + }; + + $this->referenceMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(0, $violations); + } + + /** + * @requires PHP 7.4 + */ + public function testTypedReferenceCascadeEnabled() + { + $entity = new CascadingEntity(); + $entity->requiredChild = new CascadedChild(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->buildViolation('Invalid child') + ->atPath('name') + ->addViolation() + ; + }; + + $cascadingMetadata = new ClassMetadata(CascadingEntity::class); + $cascadingMetadata->addConstraint(new Cascade()); + + $cascadedMetadata = new ClassMetadata(CascadedChild::class); + $cascadedMetadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => 'Group', + ])); + + $this->metadataFactory->addMetadata($cascadingMetadata); + $this->metadataFactory->addMetadata($cascadedMetadata); + + $violations = $this->validate($entity, new Valid(), 'Group'); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertInstanceOf(Callback::class, $violations->get(0)->getConstraint()); + } + + public function testAddCustomizedViolation() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->buildViolation('Message %param%') + ->setParameter('%param%', 'value') + ->setInvalidValue('Invalid value') + ->setPlural(2) + ->setCode('42') + ->addViolation(); + }; + + $this->metadata->addConstraint(new Callback($callback)); + + $violations = $this->validator->validate($entity); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + $this->assertSame('Message value', $violations[0]->getMessage()); + $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); + $this->assertSame(['%param%' => 'value'], $violations[0]->getParameters()); + $this->assertSame('', $violations[0]->getPropertyPath()); + $this->assertSame($entity, $violations[0]->getRoot()); + $this->assertSame('Invalid value', $violations[0]->getInvalidValue()); + $this->assertSame(2, $violations[0]->getPlural()); + $this->assertSame('42', $violations[0]->getCode()); + } + + public function testNoDuplicateValidationIfClassConstraintInMultipleGroups() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addConstraint(new Callback([ + 'callback' => $callback, + 'groups' => ['Group 1', 'Group 2'], + ])); + + $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + public function testNoDuplicateValidationIfPropertyConstraintInMultipleGroups() + { + $entity = new Entity(); + + $callback = function ($value, ExecutionContextInterface $context) { + $context->addViolation('Message'); + }; + + $this->metadata->addPropertyConstraint('firstName', new Callback([ + 'callback' => $callback, + 'groups' => ['Group 1', 'Group 2'], + ])); + + $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); + + /* @var ConstraintViolationInterface[] $violations */ + $this->assertCount(1, $violations); + } + + public function testValidateFailsIfNoConstraintsAndNoObjectOrArray() + { + $this->expectException('Symfony\Component\Validator\Exception\RuntimeException'); + $this->validate('Foobar'); + } + + public function testAccessCurrentObject() + { + $called = false; + $entity = new Entity(); + $entity->firstName = 'Bernhard'; + $entity->data = ['firstName' => 'Bernhard']; + + $callback = function ($value, ExecutionContextInterface $context) use ($entity, &$called) { + $called = true; + $this->assertSame($entity, $context->getObject()); + }; + + $this->metadata->addConstraint(new Callback($callback)); + $this->metadata->addPropertyConstraint('firstName', new Callback($callback)); + $this->metadata->addPropertyConstraint('data', new Collection(['firstName' => new Expression('value == this.firstName')])); + + $this->validator->validate($entity); + + $this->assertTrue($called); + } + + public function testInitializeObjectsOnFirstValidation() + { + $entity = new Entity(); + $entity->initialized = false; + + // prepare initializers that set "initialized" to true + $initializer1 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock(); + $initializer2 = $this->getMockBuilder('Symfony\\Component\\Validator\\ObjectInitializerInterface')->getMock(); + + $initializer1->expects($this->once()) + ->method('initialize') + ->with($entity) + ->willReturnCallback(function ($object) { + $object->initialized = true; + }); + + $initializer2->expects($this->once()) + ->method('initialize') + ->with($entity); + + $this->validator = $this->createValidator($this->metadataFactory, [ + $initializer1, + $initializer2, + ]); + + // prepare constraint which + // * checks that "initialized" is set to true + // * validates the object again + $callback = function ($object, ExecutionContextInterface $context) { + $this->assertTrue($object->initialized); + + // validate again in same group + $validator = $context->getValidator()->inContext($context); + + $validator->validate($object); + + // validate again in other group + $validator->validate($object, null, 'SomeGroup'); + }; + + $this->metadata->addConstraint(new Callback($callback)); + + $this->validate($entity); + + $this->assertTrue($entity->initialized); + } + + public function testPassConstraintToViolation() + { + $constraint = new FailingConstraint(); + $violations = $this->validate('Foobar', $constraint); + + $this->assertCount(1, $violations); + $this->assertSame($constraint, $violations[0]->getConstraint()); + } + + public function testCollectionConstraitViolationHasCorrectContext() + { + $data = [ + 'foo' => 'fooValue', + ]; + + // Missing field must not be the first in the collection validation + $constraint = new Collection([ + 'foo' => new NotNull(), + 'bar' => new NotNull(), + ]); + + $violations = $this->validate($data, $constraint); + + $this->assertCount(1, $violations); + $this->assertSame($constraint, $violations[0]->getConstraint()); + } + + public function testNestedObjectIsNotValidatedIfGroupInValidConstraintIsNotValidated() + { + $entity = new Entity(); + $entity->firstName = ''; + $reference = new Reference(); + $reference->value = ''; + $entity->childA = $reference; + + $this->metadata->addPropertyConstraint('firstName', new NotBlank(['groups' => 'group1'])); + $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => 'group1'])); + $this->referenceMetadata->addPropertyConstraint('value', new NotBlank()); + + $violations = $this->validator->validate($entity, null, []); + + $this->assertCount(0, $violations); + } + + public function testNestedObjectIsValidatedIfGroupInValidConstraintIsValidated() + { + $entity = new Entity(); + $entity->firstName = ''; + $reference = new Reference(); + $reference->value = ''; + $entity->childA = $reference; + + $this->metadata->addPropertyConstraint('firstName', new NotBlank(['groups' => 'group1'])); + $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => 'group1'])); + $this->referenceMetadata->addPropertyConstraint('value', new NotBlank(['groups' => 'group1'])); + + $violations = $this->validator->validate($entity, null, ['Default', 'group1']); + + $this->assertCount(2, $violations); + } + + public function testNestedObjectIsValidatedInMultipleGroupsIfGroupInValidConstraintIsValidated() + { + $entity = new Entity(); + $entity->firstName = null; + + $reference = new Reference(); + $reference->value = null; + + $entity->childA = $reference; + + $this->metadata->addPropertyConstraint('firstName', new NotBlank()); + $this->metadata->addPropertyConstraint('childA', new Valid(['groups' => ['group1', 'group2']])); + + $this->referenceMetadata->addPropertyConstraint('value', new NotBlank(['groups' => 'group1'])); + $this->referenceMetadata->addPropertyConstraint('value', new NotNull(['groups' => 'group2'])); + + $violations = $this->validator->validate($entity, null, ['Default', 'group1', 'group2']); + + $this->assertCount(3, $violations); + } + protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = []): ValidatorInterface { $translator = new IdentityTranslator(); diff --git a/src/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php b/src/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php index a09c8fc3c0dfe..4f7b6d66b585d 100644 --- a/src/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php +++ b/src/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php @@ -11,12 +11,18 @@ namespace Symfony\Component\Validator\Tests; +use Doctrine\Common\Annotations\CachedReader; +use Doctrine\Common\Annotations\Reader; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\ValidatorBuilder; class ValidatorBuilderTest extends TestCase { + use ExpectDeprecationTrait; + /** * @var ValidatorBuilder */ @@ -74,9 +80,74 @@ public function testAddMethodMappings() $this->assertSame($this->builder, $this->builder->addMethodMappings([])); } + /** + * @group legacy + */ public function testEnableAnnotationMapping() { + $this->expectDeprecation('Since symfony/validator 5.2: Not passing true as first argument to "Symfony\Component\Validator\ValidatorBuilder::enableAnnotationMapping" is deprecated. Pass true and call "addDefaultDoctrineAnnotationReader()" if you want to enable annotation mapping with Doctrine Annotations.'); $this->assertSame($this->builder, $this->builder->enableAnnotationMapping()); + + $loaders = $this->builder->getLoaders(); + $this->assertCount(1, $loaders); + $this->assertInstanceOf(AnnotationLoader::class, $loaders[0]); + + $r = new \ReflectionProperty(AnnotationLoader::class, 'reader'); + $r->setAccessible(true); + + $this->assertInstanceOf(CachedReader::class, $r->getValue($loaders[0])); + } + + public function testEnableAnnotationMappingWithDefaultDoctrineAnnotationReader() + { + $this->assertSame($this->builder, $this->builder->enableAnnotationMapping(true)); + $this->assertSame($this->builder, $this->builder->addDefaultDoctrineAnnotationReader()); + + $loaders = $this->builder->getLoaders(); + $this->assertCount(1, $loaders); + $this->assertInstanceOf(AnnotationLoader::class, $loaders[0]); + + $r = new \ReflectionProperty(AnnotationLoader::class, 'reader'); + $r->setAccessible(true); + + $this->assertInstanceOf(CachedReader::class, $r->getValue($loaders[0])); + } + + /** + * @group legacy + */ + public function testEnableAnnotationMappingWithCustomDoctrineAnnotationReaderLegacy() + { + $reader = $this->createMock(Reader::class); + + $this->expectDeprecation('Since symfony/validator 5.2: Passing an instance of "'.\get_class($reader).'" as first argument to "Symfony\Component\Validator\ValidatorBuilder::enableAnnotationMapping" is deprecated. Pass true instead and call setDoctrineAnnotationReader() if you want to enable annotation mapping with Doctrine Annotations.'); + $this->assertSame($this->builder, $this->builder->enableAnnotationMapping($reader)); + + $loaders = $this->builder->getLoaders(); + $this->assertCount(1, $loaders); + $this->assertInstanceOf(AnnotationLoader::class, $loaders[0]); + + $r = new \ReflectionProperty(AnnotationLoader::class, 'reader'); + $r->setAccessible(true); + + $this->assertSame($reader, $r->getValue($loaders[0])); + } + + public function testEnableAnnotationMappingWithCustomDoctrineAnnotationReader() + { + $reader = $this->createMock(Reader::class); + + $this->assertSame($this->builder, $this->builder->enableAnnotationMapping(true)); + $this->assertSame($this->builder, $this->builder->setDoctrineAnnotationReader($reader)); + + $loaders = $this->builder->getLoaders(); + $this->assertCount(1, $loaders); + $this->assertInstanceOf(AnnotationLoader::class, $loaders[0]); + + $r = new \ReflectionProperty(AnnotationLoader::class, 'reader'); + $r->setAccessible(true); + + $this->assertSame($reader, $r->getValue($loaders[0])); } public function testDisableAnnotationMapping() diff --git a/src/Symfony/Component/Validator/ValidatorBuilder.php b/src/Symfony/Component/Validator/ValidatorBuilder.php index e85bba34d120f..59698f327c000 100644 --- a/src/Symfony/Component/Validator/ValidatorBuilder.php +++ b/src/Symfony/Component/Validator/ValidatorBuilder.php @@ -17,7 +17,6 @@ use Doctrine\Common\Cache\ArrayCache; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Validator\Context\ExecutionContextFactory; -use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; @@ -53,6 +52,7 @@ class ValidatorBuilder * @var Reader|null */ private $annotationReader; + private $enableAnnotationMapping = false; /** * @var MetadataFactoryInterface|null @@ -212,23 +212,28 @@ public function addMethodMappings(array $methodNames) /** * Enables annotation based constraint mapping. * + * @param bool $skipDoctrineAnnotations + * * @return $this */ - public function enableAnnotationMapping(Reader $annotationReader = null) + public function enableAnnotationMapping(/* bool $skipDoctrineAnnotations = true */) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.'); } - if (null === $annotationReader) { - if (!class_exists(AnnotationReader::class) || !class_exists(ArrayCache::class)) { - throw new LogicException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.'); - } - - $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); + $skipDoctrineAnnotations = 1 > \func_num_args() ? false : func_get_arg(0); + if (false === $skipDoctrineAnnotations || null === $skipDoctrineAnnotations) { + trigger_deprecation('symfony/validator', '5.2', 'Not passing true as first argument to "%s" is deprecated. Pass true and call "addDefaultDoctrineAnnotationReader()" if you want to enable annotation mapping with Doctrine Annotations.', __METHOD__); + $this->addDefaultDoctrineAnnotationReader(); + } elseif ($skipDoctrineAnnotations instanceof Reader) { + trigger_deprecation('symfony/validator', '5.2', 'Passing an instance of "%s" as first argument to "%s" is deprecated. Pass true instead and call setDoctrineAnnotationReader() if you want to enable annotation mapping with Doctrine Annotations.', get_debug_type($skipDoctrineAnnotations), __METHOD__); + $this->setDoctrineAnnotationReader($skipDoctrineAnnotations); + } elseif (true !== $skipDoctrineAnnotations) { + throw new \TypeError(sprintf('"%s": Argument 1 is expected to be a boolean, "%s" given.', __METHOD__, get_debug_type($skipDoctrineAnnotations))); } - $this->annotationReader = $annotationReader; + $this->enableAnnotationMapping = true; return $this; } @@ -240,11 +245,32 @@ public function enableAnnotationMapping(Reader $annotationReader = null) */ public function disableAnnotationMapping() { + $this->enableAnnotationMapping = false; $this->annotationReader = null; return $this; } + /** + * @return $this + */ + public function setDoctrineAnnotationReader(?Reader $reader): self + { + $this->annotationReader = $reader; + + return $this; + } + + /** + * @return $this + */ + public function addDefaultDoctrineAnnotationReader(): self + { + $this->annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); + + return $this; + } + /** * Sets the class metadata factory used by the validator. * @@ -252,7 +278,7 @@ public function disableAnnotationMapping() */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory) { - if (\count($this->xmlMappings) > 0 || \count($this->yamlMappings) > 0 || \count($this->methodMappings) > 0 || null !== $this->annotationReader) { + if (\count($this->xmlMappings) > 0 || \count($this->yamlMappings) > 0 || \count($this->methodMappings) > 0 || $this->enableAnnotationMapping) { throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.'); } @@ -346,7 +372,7 @@ public function getLoaders() $loaders[] = new StaticMethodLoader($methodName); } - if ($this->annotationReader) { + if ($this->enableAnnotationMapping) { $loaders[] = new AnnotationLoader($this->annotationReader); } diff --git a/src/Symfony/Component/VarDumper/Caster/ArgsStub.php b/src/Symfony/Component/VarDumper/Caster/ArgsStub.php index 591c7e2a844a0..f8b485bd40c3f 100644 --- a/src/Symfony/Component/VarDumper/Caster/ArgsStub.php +++ b/src/Symfony/Component/VarDumper/Caster/ArgsStub.php @@ -24,7 +24,7 @@ class ArgsStub extends EnumStub public function __construct(array $args, string $function, ?string $class) { - list($variadic, $params) = self::getParameters($function, $class); + [$variadic, $params] = self::getParameters($function, $class); $values = []; foreach ($args as $k => $v) { diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index eee19cd60b43d..ee9abd346c3ff 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -305,7 +305,7 @@ protected function castObject(Stub $stub, bool $isNested) $stub->class = get_debug_type($obj); } if (isset($this->classInfo[$class])) { - list($i, $parents, $hasDebugInfo, $fileInfo) = $this->classInfo[$class]; + [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class]; } else { $i = 2; $parents = [$class]; diff --git a/src/Symfony/Component/VarDumper/Server/DumpServer.php b/src/Symfony/Component/VarDumper/Server/DumpServer.php index 3e6343e350258..28decf319185b 100644 --- a/src/Symfony/Component/VarDumper/Server/DumpServer.php +++ b/src/Symfony/Component/VarDumper/Server/DumpServer.php @@ -75,7 +75,7 @@ public function listen(callable $callback): void continue; } - list($data, $context) = $payload; + [$data, $context] = $payload; $callback($data, $context, $clientId); } diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index fcb1d146944a5..7eb60be917168 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -338,7 +338,7 @@ public function unserialize($data) if ('' === $data) { throw new \InvalidArgumentException('Serialized data is empty.'); } - list(, $data) = unserialize($data); + [, $data] = unserialize($data); parent::unserialize($data); } } @@ -392,7 +392,7 @@ public function serialize(): string public function unserialize($str) { - list($this->foo) = unserialize($str); + [$this->foo] = unserialize($str); } } @@ -405,7 +405,7 @@ public function __serialize(): array public function __unserialize(array $data) { - list($this->foo) = $data; + [$this->foo] = $data; } public function __sleep(): array diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php index 967db71c69258..3474e953fa637 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -29,7 +29,7 @@ public function addWorkflow(WorkflowInterface $workflow, WorkflowSupportStrategy public function has(object $subject, string $workflowName = null): bool { - foreach ($this->workflows as list($workflow, $supportStrategy)) { + foreach ($this->workflows as [$workflow, $supportStrategy]) { if ($this->supports($workflow, $supportStrategy, $subject, $workflowName)) { return true; } @@ -45,7 +45,7 @@ public function get(object $subject, string $workflowName = null) { $matched = []; - foreach ($this->workflows as list($workflow, $supportStrategy)) { + foreach ($this->workflows as [$workflow, $supportStrategy]) { if ($this->supports($workflow, $supportStrategy, $subject, $workflowName)) { $matched[] = $workflow; } @@ -72,7 +72,7 @@ public function get(object $subject, string $workflowName = null) public function all(object $subject): array { $matched = []; - foreach ($this->workflows as list($workflow, $supportStrategy)) { + foreach ($this->workflows as [$workflow, $supportStrategy]) { if ($supportStrategy->supports($workflow, $subject)) { $matched[] = $workflow; }