diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0bef18db33536..e459d1e55f616 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,6 +2,23 @@ /src/Symfony/Component/Console/Logger/ConsoleLogger.php @dunglas # DependencyInjection /src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @dunglas +# Form +/src/Symfony/Bridge/Twig/Extension/FormExtension.php @xabbuh +/src/Symfony/Bridge/Twig/Form/* @xabbuh +/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @xabbuh +/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php @xabbuh +/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php @xabbuh +/src/Symfony/Bridge/Twig/Tests/Extension/FormExtension* @xabbuh +/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @xabbuh +/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php @xabbuh +/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php @xabbuh +/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php @xabbuh +/src/Symfony/Bundle/FrameworkBundle/Resources/views/* @xabbuh +/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @xabbuh +/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php @xabbuh +/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @xabbuh +/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @xabbuh +/src/Symfony/Component/Form/* @xabbuh # HttpKernel /src/Symfony/Component/HttpKernel/Log/Logger.php @dunglas # LDAP diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index 8dabce2aaf90e..20ddc15fe2747 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -7,6 +7,41 @@ in 3.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.4.0...v3.4.1 +* 3.4.23 (2019-03-03) + + * bug #26532 [HttpKernel] Correctly merging cache directives in HttpCache/ResponseCacheStrategy (aschempp) + * bug #30363 Fixed the DebugClassLoader compatibility with eval()'d code on Darwin (skalpa) + * bug #30329 [Form] IntegerType: reject submitted non-integer numbers (xabbuh) + * bug #30347 [Security] Change FormAuthenticator if condition (PReimers) + * bug #30354 [Console] handles multi-byte characters in autocomplete (jls-esokia) + * bug #30351 Fix getItems() performance issue with RedisCluster (php-redis) (andrerom) + * bug #30350 [VarDumper] Keep a ref to objects to ensure their handle cannot be reused while cloning (nicolas-grekas) + * bug #30327 [HttpKernel] Fix possible infinite loop of exceptions (enumag) + * bug #27601 [Routing] fix URL generation with look-around requirements (nasimnabavi) + * bug #30277 [Console] Prevent ArgvInput::getFirstArgument() from returning an option value (chalasr) + * bug #29981 [Security] Complain about an empty decision strategy (corphi) + * bug #29822 [EventDispatcher] Fix unknown priority (ro0NL) + * bug #30324 [Validator] Fixed duplicate UUID (ralfkuehnel) + * bug #30265 [Form] do not validate non-submitted form fields in PATCH requests (xabbuh) + * bug #30313 Avoid mutating the Finder when building the iterator (stof) + * bug #30271 [Console] Fix command testing with missing user inputs (chalasr) + * bug #30278 Remove unnecessary ProgressBar stdout writes (fixes flickering) (ostrolucky) + * bug #30274 [VarDumper] fix serializing Stub instances (nicolas-grekas) + * bug #30247 Don't resolve the Deprecation error handler mode until a deprecation is triggered (ossinkine) + * bug #30264 [Debug][ErrorHandler] Preserve next error handler (fancyweb) + * bug #30090 [FrameworkBundle] add constraint validators before optimizations (xabbuh) + * feature #30126 [Form] forward valid numeric values to transform() (xabbuh) + * bug #30122 [Security] fix switch user without having current token (Antoine Lamirault) + * bug #30136 use PropertyAccessorInterface instead of PropertyAccessor (nick-zh) + * bug #30124 Fix KernelTestCase compatibility for PhpUnit 8 (bis) (nicolas-grekas) + * bug #30061 [Form] render integer types with grouping as text input (xabbuh) + * bug #30063 [Form] don't lose int precision with not needed type casts (xabbuh) + * bug #30076 [Form] ignore _method forms in NativeRequestHandler (xabbuh) + * bug #30084 Fix KernelTestCase compatibility for PhpUnit 8 (alexander-schranz) + * bug #29884 [Form] CsrfValidationListener marks the token as invalid if it is not a string (umpirsky) + * bug #30062 [Form] do not overwrite the constraint being evaluated (xabbuh) + * bug #30087 [PhpUnitBridge] fix PHP 5.3 compat (nicolas-grekas) + * 3.4.22 (2019-02-03) * bug #30046 [DI] Fix dumping Doctrine-like service graphs (nicolas-grekas) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b6b40057db1df..bc64e2f7979e5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -17,9 +17,9 @@ Symfony is the result of the work of many people who made the code better - Maxime Steinhausser (ogizanagi) - Jakub Zalas (jakubzalas) - Johannes S (johannes) + - Javier Eguiluz (javier.eguiluz) - Ryan Weaver (weaverryan) - Kris Wallsmith (kriswallsmith) - - Javier Eguiluz (javier.eguiluz) - Roland Franssen (ro0) - Grégoire Pineau (lyrixx) - Hugo Hamon (hhamon) @@ -36,8 +36,8 @@ 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) - - Jules Pietri (heah) - Yonel Ceruto (yonelceruto) + - Jules Pietri (heah) - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - Sarah Khalil (saro0h) @@ -56,8 +56,8 @@ Symfony is the result of the work of many people who made the code better - Bulat Shakirzyanov (avalanche123) - Matthias Pigulla (mpdude) - Jérémy DERUSSÉ (jderusse) - - Peter Rehm (rpet) - Saša Stamenković (umpirsky) + - Peter Rehm (rpet) - Kevin Bond (kbond) - Pierre du Plessis (pierredup) - Henrik Bjørnskov (henrikbjorn) @@ -71,11 +71,11 @@ Symfony is the result of the work of many people who made the code better - Gábor Egyed (1ed) - Titouan Galopin (tgalopin) - Vladimir Reznichenko (kalessil) + - Jáchym Toušek (enumag) - Michel Weimerskirch (mweimerskirch) - Andrej Hudec (pulzarraider) - Konstantin Myakshin (koc) - Eric Clemmons (ericclemmons) - - Jáchym Toušek (enumag) - Charles Sarrazin (csarrazi) - David Maicher (dmaicher) - Christian Raue @@ -125,6 +125,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Wehner (dawehner) - excelwebzone - Gordon Franke (gimler) + - Thomas Calvet (fancyweb) - Javier Spagnoletti (phansys) - Fabien Pennequin (fabienpennequin) - Eric GELOEN (gelo) @@ -144,7 +145,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Gabriel Caruso - Hidenori Goto (hidenorigoto) - - Thomas Calvet (fancyweb) - Arnaud Kleinpeter (nanocom) - Jannik Zschiesche (apfelbox) - Guilherme Blanco (guilhermeblanco) @@ -181,6 +181,7 @@ Symfony is the result of the work of many people who made the code better - SpacePossum - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - James Halsall (jaitsu) + - Anthony MARTIN (xurudragon) - Matthieu Napoli (mnapoli) - Florent Mata (fmata) - Warnar Boekkooi (boekkooi) @@ -195,7 +196,9 @@ Symfony is the result of the work of many people who made the code better - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) - DQNEO + - Oskar Stark (oskarstark) - Benjamin Dulau (dbenjamin) + - François-Xavier de Guillebon (de-gui_f) - Mathieu Lemoine (lemoinem) - Christian Schmidt - Andreas Hucks (meandmymonkey) @@ -214,13 +217,13 @@ Symfony is the result of the work of many people who made the code better - apetitpa - Matthieu Bontemps (mbontemps) - apetitpa + - Samuel NELA (snela) - Pierre Minnieur (pminnieur) - fivestar - Dominique Bongiraud - Jeremy Livingston (jeremylivingston) - Michael Lee (zerustech) - Matthieu Auger (matthieuauger) - - Oskar Stark (oskarstark) - Leszek Prabucki (l3l0) - Fabien Bourigault (fbourigault) - François Zaninotto (fzaninotto) @@ -239,7 +242,6 @@ Symfony is the result of the work of many people who made the code better - Tristan Darricau (nicofuma) - Marcel Beerta (mazen) - Pavel Batanov (scaytrase) - - Samuel NELA (snela) - Loïc Faugeron - Hidde Wieringa (hiddewie) - Marco Pivetta (ocramius) @@ -262,7 +264,6 @@ Symfony is the result of the work of many people who made the code better - Benoît Burnichon (bburnichon) - Roman Marintšenko (inori) - Xavier Montaña Carreras (xmontana) - - François-Xavier de Guillebon (de-gui_f) - Mickaël Andrieu (mickaelandrieu) - Maxime Veber (nek-) - Xavier Perez @@ -318,6 +319,7 @@ Symfony is the result of the work of many people who made the code better - Marc Weistroff (futurecat) - Christian Schmidt - MatTheCat + - Alexander Schranz (alexander-schranz) - Chad Sikorra (chadsikorra) - Chris Smith (cs278) - Florian Klein (docteurklein) @@ -366,6 +368,7 @@ Symfony is the result of the work of many people who made the code better - Thomas Royer (cydonia7) - alquerci - Francesco Levorato + - Pascal Luna (skalpa) - Dmitrii Poddubnyi (karser) - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) @@ -384,7 +387,6 @@ Symfony is the result of the work of many people who made the code better - JhonnyL - David Badura (davidbadura) - hossein zolfi (ocean) - - Alexander Schranz (alexander-schranz) - Clément Gautier (clementgautier) - Sanpi - Eduardo Gulias (egulias) @@ -393,6 +395,7 @@ Symfony is the result of the work of many people who made the code better - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) - Grzegorz (Greg) Zdanowski (kiler129) + - Iker Ibarguren (ikerib) - Kirill chEbba Chebunin (chebba) - Greg Thornton (xdissent) - Martin Hujer (martinhujer) @@ -447,8 +450,10 @@ Symfony is the result of the work of many people who made the code better - Valentin Jonovs (valentins-jonovs) - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) + - Webnet team (webnet) - Jan Schumann - Niklas Fiekas + - renanbr - Markus Bachmann (baachi) - lancergr - Mihai Stancu @@ -456,7 +461,7 @@ Symfony is the result of the work of many people who made the code better - Olivier Dolbeau (odolbeau) - Jan Rosier (rosier) - Alessandro Lai (jean85) - - Pascal Luna (skalpa) + - Andre Rømcke (andrerom) - Arturs Vonda - Josip Kruslin - Asmir Mustafic (goetas) @@ -480,6 +485,7 @@ Symfony is the result of the work of many people who made the code better - Jonas Flodén (flojon) - Gonzalo Vilaseca (gonzalovilaseca) - Marcin Sikoń (marphi) + - Przemysław Bogusz (przemyslaw-bogusz) - Dominik Zogg (dominik.zogg) - Marek Pietrzak - Luc Vieillescazes (iamluc) @@ -492,6 +498,7 @@ Symfony is the result of the work of many people who made the code better - Adam Harvey - Anton Bakai - Rhodri Pugh (rodnaph) + - Sam Fleming (sam_fleming) - Alex Bakhturin - insekticid - Alexander Obuhovich (aik099) @@ -516,7 +523,6 @@ Symfony is the result of the work of many people who made the code better - Manuel de Ruiter (manuel) - Eduardo Oliveira (entering) - Ilya Antipenko (aivus) - - Iker Ibarguren (ikerib) - Ricardo Oliveira (ricardolotr) - Roy Van Ginneken (rvanginneken) - ondrowan @@ -546,6 +552,7 @@ Symfony is the result of the work of many people who made the code better - Almog Baku (almogbaku) - Scott Arciszewski - Xavier HAUSHERR + - Philipp Cordes - Norbert Orzechowicz (norzechowicz) - Denis Charrier (brucewouaigne) - Matthijs van den Bos (matthijs) @@ -596,6 +603,7 @@ Symfony is the result of the work of many people who made the code better - Jan Behrens - Mantas Var (mvar) - Sebastian Krebs + - Baptiste Leduc (bleduc) - Laurent VOULLEMIER (lvo) - Jean-Christophe Cuvelier [Artack] - Simon DELICATA @@ -617,7 +625,6 @@ Symfony is the result of the work of many people who made the code better - Sinan Eldem - Alexandre Dupuy (satchette) - Malte Blättermann - - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) - Christophe Villeger (seragan) @@ -626,7 +633,6 @@ Symfony is the result of the work of many people who made the code better - Stefan Gehrig (sgehrig) - Hany el-Kerdany - Wang Jingyu - - Webnet team (webnet) - Åsmund Garfors - Gunnstein Lye (glye) - Maxime Douailin @@ -641,6 +647,7 @@ Symfony is the result of the work of many people who made the code better - dantleech - Anne-Sophie Bachelard (annesophie) - Sebastian Marek (proofek) + - Guilhem N (guilhemn) - Erkhembayar Gantulga (erheme318) - Michal Trojanowski - David Fuhr @@ -656,6 +663,7 @@ Symfony is the result of the work of many people who made the code better - Stefan Warman - Arkadius Stefanski (arkadius) - Tristan Maindron (tmaindron) + - Behnoush Norouzali (behnoush) - Wesley Lancel - Ke WANG (yktd26) - Ivo Bathke (ivoba) @@ -678,6 +686,7 @@ Symfony is the result of the work of many people who made the code better - Sascha Grossenbacher - Emanuele Panzeri (thepanz) - Szijarto Tamas + - Gocha Ossinkine (ossinkine) - Robin Lehrmann (robinlehrmann) - Catalin Dan - Jaroslav Kuba @@ -734,10 +743,10 @@ Symfony is the result of the work of many people who made the code better - Pascal Helfenstein - Anthony GRASSIOT (antograssiot) - Baldur Rensch (brensch) - - Anthony MARTIN (xurudragon) - Pierre Rineau - Vladyslav Petrovych - Alex Xandra Albert Sim + - Patrick Landolt (scube) - Carson Full - Sergey Yastrebov - Trent Steel (trsteel88) @@ -774,6 +783,7 @@ Symfony is the result of the work of many people who made the code better - Noah Heck (myesain) - Christian Soronellas (theunic) - Johann Pardanaud + - fedor.f - Yosmany Garcia (yosmanyga) - Wouter de Wild - Antoine M (amakdessi) @@ -786,9 +796,9 @@ Symfony is the result of the work of many people who made the code better - possum - Denis Zunke (donalberto) - Ahmadou Waly Ndiaye (waly) - - Philipp Cordes - Ahmed TAILOULOUTE (ahmedtai) - Olivier Maisonneuve (olineuve) + - Pedro Miguel Maymone de Resende (pedroresende) - Masterklavi - Francis Turmel (fturmel) - Nikita Nefedov (nikita2206) @@ -803,6 +813,7 @@ Symfony is the result of the work of many people who made the code better - Harm van Tilborg - Jan Prieser - GDIBass + - Antoine Lamirault - Adrien Lucas (adrienlucas) - Zhuravlev Alexander (scif) - James Michael DuPont @@ -899,7 +910,6 @@ Symfony is the result of the work of many people who made the code better - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) - Matthew Davis (mdavis1982) - - Sam Fleming (sam_fleming) - Maks - Antoine LA - den @@ -907,6 +917,7 @@ Symfony is the result of the work of many people who made the code better - omerida - Gábor Tóth - Daniel Cestari + - Matt Janssen - David Lima - Stéphane Delprat - Brian Freytag (brianfreytag) @@ -926,7 +937,6 @@ Symfony is the result of the work of many people who made the code better - Kyle - Daniel Alejandro Castro Arellano (lexcast) - sensio - - Baptiste Leduc (bleduc) - Sebastien Morel (plopix) - Patrick Kaufmann - Piotr Stankowski @@ -974,10 +984,10 @@ Symfony is the result of the work of many people who made the code better - Sander Coolen (scoolen) - Nicolas Le Goff (nlegoff) - Ben Oman - - Guilhem N (guilhemn) - Chris de Kok - Andreas Kleemann - Manuele Menozzi + - zairig imad (zairigimad) - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) - Danilo Silva @@ -1013,23 +1023,25 @@ Symfony is the result of the work of many people who made the code better - tamirvs - julien.galenski - Christian Neff + - Chris Tiearney - Oliver Hoff - Ole Rößner (basster) + - Faton (notaf) + - Tom Houdmont - Per Sandström (per) - Goran Juric - Laurent Ghirardotti (laurentg) - Nicolas Macherey - Guido Donnari - AKeeman (akeeman) + - Mert Simsek (mrtsmsk0) - Lin Clark - Jeremy David (jeremy.david) - - Gocha Ossinkine (ossinkine) - Troy McCabe - Ville Mattila - ilyes kooli - gr1ev0us - mlazovla - - Behnoush norouzali (behnoush) - Max Beutel - Antanas Arvasevicius - Pierre Dudoret @@ -1038,6 +1050,7 @@ Symfony is the result of the work of many people who made the code better - nacho - Piotr Antosik (antek88) - Artem Lopata + - Patrick Reimers (preimers) - Sergey Novikov (s12v) - Marcos Quesada (marcos_quesada) - Matthew Vickery (mattvick) @@ -1052,6 +1065,7 @@ Symfony is the result of the work of many people who made the code better - Jean-Guilhem Rouel (jean-gui) - jfcixmedia - Dominic Tubach + - Tales Santos (tsantos84) - Nikita Konstantinov - Martijn Evers - Vitaliy Ryaboy (vitaliy) @@ -1060,6 +1074,7 @@ Symfony is the result of the work of many people who made the code better - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) - Michał Strzelecki + - Soner Sayakci - hugofonseca (fonsecas72) - Martynas Narbutas - Toon Verwerft (veewee) @@ -1133,10 +1148,13 @@ Symfony is the result of the work of many people who made the code better - rchoquet - gitlost - Taras Girnyk + - nikos.sotiropoulos - Eduardo García Sanz (coma) + - Sergio (deverad) - James Gilliland - fduch (fduch) - David de Boer (ddeboer) + - Eno Mullaraj (emullaraj) - Ryan Rogers - Klaus Purer - arnaud (arnooo999) @@ -1155,7 +1173,6 @@ Symfony is the result of the work of many people who made the code better - Max Voloshin (maxvoloshin) - Nicolas Fabre (nfabre) - Raul Rodriguez (raul782) - - Patrick Landolt (scube) - WybrenKoelmans - Derek Lambert - MightyBranch @@ -1183,6 +1200,7 @@ Symfony is the result of the work of many people who made the code better - Dmitri Petmanson - heccjj - Alexandre Melard + - Jonathan (jls-esokia) - Jay Klehr - Sergey Yuferev - Tobias Stöckler @@ -1244,6 +1262,7 @@ Symfony is the result of the work of many people who made the code better - Sébastien HOUZÉ - Jingyu Wang - steveYeah + - BENOIT POLASZEK (bpolaszek) - Samy Dindane (dinduks) - Keri Henare (kerihenare) - Cédric Lahouste (rapotor) @@ -1252,7 +1271,6 @@ Symfony is the result of the work of many people who made the code better - Berat Doğan - Guillaume LECERF - Juanmi Rodriguez Cerón - - renanbr - Andy Raines - Anthony Ferrara - Geoffrey Pécro (gpekz) @@ -1277,6 +1295,7 @@ Symfony is the result of the work of many people who made the code better - Luis Ramirez (luisdeimos) - Daniel Richter (richtermeister) - ChrisC + - JL - Ilya Biryukov - Kim Laï Trinh - Jason Desrosiers @@ -1311,11 +1330,14 @@ Symfony is the result of the work of many people who made the code better - Adrien Moiruad - Tomaz Ahlin - Philip Ardery + - Nasim - Marcus Stöhr (dafish) - Daniel González Zaballos (dem3trio) - Emmanuel Vella (emmanuel.vella) + - Guillaume BRETOU (guiguiboy) - Jonathan Johnson (jrjohnson) - Carsten Nielsen (phreaknerd) + - Roger Guasch (rogerguasch) - Mathieu Rochette - Jay Severson - René Kerner @@ -1343,11 +1365,14 @@ Symfony is the result of the work of many people who made the code better - Thomas Counsell - BilgeXA - r1pp3rj4ck + - phydevs - Robert Queck - Peter Bouwdewijn - mlively - Amine Matmati + - caalholm - Fabian Steiner (fabstei) + - Felipy Tavares Amorim (felipyamorim) - Klaus Silveira (klaussilveira) - Thomas Chmielowiec (chmielot) - Jānis Lukss @@ -1393,7 +1418,9 @@ Symfony is the result of the work of many people who made the code better - Keith Maika - Mephistofeles - Hoffmann András + - LubenZA - Olivier + - Anton Chernikov - Cyril PASCAL - pscheit - Wybren Koelmans @@ -1402,8 +1429,10 @@ Symfony is the result of the work of many people who made the code better - moldcraft - Antoine Bellion (abellion) - Ramon Kleiss (akathos) + - Antonio Peric-Mazar (antonioperic) - César Suárez (csuarez) - Bjorn Twachtmann (dotbjorn) + - Luis Tacón (lutacon) - Nicolas Badey (nico-b) - Shane Preece (shane) - Johannes Goslar @@ -1436,12 +1465,14 @@ Symfony is the result of the work of many people who made the code better - Przemysław Piechota (kibao) - Leonid Terentyev (li0n) - Martynas Sudintas (martiis) + - Gabriel Ostrolucký - ryunosuke - zenmate - victoria - Francisco Facioni (fran6co) - Iwan van Staveren (istaveren) - Povilas S. (povilas) + - Evrard Boulou - pborreli - Boris Betzholz - Eric Caron @@ -1452,10 +1483,13 @@ Symfony is the result of the work of many people who made the code better - catch - Alexandre Segura - Josef Cech + - Andrii Boiko - Harold Iedema + - Ikhsan Agustian - Arnau González (arnaugm) - Simon Bouland (bouland) - Matthew Foster (mfoster) + - Reyo Stallenberg (reyostallenberg) - Paul Seiffert (seiffert) - Vasily Khayrulin (sirian) - Stefan Koopmanschap (skoop) @@ -1536,9 +1570,11 @@ Symfony is the result of the work of many people who made the code better - Normunds - Luiz “Felds” Liscia - Thomas Rothe + - Martin - nietonfir - alefranz - David Barratt + - Andrea Giannantonio - Pavel.Batanov - avi123 - Pavel Prischepa @@ -1559,12 +1595,14 @@ Symfony is the result of the work of many people who made the code better - Nicolas Pion - Muhammed Akbulut - Aaron Somi + - Karoly Gossler (connorhu) - Michał Dąbrowski (defrag) - Konstantin Grachev (grachevko) - Simone Fumagalli (hpatoio) - Brian Graham (incognito) - Kevin Vergauwen (innocenzo) - Alessio Baglio (ioalessio) + - Jan van Thoor (janvt) - Johannes Müller (johmue) - Jordi Llonch (jordillonch) - Cédric Dugat (ph3nol) @@ -1680,6 +1718,7 @@ Symfony is the result of the work of many people who made the code better - Jonny Schmid (schmidjon) - Götz Gottwald - Veres Lajos + - Nick Chiu - grifx - Robert Campbell - Matt Lehner @@ -1714,6 +1753,7 @@ Symfony is the result of the work of many people who made the code better - skafandri - Derek Bonner - Alan Chen + - insidestyles - Maerlyn - Even André Fiskvik - Arjan Keeman @@ -1750,8 +1790,10 @@ Symfony is the result of the work of many people who made the code better - Brieuc THOMAS (brieucthomas) - Masao Maeda (brtriver) - Darius Leskauskas (darles) + - david perez (davidpv) - David Joos (djoos) - Denis Klementjev (dklementjev) + - Dominik Hajduk (dominikalp) - Tomáš Polívka (draczris) - Dennis Smink (dsmink) - Franz Liedke (franzliedke) @@ -1932,13 +1974,14 @@ Symfony is the result of the work of many people who made the code better - zorn - Yuriy Potemkin - Emilie Lorenzo + - enomotodev - Edvin Hultberg - Benjamin Long - - Matt Janssen - Ben Miller - Peter Gribanov - kwiateusz - jspee + - Ilya Bulakh - David Soria Parra - Sergiy Sokolenko - Ahmed Abdulrahman @@ -2042,10 +2085,10 @@ Symfony is the result of the work of many people who made the code better - Tomas Norkūnas (norkunas) - Marco Petersen (ocrampete16) - ollie harridge (ollietb) + - Dimitri Gritsajuk (ottaviano) - Paul Andrieux (paulandrieux) - Paweł Szczepanek (pauluz) - Philippe Degeeter (pdegeeter) - - Pedro Miguel Maymone de Resende (pedroresende) - Christian López Espínola (penyaskito) - Petr Jaroš (petajaros) - Philipp Hoffmann (philipphoffmann) @@ -2053,6 +2096,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Perez Pinazo (pitiflautico) - Phil Taylor (prazgod) - Maxim Pustynnikov (pustynnikov) + - Ralf Kuehnel (ralfkuehnel) - Brayden Williams (redstar504) - Rich Sage (richsage) - Rokas Mikalkėnas (rokasm) @@ -2113,6 +2157,7 @@ Symfony is the result of the work of many people who made the code better - Andrew Carter (andrewcarteruk) - Adam Elsodaney (archfizz) - Gregório Bonfante Borba (bonfante) + - Bogdan Rancichi (devck) - Daniel Kolvik (dkvk) - Marc Lemay (flug) - Henne Van Och (hennevo) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index fe43d0cf99737..fbe988fa3497f 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -230,7 +230,7 @@ DependencyInjection supported. * The ``strict`` attribute in service arguments has been removed. - The attribute is ignored since 3.0, so you can simply remove it. + The attribute is ignored since 3.0, you can remove it. * Top-level anonymous services in XML are no longer supported. diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php index 860a6c7c20d0a..7ac1856114d7e 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php @@ -24,8 +24,8 @@ * The compiler pass is meant to register the mappings with the metadata * chain driver corresponding to one of the object managers. * - * For concrete implementations that are easy to use, see the - * RegisterXyMappingsPass classes in the DoctrineBundle resp. + * For concrete implementations, see the RegisterXyMappingsPass classes + * in the DoctrineBundle resp. * DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle. * * @author David Buchmann diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index 689101d2e09a6..e4110f1d785f8 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -157,7 +157,7 @@ protected function getMetadata($class) // normalize class name $class = ClassUtils::getRealClass(ltrim($class, '\\')); - if (array_key_exists($class, $this->cache)) { + if (\array_key_exists($class, $this->cache)) { return $this->cache[$class]; } diff --git a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php index 8923aa21aa29f..7c630b4e98399 100644 --- a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php @@ -20,7 +20,7 @@ /** * Wrapper around a Doctrine ObjectManager. * - * Provides easy to use provisioning for Doctrine entity users. + * Provides provisioning for Doctrine entity users. * * @author Fabien Potencier * @author Johannes M. Schmitt diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php index afdeb5f720e27..5012171542f7b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php @@ -30,6 +30,8 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase */ private $em; + protected static $supportedFeatureSetVersion = 304; + protected function getExtensions() { $manager = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock(); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 2869c2b804c4c..1cb59c38436ef 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -57,6 +57,8 @@ class EntityTypeTest extends BaseTypeTest */ private $emRegistry; + protected static $supportedFeatureSetVersion = 304; + protected function setUp() { $this->em = DoctrineTestHelper::createTestEntityManager(); diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 3b444d5d95b2a..fc60cbd4365be 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -54,9 +54,9 @@ public static function register($mode = 0) if (false === $mode) { $mode = getenv('SYMFONY_DEPRECATIONS_HELPER'); } - if (self::MODE_DISABLED !== $mode - && self::MODE_WEAK !== $mode - && self::MODE_WEAK_VENDORS !== $mode + if (DeprecationErrorHandler::MODE_DISABLED !== $mode + && DeprecationErrorHandler::MODE_WEAK !== $mode + && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $mode && (!isset($mode[0]) || '/' !== $mode[0]) ) { $mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0; @@ -105,8 +105,7 @@ public static function register($mode = 0) 'remaining vendor' => array(), ); $deprecationHandler = function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, $getMode, $UtilPrefix, $inVendors) { - $mode = $getMode(); - if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || self::MODE_DISABLED === $mode) { + if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode = $getMode()) { $ErrorHandler = $UtilPrefix.'ErrorHandler'; return $ErrorHandler::handleError($type, $msg, $file, $line, $context); @@ -114,7 +113,7 @@ public static function register($mode = 0) $trace = debug_backtrace(); $group = 'other'; - $isVendor = self::MODE_WEAK_VENDORS === $mode && $inVendors($file); + $isVendor = DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $inVendors($file); $i = \count($trace); while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) { @@ -131,7 +130,7 @@ public static function register($mode = 0) // \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest() // then we need to use the serialized information to determine // if the error has been triggered from vendor code. - $isVendor = self::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && $inVendors($parsedMsg['triggering_file']); + $isVendor = DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && $inVendors($parsedMsg['triggering_file']); } else { $class = isset($trace[$i]['object']) ? \get_class($trace[$i]['object']) : $trace[$i]['class']; $method = $trace[$i]['function']; @@ -168,13 +167,13 @@ public static function register($mode = 0) exit(1); } - if ('legacy' !== $group && self::MODE_WEAK !== $mode) { + if ('legacy' !== $group && DeprecationErrorHandler::MODE_WEAK !== $mode) { $ref = &$deprecations[$group][$msg]['count']; ++$ref; $ref = &$deprecations[$group][$msg][$class.'::'.$method]; ++$ref; } - } elseif (self::MODE_WEAK !== $mode) { + } elseif (DeprecationErrorHandler::MODE_WEAK !== $mode) { $ref = &$deprecations[$group][$msg]['count']; ++$ref; } @@ -207,7 +206,7 @@ public static function register($mode = 0) $currErrorHandler = set_error_handler('var_dump'); restore_error_handler(); - if (self::MODE_WEAK === $mode) { + if (DeprecationErrorHandler::MODE_WEAK === $mode) { $colorize = function ($str) { return $str; }; } if ($currErrorHandler !== $deprecationHandler) { @@ -219,7 +218,7 @@ public static function register($mode = 0) }; $groups = array('unsilenced', 'remaining'); - if (self::MODE_WEAK_VENDORS === $mode) { + if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode) { $groups[] = 'remaining vendor'; } array_push($groups, 'legacy', 'other'); @@ -255,7 +254,7 @@ public static function register($mode = 0) $displayDeprecations($deprecations); // store failing status - $isFailing = self::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']; + $isFailing = DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']; // reset deprecations array foreach ($deprecations as $group => $arrayOrInt) { @@ -270,7 +269,7 @@ public static function register($mode = 0) } } $displayDeprecations($deprecations); - if ($isFailing || self::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) { + if ($isFailing || DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) { exit(1); } }); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt index e06e9bd869aca..7a0595a7ddebc 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt @@ -25,7 +25,7 @@ class Test { public static function getGroups() { - return []; + return array(); } } EOPHP diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php index 5229a7a7cc6f5..16a58246d2115 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php @@ -7,7 +7,7 @@ class Test { public static function getGroups() { - return []; + return array(); } } EOPHP diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt index 1bb1551663e13..fddeed6085dea 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt @@ -25,7 +25,7 @@ class Test { public static function getGroups() { - return []; + return array(); } } EOPHP diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt index b37b623cf297a..e20c7adf6ba1f 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt @@ -25,7 +25,7 @@ class Test { public static function getGroups() { - return []; + return array(); } } EOPHP diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index 24a48b600d1b5..25dcb0cd10272 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -21,8 +21,7 @@ "php": ">=5.3.3" }, "suggest": { - "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader", - "ext-zip": "Zip support is required when using bin/simple-phpunit" + "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index 04b8dda567307..80e36e0491efc 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Twig\Environment; +use Twig\Error\LoaderError; use Twig\Markup; use Twig\Profiler\Dumper\HtmlDumper; use Twig\Profiler\Profile; @@ -70,7 +71,7 @@ public function lateCollect() if ($profile->isTemplate()) { try { $template = $this->twig->load($name = $profile->getName()); - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { $template = null; } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php index d5bcfa8b8fceb..642623f2a693c 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php @@ -77,7 +77,7 @@ public function set($key, $value) */ public function has($key) { - if (array_key_exists($key, $this->data)) { + if (\array_key_exists($key, $this->data)) { return true; } @@ -98,7 +98,7 @@ public function has($key) */ public function get($key, $default = null) { - if (array_key_exists($key, $this->data)) { + if (\array_key_exists($key, $this->data)) { return $this->data[$key]; } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php index ebfb105826b33..e50076da73105 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php @@ -16,6 +16,8 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest { + protected static $supportedFeatureSetVersion = 304; + public function testLabelOnForm() { $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); @@ -1863,6 +1865,22 @@ public function testInteger() ); } + public function testIntegerTypeWithGroupingRendersAsTextInput() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123, [ + 'grouping' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="123"] +' + ); + } + public function testLanguage() { $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LanguageType', 'de'); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index 456e6730faa34..214df3c7f6b18 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -31,6 +31,8 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest */ private $renderer; + protected static $supportedFeatureSetVersion = 304; + protected function setUp() { parent::setUp(); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 7811a41eb6bb7..f956767363a97 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -30,6 +30,8 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest */ private $renderer; + protected static $supportedFeatureSetVersion = 304; + protected function setUp() { parent::setUp(); diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 84a1ad8a938d0..3008f43f6f4bc 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -54,7 +54,7 @@ protected function getVariableGetterWithoutStrictCheck($name) protected function getVariableGetterWithStrictCheck($name) { if (Environment::MAJOR_VERSION >= 2) { - return sprintf('(isset($context["%s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%1$s" does not exist.\', 0, $this->source); })())', $name); + return sprintf('(isset($context["%1$s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new %2$s(\'Variable "%1$s" does not exist.\', 0, $this->source); })())', $name, Environment::VERSION_ID >= 20700 ? 'RuntimeError' : 'Twig_Error_Runtime'); } if (\PHP_VERSION_ID >= 70000) { diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 58e90971bec11..42d8bef4ace45 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -23,7 +23,7 @@ "symfony/asset": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "^3.4.22|~4.1.11|^4.2.3", + "symfony/form": "^3.4.23|^4.2.4", "symfony/http-foundation": "^3.3.11|~4.0", "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 758c605ecfa01..6aa3fbf9b7183 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -139,7 +139,7 @@ private function getConfigForPath(array $config, $path, $alias) $steps = explode('.', $path); foreach ($steps as $step) { - if (!array_key_exists($step, $config)) { + if (!\array_key_exists($step, $config)) { throw new LogicException(sprintf('Unable to find configuration for "%s.%s"', $alias, $path)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index fda0fb28d3039..c7b669fda0228 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -225,7 +225,7 @@ protected function resolveServiceDefinition(ContainerBuilder $builder, $serviceI return $builder->getDefinition($serviceId); } - // Some service IDs don't have a Definition, they're simply an Alias + // Some service IDs don't have a Definition, they're aliases if ($builder->hasAlias($serviceId)) { return $builder->getAlias($serviceId); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index 83f607cc384f6..6b05612ff53d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -156,7 +156,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], Con */ protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) { - $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, array_key_exists('event', $options) ? $options['event'] : null), $options); + $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null), $options); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index a0a0dc85166fe..6575b05ec81e8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -275,7 +275,7 @@ protected function describeContainerParameter($parameter, array $options = []) */ protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) { - $event = array_key_exists('event', $options) ? $options['event'] : null; + $event = \array_key_exists('event', $options) ? $options['event'] : null; $title = 'Registered listeners'; if (null !== $event) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 7aed45bd4aced..90c7602604e2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -385,7 +385,7 @@ protected function describeContainerParameter($parameter, array $options = []) */ protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) { - $event = array_key_exists('event', $options) ? $options['event'] : null; + $event = \array_key_exists('event', $options) ? $options['event'] : null; if (null !== $event) { $title = sprintf('Registered Listeners for "%s" Event', $event); diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index 38efe85753542..53e2ee1fac358 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -111,7 +111,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], Con */ protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) { - $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, array_key_exists('event', $options) ? $options['event'] : null)); + $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null)); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index f49c5f11e0eec..52c7706456c9f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -371,7 +371,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) } foreach ($transitions as $name => $transition) { - if (array_key_exists('name', $transition)) { + if (\array_key_exists('name', $transition)) { continue; } $transition['name'] = $name; diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index a46e552a255e3..ee5dc86df201f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -602,7 +602,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $registryDefinition = $container->getDefinition('workflow.registry'); foreach ($config['workflows'] as $name => $workflow) { - if (!array_key_exists('type', $workflow)) { + if (!\array_key_exists('type', $workflow)) { $workflow['type'] = 'workflow'; @trigger_error(sprintf('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.', $name), E_USER_DEPRECATED); } @@ -1052,7 +1052,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co foreach ($config['packages'] as $name => $package) { if (null !== $package['version_strategy']) { $version = new Reference($package['version_strategy']); - } elseif (!array_key_exists('version', $package) && null === $package['json_manifest_path']) { + } elseif (!\array_key_exists('version', $package) && null === $package['json_manifest_path']) { // if neither version nor json_manifest_path are specified, use the default $version = $defaultVersion; } else { @@ -1273,7 +1273,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $definition = $container->findDefinition('validator.email'); $definition->replaceArgument(0, $config['strict_email']); - if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { + 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.'); } @@ -1281,7 +1281,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $validatorBuilder->addMethodCall('enableAnnotationMapping', [new Reference('annotation_reader')]); } - if (array_key_exists('static_method', $config) && $config['static_method']) { + if (\array_key_exists('static_method', $config) && $config['static_method']) { foreach ($config['static_method'] as $methodName) { $validatorBuilder->addMethodCall('addMethodMapping', [$methodName]); } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index daf7a37bf8547..b472275ff530a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -101,7 +101,7 @@ public function build(ContainerBuilder $container) // but as late as possible to get resolved parameters $container->addCompilerPass((new RegisterListenersPass())->setHotPathEvents($hotPathEvents), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new TemplatingPass()); - $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class, PassConfig::TYPE_BEFORE_REMOVING); + $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255); $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index adbf4e5c574ef..531f7dddb970f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -120,6 +120,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelShutdownOnTearDownTrait.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelShutdownOnTearDownTrait.php new file mode 100644 index 0000000000000..b01dbb0494340 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelShutdownOnTearDownTrait.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use PHPUnit\Framework\TestCase; + +// Auto-adapt to PHPUnit 8 that added a `void` return-type to the tearDown method + +if (method_exists(\ReflectionMethod::class, 'hasReturnType') && (new \ReflectionMethod(TestCase::class, 'tearDown'))->hasReturnType()) { + eval(' + namespace Symfony\Bundle\FrameworkBundle\Test; + + /** + * @internal + */ + trait KernelShutdownOnTearDownTrait + { + protected function tearDown(): void + { + static::ensureKernelShutdown(); + } + } +'); +} else { + /** + * @internal + */ + trait KernelShutdownOnTearDownTrait + { + /** + * @return void + */ + protected function tearDown() + { + static::ensureKernelShutdown(); + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 0feb15380e1c4..978f65863220c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -23,6 +23,8 @@ */ abstract class KernelTestCase extends TestCase { + use KernelShutdownOnTearDownTrait; + protected static $class; /** @@ -208,7 +210,7 @@ protected static function createKernel(array $options = []) } /** - * Shuts the kernel down if it was used in the test. + * Shuts the kernel down if it was used in the test - called by the tearDown method by default. */ protected static function ensureKernelShutdown() { @@ -220,12 +222,4 @@ protected static function ensureKernelShutdown() } } } - - /** - * Clean up Kernel usage in this test. - */ - protected function tearDown() - { - static::ensureKernelShutdown(); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index f211f283869eb..c2cded7ab0966 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -54,7 +54,7 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() // Ensure that all *.meta files are fresh $finder = new Finder(); $metaFiles = $finder->files()->in($this->kernel->getCacheDir())->name('*.php.meta'); - // simply check that cache is warmed up + // check that cache is warmed up $this->assertNotEmpty($metaFiles); $configCacheFactory = new ConfigCacheFactory(true); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index 0400efc25e291..bfec01aefc876 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -21,7 +21,7 @@ class ContainerDebugCommandTest extends WebTestCase { public function testDumpContainerIfNotExists() { - static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']); + static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); $application = new Application(static::$kernel); $application->setAutoExit(false); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php index 3f7bb4c7ee680..00eda6570906d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php @@ -62,7 +62,7 @@ protected static function createKernel(array $options = []) $options['test_case'], isset($options['root_config']) ? $options['root_config'] : 'config.yml', isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']), - isset($options['debug']) ? $options['debug'] : true + isset($options['debug']) ? $options['debug'] : false ); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php index 7e8d8f0972151..03b2ed6961b7d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @@ -27,6 +27,8 @@ class FormHelperDivLayoutTest extends AbstractDivLayoutTest */ protected $engine; + protected static $supportedFeatureSetVersion = 304; + protected function getExtensions() { // should be moved to the Form component once absolute file paths are supported diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php index fc5e7d17f3786..bd088078c32d1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @@ -27,6 +27,8 @@ class FormHelperTableLayoutTest extends AbstractTableLayoutTest */ protected $engine; + protected static $supportedFeatureSetVersion = 304; + public function testStartTagHasNoActionAttributeWhenActionIsEmpty() { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 8d4a46f9f330a..2db17aa130c39 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -479,7 +479,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a foreach ($this->factories as $position) { foreach ($position as $factory) { $key = str_replace('-', '_', $factory->getKey()); - if (array_key_exists($key, $firewall)) { + if (\array_key_exists($key, $firewall)) { $listenerKeys[] = $key; } } diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php index 3597b14a909c8..3051ed38dc165 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\SecurityBundle\Templating\Helper; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\Templating\Helper\Helper; @@ -38,7 +37,7 @@ public function __construct(LogoutUrlGenerator $generator) */ public function getLogoutPath($key) { - return $this->generator->getLogoutPath($key, UrlGeneratorInterface::ABSOLUTE_PATH); + return $this->generator->getLogoutPath($key); } /** @@ -50,7 +49,7 @@ public function getLogoutPath($key) */ public function getLogoutUrl($key) { - return $this->generator->getLogoutUrl($key, UrlGeneratorInterface::ABSOLUTE_URL); + return $this->generator->getLogoutUrl($key); } /** diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php index f1d23b6054ad7..9bcbc0532481d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php @@ -62,7 +62,7 @@ protected static function createKernel(array $options = []) $options['test_case'], isset($options['root_config']) ? $options['root_config'] : 'config.yml', isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']), - isset($options['debug']) ? $options['debug'] : true + isset($options['debug']) ? $options['debug'] : false ); } diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index a51a82bf5bfde..58e136a6381d0 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -193,7 +193,7 @@ private function getBundleHierarchy(ContainerBuilder $container, array $config) $bundleHierarchy = []; foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - if (!array_key_exists($name, $bundleHierarchy)) { + if (!\array_key_exists($name, $bundleHierarchy)) { $bundleHierarchy[$name] = [ 'paths' => [], 'parents' => [], @@ -222,7 +222,7 @@ private function getBundleHierarchy(ContainerBuilder $container, array $config) $bundleHierarchy[$name]['parents'][] = $bundle['parent']; - if (!array_key_exists($bundle['parent'], $bundleHierarchy)) { + if (!\array_key_exists($bundle['parent'], $bundleHierarchy)) { $bundleHierarchy[$bundle['parent']] = [ 'paths' => [], 'parents' => [], diff --git a/src/Symfony/Bundle/WebServerBundle/Resources/router.php b/src/Symfony/Bundle/WebServerBundle/Resources/router.php index a366b381aae47..30d6b258a29de 100644 --- a/src/Symfony/Bundle/WebServerBundle/Resources/router.php +++ b/src/Symfony/Bundle/WebServerBundle/Resources/router.php @@ -17,8 +17,8 @@ * If you have custom directory layout, then you have to write your own router * and pass it as a value to 'router' option of server:run command. * - * @author: Michał Pipa - * @author: Albert Jessurum + * @author Michał Pipa + * @author Albert Jessurum */ // Workaround https://bugs.php.net/64566 diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index 294b1fb84bbfb..98553353d8ce3 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -452,7 +452,7 @@ public function back() { do { $request = $this->history->back(); - } while (array_key_exists(serialize($request), $this->redirects)); + } while (\array_key_exists(serialize($request), $this->redirects)); return $this->requestFromRequest($request, false); } @@ -466,7 +466,7 @@ public function forward() { do { $request = $this->history->forward(); - } while (array_key_exists(serialize($request), $this->redirects)); + } while (\array_key_exists(serialize($request), $this->redirects)); return $this->requestFromRequest($request, false); } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index 482751f620c64..5758a28618e27 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -21,11 +21,11 @@ protected function setUp() { parent::setUp(); - if (!array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && \defined('HHVM_VERSION')) { + if (!\array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && \defined('HHVM_VERSION')) { $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; } - if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { + if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; } } diff --git a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php index 27003bf913eb9..ff9944a3400b2 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php @@ -21,7 +21,7 @@ protected function setUp() { parent::setUp(); - if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { + if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; } } diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 6c2190ab754ad..9b7a84ab59991 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -135,7 +135,7 @@ public static function createConnection($servers, array $options = []) $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); $client->setOption(\Memcached::OPT_NO_BLOCK, true); $client->setOption(\Memcached::OPT_TCP_NODELAY, true); - if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); } foreach ($options as $name => $value) { diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index a637be8080030..7cbd304a0cec7 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -169,18 +169,29 @@ public static function createConnection($dsn, array $options = []) */ protected function doFetch(array $ids) { - if ($ids) { + if (!$ids) { + return []; + } + + $result = []; + + if ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'get' => [$id]; } }); - foreach ($values as $id => $v) { - if ($v) { - yield $id => parent::unserialize($v); - } + } else { + $values = array_combine($ids, $this->redis->mget($ids)); + } + + foreach ($values as $id => $v) { + if ($v) { + $result[$id] = parent::unserialize($v); } } + + return $result; } /** diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 70baa5a0ab2c0..ac310819d4199 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -59,7 +59,7 @@ protected function preNormalize($value) $normalized = []; foreach ($value as $k => $v) { - if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { + if (false !== strpos($k, '-') && false === strpos($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { $normalized[$normalizedKey] = $v; } else { $normalized[$k] = $v; @@ -223,7 +223,7 @@ protected function finalizeValue($value) } foreach ($this->children as $name => $child) { - if (!array_key_exists($name, $value)) { + if (!\array_key_exists($name, $value)) { if ($child->isRequired()) { $ex = new InvalidConfigurationException(sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath())); $ex->setPath($this->getPath()); @@ -359,7 +359,7 @@ protected function mergeValues($leftSide, $rightSide) foreach ($rightSide as $k => $v) { // no conflict - if (!array_key_exists($k, $leftSide)) { + if (!\array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath())); $ex->setPath($this->getPath()); diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index 9837e5d88321e..115054a24fb0c 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -332,10 +332,10 @@ public function performNoDeepMerging() * Allows extra config keys to be specified under an array without * throwing an exception. * - * Those config values are simply ignored and removed from the - * resulting array. This should be used only in special cases where - * you want to send an entire configuration array through a special - * tree that processes only part of the array. + * Those config values are ignored and removed from the resulting + * array. This should be used only in special cases where you want + * to send an entire configuration array through a special tree that + * processes only part of the array. * * @param bool $remove Whether to remove the extra keys * diff --git a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php index f00cfcaa8349c..9a14449c487e3 100644 --- a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php +++ b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php @@ -245,7 +245,7 @@ protected function normalizeValue($value) // if only "value" is left if (array_keys($v) === ['value']) { $v = $v['value']; - if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && array_key_exists('value', $children)) { + if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) { $valuePrototype = current($this->valuePrototypes) ?: clone $children['value']; $valuePrototype->parent = $this; $originalClosures = $this->prototype->normalizationClosures; @@ -258,7 +258,7 @@ protected function normalizeValue($value) } } - if (array_key_exists($k, $normalized)) { + if (\array_key_exists($k, $normalized)) { $ex = new DuplicateKeyException(sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath())); $ex->setPath($this->getPath()); @@ -301,14 +301,14 @@ protected function mergeValues($leftSide, $rightSide) } foreach ($rightSide as $k => $v) { - // prototype, and key is irrelevant, so simply append the element + // prototype, and key is irrelevant, append the element if (null === $this->keyAttribute) { $leftSide[] = $v; continue; } // no conflict - if (!array_key_exists($k, $leftSide)) { + if (!\array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath())); $ex->setPath($this->getPath()); diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 0d52007454022..6cc5f5c580ecf 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -202,6 +202,13 @@ public function doRun(InputInterface $input, OutputInterface $output) return 0; } + try { + // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + // Errors must be ignored, full binding/validation happens later when the command is known. + } + $name = $this->getCommandName($input); if (true === $input->hasParameterOption(['--help', '-h'], true)) { if (!$name) { diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index a1c3cc5d217e7..172565514128b 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -466,19 +466,16 @@ private function overwrite($message) { if ($this->overwrite) { if (!$this->firstRun) { - // Move the cursor to the beginning of the line - $this->output->write("\x0D"); - - // Erase the line - $this->output->write("\x1B[2K"); - // Erase previous lines if ($this->formatLineCount > 0) { - $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount)); + $message = str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount).$message; } + + // Move the cursor to the beginning of the line and erase the line + $message = "\x0D\x1B[2K$message"; } } elseif ($this->step > 0) { - $this->output->writeln(''); + $message = PHP_EOL.$message; } $this->firstRun = false; diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index d3188897f37c8..9c200fe897ea9 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -166,7 +166,7 @@ private function doAsk(OutputInterface $output, Question $question) if (false === $ret) { $ret = fgets($inputStream, 4096); if (false === $ret) { - throw new RuntimeException('Aborted'); + throw new RuntimeException('Aborted.'); } $ret = trim($ret); } @@ -252,8 +252,10 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu while (!feof($inputStream)) { $c = fread($inputStream, 1); - // Backspace Character - if ("\177" === $c) { + // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. + if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { + throw new RuntimeException('Aborted.'); + } elseif ("\177" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { --$i; // Move cursor backwards @@ -306,6 +308,10 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu continue; } else { + if ("\x80" <= $c) { + $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); + } + $output->write($c); $ret .= $c; ++$i; @@ -380,7 +386,7 @@ private function getHiddenResponse(OutputInterface $output, $inputStream) shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { - throw new RuntimeException('Aborted'); + throw new RuntimeException('Aborted.'); } $value = trim($value); diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index 142096ae62793..f604057ec0255 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -262,8 +262,27 @@ private function addLongOption($name, $value) */ public function getFirstArgument() { - foreach ($this->tokens as $token) { + $isOption = false; + foreach ($this->tokens as $i => $token) { if ($token && '-' === $token[0]) { + if (false !== strpos($token, '=') || !isset($this->tokens[$i + 1])) { + continue; + } + + // If it's a long option, consider that everything after "--" is the option name. + // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) + $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); + if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { + // noop + } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { + $isOption = true; + } + + continue; + } + + if ($isOption) { + $isOption = false; continue; } diff --git a/src/Symfony/Component/Console/Input/ArrayInput.php b/src/Symfony/Component/Console/Input/ArrayInput.php index cf09ff45ecb49..44c2f0d5c66aa 100644 --- a/src/Symfony/Component/Console/Input/ArrayInput.php +++ b/src/Symfony/Component/Console/Input/ArrayInput.php @@ -19,7 +19,7 @@ * * Usage: * - * $input = new ArrayInput(['name' => 'foo', '--bar' => 'foobar']); + * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); * * @author Fabien Potencier */ diff --git a/src/Symfony/Component/Console/Input/Input.php b/src/Symfony/Component/Console/Input/Input.php index 7a16e0ee4b9f2..c1220316dcfff 100644 --- a/src/Symfony/Component/Console/Input/Input.php +++ b/src/Symfony/Component/Console/Input/Input.php @@ -69,7 +69,7 @@ public function validate() $givenArguments = $this->arguments; $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { - return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); }); if (\count($missingArguments) > 0) { @@ -150,7 +150,7 @@ public function getOption($name) throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } - return array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** diff --git a/src/Symfony/Component/Console/Input/InputDefinition.php b/src/Symfony/Component/Console/Input/InputDefinition.php index 9dc1c09b94e3a..53f41d73f5ce2 100644 --- a/src/Symfony/Component/Console/Input/InputDefinition.php +++ b/src/Symfony/Component/Console/Input/InputDefinition.php @@ -338,8 +338,10 @@ public function getOptionDefaults() * @return string The InputOption name * * @throws InvalidArgumentException When option given does not exist + * + * @internal */ - private function shortcutToName($shortcut) + public function shortcutToName($shortcut) { if (!isset($this->shortcuts[$shortcut])) { throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); diff --git a/src/Symfony/Component/Console/Tester/ApplicationTester.php b/src/Symfony/Component/Console/Tester/ApplicationTester.php index bcf91d640b7df..dc970182ecae6 100644 --- a/src/Symfony/Component/Console/Tester/ApplicationTester.php +++ b/src/Symfony/Component/Console/Tester/ApplicationTester.php @@ -66,7 +66,7 @@ public function run(array $input, $options = []) $this->input->setInteractive($options['interactive']); } - $this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; if (!$this->captureStreamsIndependently) { $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { diff --git a/src/Symfony/Component/Console/Tester/CommandTester.php b/src/Symfony/Component/Console/Tester/CommandTester.php index 229471e13a35e..f869995eb92d6 100644 --- a/src/Symfony/Component/Console/Tester/CommandTester.php +++ b/src/Symfony/Component/Console/Tester/CommandTester.php @@ -62,9 +62,8 @@ public function execute(array $input, array $options = []) } $this->input = new ArrayInput($input); - if ($this->inputs) { - $this->input->setStream(self::createStream($this->inputs)); - } + // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. + $this->input->setStream(self::createStream($this->inputs)); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 2cb3324630a08..ae9d130f502ab 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -884,6 +884,19 @@ public function testRun() $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed'); } + public function testRunWithGlobalOptionAndNoCommand() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->getDefinition()->addOption(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)); + + $output = new StreamOutput(fopen('php://memory', 'w', false)); + $input = new ArgvInput(['cli.php', '--foo', 'bar']); + + $this->assertSame(0, $application->run($input, $output)); + } + /** * Issue #9285. * diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 531474eddfe1e..46cfe8184278d 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -237,6 +237,43 @@ public function testAskWithAutocompleteWithExactMatch() $this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } + public function getInputs() + { + return [ + ['$'], // 1 byte character + ['¢'], // 2 bytes character + ['€'], // 3 bytes character + ['𐍈'], // 4 bytes character + ]; + } + + /** + * @dataProvider getInputs + */ + public function testAskWithAutocompleteWithMultiByteCharacter($character) + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + $inputStream = $this->getInputStream("$character\n"); + + $possibleChoices = [ + '$' => '1 byte character', + '¢' => '2 bytes character', + '€' => '3 bytes character', + '𐍈' => '4 bytes character', + ]; + + $dialog = new QuestionHelper(); + $dialog->setHelperSet(new HelperSet([new FormatterHelper()])); + + $question = new ChoiceQuestion('Please select a character', $possibleChoices); + $question->setMaxAttempts(1); + + $this->assertSame($character, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + } + public function testAutocompleteWithTrailingBackslash() { if (!$this->hasSttyAvailable()) { @@ -900,7 +937,7 @@ public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys() /** * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted + * @expectedExceptionMessage Aborted. */ public function testAskThrowsExceptionOnMissingInput() { @@ -910,7 +947,17 @@ public function testAskThrowsExceptionOnMissingInput() /** * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted + * @expectedExceptionMessage Aborted. + */ + public function testAskThrowsExceptionOnMissingInputForChoiceQuestion() + { + $dialog = new QuestionHelper(); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new ChoiceQuestion('Choice', ['a', 'b'])); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted. */ public function testAskThrowsExceptionOnMissingInputWithValidator() { diff --git a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php index e7fd806064d2c..cf7a78c34ecda 100644 --- a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php @@ -124,7 +124,7 @@ public function testLabelTrailingBackslash() /** * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted + * @expectedExceptionMessage Aborted. */ public function testAskThrowsExceptionOnMissingInput() { diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 37caaf2d1cd72..e20bcdd21bc7c 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -312,6 +312,14 @@ public function testGetFirstArgument() $input = new ArgvInput(['cli.php', '-fbbar', 'foo']); $this->assertEquals('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input'); + + $input = new ArgvInput(['cli.php', '--foo', 'fooval', 'bar']); + $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('arg')])); + $this->assertSame('bar', $input->getFirstArgument()); + + $input = new ArgvInput(['cli.php', '-bf', 'fooval', 'argval']); + $input->bind(new InputDefinition([new InputOption('bar', 'b', InputOption::VALUE_NONE), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('arg')])); + $this->assertSame('argval', $input->getFirstArgument()); } public function testHasParameterOption() diff --git a/src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php b/src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php index 8cad7f0385d08..f916b1821fcc8 100644 --- a/src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php +++ b/src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Output\Output; +use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Tester\CommandTester; @@ -139,7 +140,7 @@ public function testCommandWithDefaultInputs() /** * @expectedException \RuntimeException - * @expectedMessage Aborted + * @expectedExceptionMessage Aborted. */ public function testCommandWithWrongInputsNumber() { @@ -153,13 +154,40 @@ public function testCommandWithWrongInputsNumber() $command->setHelperSet(new HelperSet([new QuestionHelper()])); $command->setCode(function ($input, $output) use ($questions, $command) { $helper = $command->getHelper('question'); + $helper->ask($input, $output, new ChoiceQuestion('choice', ['a', 'b'])); + $helper->ask($input, $output, new Question($questions[0])); + $helper->ask($input, $output, new Question($questions[1])); + $helper->ask($input, $output, new Question($questions[2])); + }); + + $tester = new CommandTester($command); + $tester->setInputs(['a', 'Bobby', 'Fine']); + $tester->execute([]); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Aborted. + */ + public function testCommandWithQuestionsButNoInputs() + { + $questions = [ + 'What\'s your name?', + 'How are you?', + 'Where do you come from?', + ]; + + $command = new Command('foo'); + $command->setHelperSet(new HelperSet([new QuestionHelper()])); + $command->setCode(function ($input, $output) use ($questions, $command) { + $helper = $command->getHelper('question'); + $helper->ask($input, $output, new ChoiceQuestion('choice', ['a', 'b'])); $helper->ask($input, $output, new Question($questions[0])); $helper->ask($input, $output, new Question($questions[1])); $helper->ask($input, $output, new Question($questions[2])); }); $tester = new CommandTester($command); - $tester->setInputs(['Bobby', 'Fine']); $tester->execute([]); } diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 54df7de0cfc98..310f7d4e2247c 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -390,6 +390,11 @@ private function darwinRealpath($real) $dirFiles = self::$darwinCache[$kDir][1]; + if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { + // Get the file name from "file_name.php(123) : eval()'d code" + $file = substr($file, 0, strrpos($file, '(', -17)); + } + if (isset($dirFiles[$file])) { return $real .= $dirFiles[$file]; } diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 22a6426dab7e9..d871b91538c22 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -222,7 +222,7 @@ public function setLoggers(array $loggers) } if (!\is_array($log)) { $log = [$log]; - } elseif (!array_key_exists(0, $log)) { + } elseif (!\array_key_exists(0, $log)) { throw new \InvalidArgumentException('No logger provided'); } if (null === $log[0]) { @@ -517,6 +517,11 @@ public function handleError($type, $message, $file, $line) $errorAsException ? ['exception' => $errorAsException] : [], ]; } else { + if (!\defined('HHVM_VERSION')) { + $currentErrorHandler = set_error_handler('var_dump'); + restore_error_handler(); + } + try { $this->isRecursive = true; $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; @@ -525,7 +530,7 @@ public function handleError($type, $message, $file, $line) $this->isRecursive = false; if (!\defined('HHVM_VERSION')) { - set_error_handler([$this, __FUNCTION__]); + set_error_handler($currentErrorHandler); } } } diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 73fee9ac15727..c6bc3f7d88b5e 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -297,7 +297,7 @@ public function testExtendedFinalClass() require __DIR__.'/Fixtures/FinalClasses.php'; $i = 1; - while(class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) { + while (class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) { spl_autoload_call($finalClass); class_exists('Test\\'.__NAMESPACE__.'\\Extends'.substr($finalClass, strrpos($finalClass, '\\') + 1), true); } @@ -385,6 +385,11 @@ class_exists('Test\\'.__NAMESPACE__.'\\UseTraitWithInternalMethod', true); $this->assertSame([], $deprecations); } + + public function testEvaluatedCode() + { + $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\DefinitionInEvaluatedCode', true)); + } } class ClassLoader diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 6e0afd55cacf0..c1dea75bbd90e 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -12,12 +12,12 @@ namespace Symfony\Component\Debug\Tests; use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Psr\Log\NullLogger; use Symfony\Component\Debug\BufferingLogger; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\Exception\SilencedErrorContext; +use Symfony\Component\Debug\Tests\Fixtures\ErrorHandlerThatUsesThePreviousOne; use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler; /** @@ -590,26 +590,40 @@ public function testCustomExceptionHandler() } /** - * @dataProvider errorHandlerIsNotLostWhenLoggingProvider + * @dataProvider errorHandlerWhenLoggingProvider */ - public function testErrorHandlerIsNotLostWhenLogging($customErrorHandlerHasBeenPreviouslyDefined, LoggerInterface $logger) + public function testErrorHandlerWhenLogging($previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined) { try { - if ($customErrorHandlerHasBeenPreviouslyDefined) { + if ($previousHandlerWasDefined) { set_error_handler('count'); } + $logger = $loggerSetsAnotherHandler ? new LoggerThatSetAnErrorHandler() : new NullLogger(); + $handler = ErrorHandler::register(); $handler->setDefaultLogger($logger); + if ($nextHandlerIsDefined) { + $handler = ErrorHandlerThatUsesThePreviousOne::register(); + } + @trigger_error('foo', E_USER_DEPRECATED); @trigger_error('bar', E_USER_DEPRECATED); $this->assertSame([$handler, 'handleError'], set_error_handler('var_dump')); + if ($logger instanceof LoggerThatSetAnErrorHandler) { + $this->assertCount(2, $logger->cleanLogs()); + } + restore_error_handler(); - if ($customErrorHandlerHasBeenPreviouslyDefined) { + if ($previousHandlerWasDefined) { + restore_error_handler(); + } + + if ($nextHandlerIsDefined) { restore_error_handler(); } } finally { @@ -618,13 +632,14 @@ public function testErrorHandlerIsNotLostWhenLogging($customErrorHandlerHasBeenP } } - public function errorHandlerIsNotLostWhenLoggingProvider() + public function errorHandlerWhenLoggingProvider() { - return [ - [false, new NullLogger()], - [true, new NullLogger()], - [false, new LoggerThatSetAnErrorHandler()], - [true, new LoggerThatSetAnErrorHandler()], - ]; + foreach ([false, true] as $previousHandlerWasDefined) { + foreach ([false, true] as $loggerSetsAnotherHandler) { + foreach ([false, true] as $nextHandlerIsDefined) { + yield [$previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined]; + } + } + } } } diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/DefinitionInEvaluatedCode.php b/src/Symfony/Component/Debug/Tests/Fixtures/DefinitionInEvaluatedCode.php new file mode 100644 index 0000000000000..ff6976e0fb1d7 --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/Fixtures/DefinitionInEvaluatedCode.php @@ -0,0 +1,11 @@ +arguments)) { + if (\array_key_exists('index_'.$index, $this->arguments)) { return $this->arguments['index_'.$index]; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index b411b30f262b5..252b304f118f5 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -214,7 +214,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a } foreach ($parameters as $index => $parameter) { - if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) { + if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index 8eac9f0061c5f..bf1387c04ed17 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -43,10 +43,10 @@ protected function processValue($value, $isRoot = false) if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) { throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId)); } - if (!array_key_exists('id', $attributes)) { + if (!\array_key_exists('id', $attributes)) { throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId)); } - if (!array_key_exists('key', $attributes)) { + if (!\array_key_exists('key', $attributes)) { $attributes['key'] = $attributes['id']; } if (isset($serviceMap[$attributes['key']])) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index 0fad285e5aaf4..20b262b6d461c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -119,11 +119,11 @@ protected function processValue($value, $isRoot = false) } foreach ($reflectionMethod->getParameters() as $key => $parameter) { - if (array_key_exists($key, $arguments) && '' !== $arguments[$key]) { + if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { continue; } - if (array_key_exists('$'.$parameter->name, $bindings)) { + if (\array_key_exists('$'.$parameter->name, $bindings)) { $arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]); continue; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php index ee54288ec3244..0b79280110f65 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php @@ -71,7 +71,7 @@ protected function processValue($value, $isRoot = false) $typeFound = false; foreach ($parameters as $j => $p) { - if (!array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { + if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { $resolvedArguments[$j] = $argument; $typeFound = true; } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index ea4a6d7631f1c..e822643439c2f 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -466,7 +466,7 @@ protected function getEnv($name) if (isset($this->resolving[$envName = "env($name)"])) { throw new ParameterCircularReferenceException(array_keys($this->resolving)); } - if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { + if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } if (!$this->has($id = 'container.env_var_processors_locator')) { diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 171bcaf46a36f..ee58034713b0b 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -263,7 +263,7 @@ public function replaceArgument($index, $argument) throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1)); } - if (!array_key_exists($index, $this->arguments)) { + if (!\array_key_exists($index, $this->arguments)) { throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); } @@ -308,7 +308,7 @@ public function getArguments() */ public function getArgument($index) { - if (!array_key_exists($index, $this->arguments)) { + if (!\array_key_exists($index, $this->arguments)) { throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php index 3adcef79b195e..f06e6e80d5031 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php @@ -193,7 +193,7 @@ private function findNodes() } foreach ($container->getServiceIds() as $id) { - if (array_key_exists($id, $container->getAliases())) { + if (\array_key_exists($id, $container->getAliases())) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Extension/Extension.php b/src/Symfony/Component/DependencyInjection/Extension/Extension.php index 80a9419c5d3f3..a9389862ccbe2 100644 --- a/src/Symfony/Component/DependencyInjection/Extension/Extension.php +++ b/src/Symfony/Component/DependencyInjection/Extension/Extension.php @@ -115,7 +115,7 @@ final public function getProcessedConfigs() */ protected function isConfigEnabled(ContainerBuilder $container, array $config) { - if (!array_key_exists('enabled', $config)) { + if (!\array_key_exists('enabled', $config)) { throw new InvalidArgumentException("The config array has no 'enabled' key."); } diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php index 3b0b57ef0f6b9..532e768684f30 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php @@ -17,7 +17,7 @@ /** * {@inheritdoc} * - * Noop proxy instantiator - simply produces the real service instead of a proxy instance. + * Noop proxy instantiator - produces the real service instead of a proxy instance. * * @author Marco Pivetta */ diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index a02a6c8ea5c66..fd2a20a8768f7 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -333,7 +333,7 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) continue; } - if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { + if (false !== strpos($name, '-') && false === strpos($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); } // keep not normalized key diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 5dc41e0347895..a3a799024e499 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -213,7 +213,7 @@ private function parseDefinitions(array $content, $file) throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); } - if (array_key_exists('_instanceof', $content['services'])) { + if (\array_key_exists('_instanceof', $content['services'])) { $instanceof = $content['services']['_instanceof']; unset($content['services']['_instanceof']); @@ -250,7 +250,7 @@ private function parseDefinitions(array $content, $file) */ private function parseDefaults(array &$content, $file) { - if (!array_key_exists('_defaults', $content['services'])) { + if (!\array_key_exists('_defaults', $content['services'])) { return []; } $defaults = $content['services']['_defaults']; @@ -361,7 +361,7 @@ private function parseDefinition($id, $service, $file, array $defaults) if (isset($service['alias'])) { $this->container->setAlias($id, $alias = new Alias($service['alias'])); - if (array_key_exists('public', $service)) { + if (\array_key_exists('public', $service)) { $alias->setPublic($service['public']); } elseif (isset($defaults['public'])) { $alias->setPublic($defaults['public']); @@ -438,7 +438,7 @@ private function parseDefinition($id, $service, $file, array $defaults) $definition->setAbstract($service['abstract']); } - if (array_key_exists('deprecated', $service)) { + if (\array_key_exists('deprecated', $service)) { $definition->setDeprecated(true, $service['deprecated']); } @@ -571,11 +571,11 @@ private function parseDefinition($id, $service, $file, array $defaults) } } - if (array_key_exists('namespace', $service) && !array_key_exists('resource', $service)) { + if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) { throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in %s. Check your YAML syntax.', $id, $file)); } - if (array_key_exists('resource', $service)) { + if (\array_key_exists('resource', $service)) { if (!\is_string($service['resource'])) { throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); } diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 8a86f94170a75..c4e702181fe68 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -70,7 +70,7 @@ public function get($name) { $name = $this->normalizeName($name); - if (!array_key_exists($name, $this->parameters)) { + if (!\array_key_exists($name, $this->parameters)) { if (!$name) { throw new ParameterNotFoundException($name); } @@ -121,7 +121,7 @@ public function set($name, $value) */ public function has($name) { - return array_key_exists($this->normalizeName($name), $this->parameters); + return \array_key_exists($this->normalizeName($name), $this->parameters); } /** diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index b2355dedf9a65..68d7c3dafce88 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -968,7 +968,7 @@ private function relativize($xpath) $expressions = []; // An expression which will never match to replace expressions which cannot match in the crawler - // We cannot simply drop + // We cannot drop $nonMatchingExpression = 'a[name() = "b"]'; $xpathLen = \strlen($xpath); diff --git a/src/Symfony/Component/DomCrawler/Field/FileFormField.php b/src/Symfony/Component/DomCrawler/Field/FileFormField.php index af9c6e6f25ff4..9e21c9c4b9bd1 100644 --- a/src/Symfony/Component/DomCrawler/Field/FileFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/FileFormField.php @@ -60,7 +60,7 @@ public function setValue($value) // copy to a tmp location $tmp = sys_get_temp_dir().'/'.strtr(substr(base64_encode(hash('sha256', uniqid(mt_rand(), true), true)), 0, 7), '/', '_'); - if (array_key_exists('extension', $info)) { + if (\array_key_exists('extension', $info)) { $tmp .= '.'.$info['extension']; } if (is_file($tmp)) { diff --git a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php index 10c7e8cb365b2..8f432cfbbb830 100644 --- a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php +++ b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php @@ -57,7 +57,7 @@ public function remove($name) $target = &$this->fields; while (\count($segments) > 1) { $path = array_shift($segments); - if (!array_key_exists($path, $target)) { + if (!\array_key_exists($path, $target)) { return; } $target = &$target[$path]; @@ -80,7 +80,7 @@ public function &get($name) $target = &$this->fields; while ($segments) { $path = array_shift($segments); - if (!array_key_exists($path, $target)) { + if (!\array_key_exists($path, $target)) { throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path)); } $target = &$target[$path]; diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index c90ac927b2c84..de2b850953c3d 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -29,6 +29,7 @@ class WrappedListener private $dispatcher; private $pretty; private $stub; + private $priority; private static $hasClassStub; public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) @@ -96,7 +97,7 @@ public function getInfo($eventName) return [ 'event' => $eventName, - 'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null, + 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), 'pretty' => $this->pretty, 'stub' => $this->stub, ]; @@ -104,11 +105,14 @@ public function getInfo($eventName) public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) { + $dispatcher = $this->dispatcher ?: $dispatcher; + $this->called = true; + $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); $e = $this->stopwatch->start($this->name, 'event_listener'); - \call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher); + \call_user_func($this->listener, $event, $eventName, $dispatcher); if ($e->isStarted()) { $e->stop(); diff --git a/src/Symfony/Component/EventDispatcher/GenericEvent.php b/src/Symfony/Component/EventDispatcher/GenericEvent.php index a9a0a5dfa59c6..f005e3a3db076 100644 --- a/src/Symfony/Component/EventDispatcher/GenericEvent.php +++ b/src/Symfony/Component/EventDispatcher/GenericEvent.php @@ -111,7 +111,7 @@ public function setArguments(array $args = []) */ public function hasArgument($key) { - return array_key_exists($key, $this->arguments); + return \array_key_exists($key, $this->arguments); } /** diff --git a/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php b/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php index c11965a4247ee..f9d4644a87279 100644 --- a/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php +++ b/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php @@ -21,7 +21,7 @@ interface IOExceptionInterface extends ExceptionInterface /** * Returns the associated path for the exception. * - * @return string The path + * @return string|null The path */ public function getPath(); } diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index aa9afb349d30a..3c61fc15048fe 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -137,8 +137,8 @@ public function exists($files) * Sets access and modification time of file. * * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create - * @param int $time The touch time as a Unix timestamp - * @param int $atime The access time as a Unix timestamp + * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used + * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used * * @throws IOException When touch fails */ @@ -193,7 +193,7 @@ public function remove($files) * @param int $umask The mode mask (octal) * @param bool $recursive Whether change the mod recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ public function chmod($files, $mode, $umask = 0000, $recursive = false) { @@ -214,7 +214,7 @@ public function chmod($files, $mode, $umask = 0000, $recursive = false) * @param string $user The new owner user name * @param bool $recursive Whether change the owner recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ public function chown($files, $user, $recursive = false) { @@ -241,7 +241,7 @@ public function chown($files, $user, $recursive = false) * @param string $group The group name * @param bool $recursive Whether change the group recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ public function chgrp($files, $group, $recursive = false) { @@ -519,14 +519,14 @@ public function makePathRelative($endPath, $startPath) * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) * - * @param string $originDir The origin directory - * @param string $targetDir The target directory - * @param \Traversable $iterator Iterator that filters which files and directories to copy - * @param array $options An array of boolean options - * Valid options are: - * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) - * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) + * @param string $originDir The origin directory + * @param string $targetDir The target directory + * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created + * @param array $options An array of boolean options + * Valid options are: + * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) + * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown */ diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index f03882bba1de7..133c4b8c50b15 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -29,7 +29,7 @@ * * All rules may be invoked several times. * - * All methods return the current Finder object to allow easy chaining: + * All methods return the current Finder object to allow chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * @@ -645,12 +645,15 @@ public function count() */ private function searchInDirectory($dir) { + $exclude = $this->exclude; + $notPaths = $this->notPaths; + if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $this->exclude = array_merge($this->exclude, self::$vcsPatterns); + $exclude = array_merge($exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $this->notPaths[] = '#(^|/)\..+(/|$)#'; + $notPaths[] = '#(^|/)\..+(/|$)#'; } $minDepth = 0; @@ -683,8 +686,8 @@ private function searchInDirectory($dir) $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); + if ($exclude) { + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); } $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); @@ -717,8 +720,8 @@ private function searchInDirectory($dir) $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } - if ($this->paths || $this->notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); + if ($this->paths || $notPaths) { + $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); } if ($this->sort) { diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index d309d23b1767a..aac35bc234195 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -199,6 +199,18 @@ public function testIgnoreVCS() $this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar']), $finder->in(self::$tmpDir)->getIterator()); } + public function testIgnoreVCSCanBeDisabledAfterFirstIteration() + { + $finder = $this->buildFinder(); + $finder->in(self::$tmpDir); + $finder->ignoreDotFiles(false); + + $this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar']), $finder->getIterator()); + + $finder->ignoreVCS(false); + $this->assertIterator($this->toAbsolute(['.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar']), $finder->getIterator()); + } + public function testIgnoreDotFiles() { $finder = $this->buildFinder(); @@ -214,6 +226,17 @@ public function testIgnoreDotFiles() $this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar']), $finder->in(self::$tmpDir)->getIterator()); } + public function testIgnoreDotFilesCanBeDisabledAfterFirstIteration() + { + $finder = $this->buildFinder(); + $finder->in(self::$tmpDir); + + $this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar']), $finder->getIterator()); + + $finder->ignoreDotFiles(false); + $this->assertIterator($this->toAbsolute(['foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar']), $finder->getIterator()); + } + public function testSortByName() { $finder = $this->buildFinder(); diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php index d2044f214ed52..903e842b9e8b8 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -664,7 +664,7 @@ public function getAttributes() */ public function hasAttribute($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -677,7 +677,7 @@ public function hasAttribute($name) */ public function getAttribute($name, $default = null) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -771,7 +771,7 @@ public function getOptions() */ public function hasOption($name) { - return array_key_exists($name, $this->options); + return \array_key_exists($name, $this->options); } /** @@ -784,7 +784,7 @@ public function hasOption($name) */ public function getOption($name, $default = null) { - return array_key_exists($name, $this->options) ? $this->options[$name] : $default; + return \array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index c33dda70ca6df..02685a2504185 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -78,7 +78,7 @@ public function __construct($choices, callable $value = null) // If a deterministic value generator was passed, use it later $this->valueCallback = $value; } else { - // Otherwise simply generate incrementing integers as values + // Otherwise generate incrementing integers as values $i = 0; $value = function () use (&$i) { return $i++; @@ -135,7 +135,7 @@ public function getChoicesForValues(array $values) $choices = []; foreach ($values as $i => $givenValue) { - if (array_key_exists($givenValue, $this->choices)) { + if (\array_key_exists($givenValue, $this->choices)) { $choices[$i] = $this->choices[$givenValue]; } } diff --git a/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php b/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php index b81ad48b91896..0fb32734d5318 100644 --- a/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php @@ -32,7 +32,7 @@ class LazyChoiceList implements ChoiceListInterface /** * The callable creating string values for each choice. * - * If null, choices are simply cast to strings. + * If null, choices are cast to strings. * * @var callable|null */ diff --git a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php index d602a15f77766..ab518dbfeed12 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php @@ -66,7 +66,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio 'allowed_values' => 'allowedValues', ]; foreach ($map as $label => $name) { - if (array_key_exists($name, $definition)) { + if (\array_key_exists($name, $definition)) { $data[$label] = $definition[$name]; if ('default' === $name) { diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php index 015caf13ad351..957944f9ebea9 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -110,7 +110,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio ]; $rows = []; foreach ($map as $label => $name) { - $value = array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; + $value = \array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; if ('default' === $name && isset($definition['lazy'])) { $value = "Value: $value\n\nClosure(s): ".$dump($definition['lazy']); } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index 999e47391b576..ca69b5fe8a8b7 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer; +use Symfony\Component\Form\Exception\TransformationFailedException; + /** * Transforms between an integer and a localized number with grouping * (each thousand) and comma separators. @@ -40,8 +42,22 @@ public function __construct($scale = 0, $grouping = false, $roundingMode = self: */ public function reverseTransform($value) { + $decimalSeparator = $this->getNumberFormatter()->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + + if (\is_string($value) && false !== strpos($value, $decimalSeparator)) { + throw new TransformationFailedException(sprintf('The value "%s" is not a valid integer.', $value)); + } + $result = parent::reverseTransform($value); return null !== $result ? (int) $result : null; } + + /** + * @internal + */ + protected function castParsedValue($value) + { + return $value; + } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 7449fedfc69cc..b163cc093bfac 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -23,6 +23,12 @@ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransform { private $divisor; + /** + * @param int|null $scale + * @param bool|null $grouping + * @param int|null $roundingMode + * @param int|null $divisor + */ public function __construct($scale = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1) { if (null === $grouping) { @@ -58,7 +64,7 @@ public function transform($value) if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } - $value = (string) ($value / $this->divisor); + $value /= $this->divisor; } return parent::transform($value); diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 638885e4226e6..d720bb8e77f45 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -78,6 +78,11 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface private $scale; + /** + * @param int|null $scale + * @param bool|null $grouping + * @param int|null $roundingMode + */ public function __construct($scale = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP) { if (null === $grouping) { @@ -181,9 +186,7 @@ public function reverseTransform($value) throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } - if (\is_int($result) && $result === (int) $float = (float) $result) { - $result = $float; - } + $result = $this->castParsedValue($result); if (false !== $encoding = mb_detect_encoding($value, null, true)) { $length = mb_strlen($value, $encoding); @@ -228,6 +231,18 @@ protected function getNumberFormatter() return $formatter; } + /** + * @internal + */ + protected function castParsedValue($value) + { + if (\is_int($value) && $value === (int) $float = (float) $value) { + return $float; + } + + return $value; + } + /** * Rounds a number according to the configured scale and rounding mode. * diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php index 35429b2cb728c..72b14035e575c 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php @@ -38,7 +38,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); - $isDataOptionSet = array_key_exists('data', $options); + $isDataOptionSet = \array_key_exists('data', $options); $builder ->setRequired($options['required']) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/IntegerType.php b/src/Symfony/Component/Form/Extension/Core/Type/IntegerType.php index 3e119ed5ce26c..e3699614b4f69 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/IntegerType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/IntegerType.php @@ -14,6 +14,8 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; class IntegerType extends AbstractType @@ -31,6 +33,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) )); } + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + if ($options['grouping']) { + $view->vars['type'] = 'text'; + } + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php index 452bca443f5e9..8f90d21c297bd 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -59,7 +59,7 @@ public function preSubmit(FormEvent $event) if ($form->isRoot() && $form->getConfig()->getOption('compound') && !$postRequestSizeExceeded) { $data = $event->getData(); - if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { + if (!isset($data[$this->fieldName]) || !\is_string($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index e7b485d39f8f7..88fa453a62580 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -228,9 +228,6 @@ public function getData() return $this->data; } - /** - * @internal - */ public function serialize() { if ($this->hasVarDumper) { diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 08d679a4b5d4c..7922bcc74c87f 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -26,10 +26,10 @@ class FormValidator extends ConstraintValidator /** * {@inheritdoc} */ - public function validate($form, Constraint $constraint) + public function validate($form, Constraint $formConstraint) { - if (!$constraint instanceof Form) { - throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Form'); + if (!$formConstraint instanceof Form) { + throw new UnexpectedTypeException($formConstraint, __NAMESPACE__.'\Form'); } if (!$form instanceof FormInterface) { @@ -41,7 +41,7 @@ public function validate($form, Constraint $constraint) $validator = $this->context->getValidator()->inContext($this->context); - if ($form->isSynchronized()) { + if ($form->isSubmitted() && $form->isSynchronized()) { // Validate the form data only if transformation succeeded $groups = self::getValidationGroups($form); $data = $form->getData(); @@ -62,8 +62,8 @@ public function validate($form, Constraint $constraint) // Otherwise validate a constraint only once for the first // matching group foreach ($groups as $group) { - if (\in_array($group, $constraint->groups)) { - $validator->atPath('data')->validate($form->getData(), $constraint, $group); + if (\in_array($group, $formConstraint->groups)) { + $validator->atPath('data')->validate($form->getData(), $formConstraint, $group); if (\count($this->context->getViolations()) > 0) { break; } @@ -90,7 +90,7 @@ public function validate($form, Constraint $constraint) } } } - } else { + } elseif (!$form->isSynchronized()) { $childrenSynchronized = true; /** @var FormInterface $child */ @@ -113,7 +113,7 @@ public function validate($form, Constraint $constraint) ? (string) $form->getViewData() : \gettype($form->getViewData()); - $this->context->setConstraint($constraint); + $this->context->setConstraint($formConstraint); $this->context->buildViolation($config->getOption('invalid_message')) ->setParameters(array_replace(['{{ value }}' => $clientDataAsString], $config->getOption('invalid_message_parameters'))) ->setInvalidValue($form->getViewData()) @@ -125,7 +125,7 @@ public function validate($form, Constraint $constraint) // Mark the form with an error if it contains extra fields if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) { - $this->context->setConstraint($constraint); + $this->context->setConstraint($formConstraint); $this->context->buildViolation($config->getOption('extra_fields_message')) ->setParameter('{{ extra_fields }}', '"'.implode('", "', array_keys($form->getExtraData())).'"') ->setInvalidValue($form->getExtraData()) diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php index 590f7df2d8b58..cb9f3f953326b 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php @@ -55,7 +55,7 @@ public function getOrigin() */ public function match($propertyPath) { - if ($propertyPath === (string) $this->propertyPath) { + if ($propertyPath === $this->propertyPath) { return $this->getTarget(); } } diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php index 86a77044d13d5..659c266ce6fa9 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -273,9 +273,6 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or */ private function acceptsErrors(FormInterface $form) { - // Ignore non-submitted forms. This happens, for example, in PATCH - // requests. - // https://github.com/symfony/symfony/pull/10567 - return $form->isSubmitted() && ($this->allowNonSynchronized || $form->isSynchronized()); + return $this->allowNonSynchronized || $form->isSynchronized(); } } diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 1822cf6e18acc..cfa7eb5b6a6d8 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -42,9 +42,9 @@ * * In most cases, format (1) and format (2) will be the same. For example, * a checkbox field uses a Boolean value for both internal processing and - * storage in the object. In these cases you simply need to set a view - * transformer to convert between formats (2) and (3). You can do this by - * calling addViewTransformer(). + * storage in the object. In these cases you need to set a view transformer + * to convert between formats (2) and (3). You can do this by calling + * addViewTransformer(). * * In some cases though it makes sense to make format (1) configurable. To * demonstrate this, let's extend our above date field to store the value @@ -574,7 +574,7 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - $isSubmitted = array_key_exists($name, $submittedData); + $isSubmitted = \array_key_exists($name, $submittedData); if ($isSubmitted || $clearMissing) { $child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing); diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index 28094d27c9ea1..fc864fc617173 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -431,7 +431,7 @@ public function getAttributes() */ public function hasAttribute($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -439,7 +439,7 @@ public function hasAttribute($name) */ public function getAttribute($name, $default = null) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -526,7 +526,7 @@ public function getOptions() */ public function hasOption($name) { - return array_key_exists($name, $this->options); + return \array_key_exists($name, $this->options); } /** @@ -534,7 +534,7 @@ public function hasOption($name) */ public function getOption($name, $default = null) { - return array_key_exists($name, $this->options) ? $this->options[$name] : $default; + return \array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** diff --git a/src/Symfony/Component/Form/FormFactory.php b/src/Symfony/Component/Form/FormFactory.php index d474d5903f86f..b397f9a21fbfa 100644 --- a/src/Symfony/Component/Form/FormFactory.php +++ b/src/Symfony/Component/Form/FormFactory.php @@ -63,7 +63,7 @@ public function createBuilder($type = 'Symfony\Component\Form\Extension\Core\Typ */ public function createNamedBuilder($name, $type = 'Symfony\Component\Form\Extension\Core\Type\FormType', $data = null, array $options = []) { - if (null !== $data && !array_key_exists('data', $options)) { + if (null !== $data && !\array_key_exists('data', $options)) { $options['data'] = $data; } diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 16f0a65ac1141..8b15e0344d0ce 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -163,7 +163,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // "form_widget" in this example (again, no matter in which theme). // If the designer wants to explicitly fallback to "form_widget" in their // custom "choice_widget", for example because they only want to wrap - // a
around the original implementation, they can simply call the + // a
around the original implementation, they can call the // widget() function again to render the block for the parent type. // // The second kind is implemented in the following blocks. diff --git a/src/Symfony/Component/Form/FormTypeGuesserInterface.php b/src/Symfony/Component/Form/FormTypeGuesserInterface.php index 0aec6364c4ac7..6521ea47ca767 100644 --- a/src/Symfony/Component/Form/FormTypeGuesserInterface.php +++ b/src/Symfony/Component/Form/FormTypeGuesserInterface.php @@ -32,7 +32,7 @@ public function guessType($class, $property); * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * - * @return Guess\ValueGuess A guess for the field's required setting + * @return Guess\ValueGuess|null A guess for the field's required setting */ public function guessRequired($class, $property); diff --git a/src/Symfony/Component/Form/NativeRequestHandler.php b/src/Symfony/Component/Form/NativeRequestHandler.php index ffe91ba7604dc..246ea92ccee50 100644 --- a/src/Symfony/Component/Form/NativeRequestHandler.php +++ b/src/Symfony/Component/Form/NativeRequestHandler.php @@ -94,10 +94,10 @@ public function handleRequest(FormInterface $form, $request = null) if ('' === $name) { $params = $_POST; $files = $fixedFiles; - } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) { + } elseif (\array_key_exists($name, $_POST) || \array_key_exists($name, $fixedFiles)) { $default = $form->getConfig()->getCompound() ? [] : null; - $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; - $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; + $params = \array_key_exists($name, $_POST) ? $_POST[$name] : $default; + $files = \array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { // Don't submit the form if it is not present in the request return; @@ -115,6 +115,10 @@ public function handleRequest(FormInterface $form, $request = null) return; } + if (\is_array($data) && \array_key_exists('_method', $data) && $method === $data['_method'] && !$form->has('_method')) { + unset($data['_method']); + } + $form->submit($data, 'PATCH' !== $method); } diff --git a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php index 01440575a1126..e11ce03357f6d 100644 --- a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php +++ b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Test; +use Symfony\Component\Form\Tests\VersionAwareTest; + /** * Base class for performance tests. * @@ -21,6 +23,8 @@ */ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { + use VersionAwareTest; + /** * @var int */ diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 0e749b780c784..4e01253e2e564 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -18,6 +18,8 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase { + use VersionAwareTest; + protected $csrfTokenManager; protected $testableFeatures = []; @@ -1730,6 +1732,21 @@ public function testInteger() ); } + public function testIntegerTypeWithGroupingRendersAsTextInput() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123, [ + 'grouping' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/input + [@type="text"] + [@name="name"] + [@value="123"] +' + ); + } + public function testLanguage() { $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LanguageType', 'de'); diff --git a/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php index dd73dcde23e4e..16d4045e6d580 100644 --- a/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php @@ -200,7 +200,7 @@ public function testMergeParamsAndFiles($method) $form = $this->createForm('param1', $method, true); $form->add($this->createForm('field1')); $form->add($this->createBuilder('field2', false, ['allow_file_upload' => true])->getForm()); - $file = $this->getMockFile(); + $file = $this->getUploadedFile(); $this->setRequestData($method, [ 'param1' => [ @@ -225,7 +225,7 @@ public function testMergeParamsAndFiles($method) public function testParamTakesPrecedenceOverFile($method) { $form = $this->createForm('param1', $method); - $file = $this->getMockFile(); + $file = $this->getUploadedFile(); $this->setRequestData($method, [ 'param1' => 'DATA', @@ -247,7 +247,7 @@ public function testSubmitFileIfNoParam($method) $form = $this->createBuilder('param1', false, ['allow_file_upload' => true]) ->setMethod($method) ->getForm(); - $file = $this->getMockFile(); + $file = $this->getUploadedFile(); $this->setRequestData($method, [ 'param1' => null, @@ -269,14 +269,14 @@ public function testSubmitMultipleFiles($method) $form = $this->createBuilder('param1', false, ['allow_file_upload' => true]) ->setMethod($method) ->getForm(); - $file = $this->getMockFile(); + $file = $this->getUploadedFile(); $this->setRequestData($method, [ 'param1' => null, ], [ - 'param2' => $this->getMockFile('2'), + 'param2' => $this->getUploadedFile('2'), 'param1' => $file, - 'param3' => $this->getMockFile('3'), + 'param3' => $this->getUploadedFile('3'), ]); $this->requestHandler->handleRequest($form, $this->request); @@ -285,6 +285,26 @@ public function testSubmitMultipleFiles($method) $this->assertSame($file, $form->getData()); } + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitFileWithNamelessForm($method) + { + $form = $this->createForm('', $method, true); + $fileForm = $this->createBuilder('document', false, ['allow_file_upload' => true])->getForm(); + $form->add($fileForm); + $file = $this->getUploadedFile(); + $this->setRequestData($method, [ + 'document' => null, + ], [ + 'document' => $file, + ]); + $this->requestHandler->handleRequest($form, $this->request); + + $this->assertTrue($form->isSubmitted()); + $this->assertSame($file, $fileForm->getData()); + } + /** * @dataProvider getPostMaxSizeFixtures */ @@ -332,7 +352,7 @@ public function getPostMaxSizeFixtures() public function testUploadedFilesAreAccepted() { - $this->assertTrue($this->requestHandler->isFileUpload($this->getMockFile())); + $this->assertTrue($this->requestHandler->isFileUpload($this->getUploadedFile())); } public function testInvalidFilesAreRejected() @@ -344,7 +364,7 @@ abstract protected function setRequestData($method, $data, $files = []); abstract protected function getRequestHandler(); - abstract protected function getMockFile($suffix = ''); + abstract protected function getUploadedFile($suffix = ''); abstract protected function getInvalidFile(); diff --git a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php index 52fc78aed9087..a23607412cc8d 100644 --- a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php +++ b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php @@ -19,8 +19,9 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Command\DebugCommand; use Symfony\Component\Form\DependencyInjection\FormPass; -use Symfony\Component\Form\FormRegistryInterface; +use Symfony\Component\Form\FormRegistry; /** * @author Bernhard Schussek @@ -70,8 +71,12 @@ public function testAddTaggedTypesToDebugCommand() { $container = $this->createContainerBuilder(); + $container->register('form.registry', FormRegistry::class); + $commandDefinition = new Definition(DebugCommand::class, [new Reference('form.registry')]); + $commandDefinition->setPublic(true); + $container->setDefinition('form.extension', $this->createExtensionDefinition()); - $container->setDefinition('console.command.form_debug', $this->createDebugCommandDefinition()); + $container->setDefinition('console.command.form_debug', $commandDefinition); $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type')->setPublic(true); $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type')->setPublic(true); @@ -259,19 +264,6 @@ private function createExtensionDefinition() return $definition; } - private function createDebugCommandDefinition() - { - $definition = new Definition('Symfony\Component\Form\Command\DebugCommand'); - $definition->setPublic(true); - $definition->setArguments([ - $formRegistry = $this->getMockBuilder(FormRegistryInterface::class)->getMock(), - [], - ['Symfony\Component\Form\Extension\Core\Type'], - ]); - - return $definition; - } - private function createContainerBuilder() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 901af61ce94fb..da351295c381e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -12,9 +12,14 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; +use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; -use Symfony\Component\Form\FormConfigInterface; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; +use Symfony\Component\PropertyAccess\PropertyPath; class PropertyPathMapperTest extends TestCase { @@ -24,78 +29,36 @@ class PropertyPathMapperTest extends TestCase private $mapper; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EventDispatcherInterface */ private $dispatcher; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var PropertyAccessorInterface */ private $propertyAccessor; protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->propertyAccessor = $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyAccessorInterface')->getMock(); + $this->dispatcher = new EventDispatcher(); + $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); $this->mapper = new PropertyPathMapper($this->propertyAccessor); } - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getPropertyPath($path) - { - return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath') - ->setConstructorArgs([$path]) - ->setMethods(['getValue', 'setValue']) - ->getMock(); - } - - /** - * @param FormConfigInterface $config - * @param bool $synchronized - * @param bool $submitted - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) - { - $form = $this->getMockBuilder('Symfony\Component\Form\Form') - ->setConstructorArgs([$config]) - ->setMethods(['isSynchronized', 'isSubmitted']) - ->getMock(); - - $form->expects($this->any()) - ->method('isSynchronized') - ->will($this->returnValue($synchronized)); - - $form->expects($this->any()) - ->method('isSubmitted') - ->will($this->returnValue($submitted)); - - return $form; - } - public function testMapDataToFormsPassesObjectRefIfByReference() { $car = new \stdClass(); $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->with($car, $propertyPath) - ->will($this->returnValue($engine)); + $car->engine = $engine; + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); - $form = $this->getForm($config); + $form = new Form($config); $this->mapper->mapDataToForms($car, [$form]); - // Can't use isIdentical() above because mocks always clone their - // arguments which can't be disabled in PHPUnit 3.6 $this->assertSame($engine, $form->getData()); } @@ -103,17 +66,14 @@ public function testMapDataToFormsPassesObjectCloneIfNotByReference() { $car = new \stdClass(); $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->with($car, $propertyPath) - ->will($this->returnValue($engine)); + $engine->brand = 'Rolls-Royce'; + $car->engine = $engine; + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); - $form = $this->getForm($config); + $form = new Form($config); $this->mapper->mapDataToForms($car, [$form]); @@ -127,7 +87,7 @@ public function testMapDataToFormsIgnoresEmptyPropertyPath() $config = new FormConfigBuilder(null, '\stdClass', $this->dispatcher); $config->setByReference(true); - $form = $this->getForm($config); + $form = new Form($config); $this->assertNull($form->getPropertyPath()); @@ -139,16 +99,14 @@ public function testMapDataToFormsIgnoresEmptyPropertyPath() public function testMapDataToFormsIgnoresUnmapped() { $car = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('getValue'); + $car->engine = new \stdClass(); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setMapped(false); $config->setPropertyPath($propertyPath); - $form = $this->getForm($config); + $form = new Form($config); $this->mapper->mapDataToForms($car, [$form]); @@ -158,204 +116,188 @@ public function testMapDataToFormsIgnoresUnmapped() public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull() { $default = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('getValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); - $form = $this->getMockBuilder('Symfony\Component\Form\Form') - ->setConstructorArgs([$config]) - ->setMethods(['setData']) - ->getMock(); - - $form->expects($this->once()) - ->method('setData') - ->with($default); + $form = new Form($config); $this->mapper->mapDataToForms(null, [$form]); + + $this->assertSame($default, $form->getData()); } public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray() { $default = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('getValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); - $form = $this->getMockBuilder('Symfony\Component\Form\Form') - ->setConstructorArgs([$config]) - ->setMethods(['setData']) - ->getMock(); - - $form->expects($this->once()) - ->method('setData') - ->with($default); + $form = new Form($config); $this->mapper->mapDataToForms([], [$form]); + + $this->assertSame($default, $form->getData()); } public function testMapFormsToDataWritesBackIfNotByReference() { $car = new \stdClass(); + $car->engine = new \stdClass(); $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->once()) - ->method('setValue') - ->with($car, $propertyPath, $engine); + $engine->brand = 'Rolls-Royce'; + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $config->setData($engine); - $form = $this->getForm($config); + $form = new SubmittedForm($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertEquals($engine, $car->engine); + $this->assertNotSame($engine, $car->engine); } public function testMapFormsToDataWritesBackIfByReferenceButNoReference() { $car = new \stdClass(); + $car->engine = new \stdClass(); $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->once()) - ->method('setValue') - ->with($car, $propertyPath, $engine); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); - $form = $this->getForm($config); + $form = new SubmittedForm($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($engine, $car->engine); } public function testMapFormsToDataWritesBackIfByReferenceAndReference() { $car = new \stdClass(); - $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - // $car already contains the reference of $engine - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->with($car, $propertyPath) - ->will($this->returnValue($engine)); + $car->engine = 'BMW'; + $propertyPath = new PropertyPath('engine'); - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); - - $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config = new FormConfigBuilder('engine', null, $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); - $config->setData($engine); - $form = $this->getForm($config); + $config->setData('Rolls-Royce'); + $form = new SubmittedForm($config); + + $car->engine = 'Rolls-Royce'; $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame('Rolls-Royce', $car->engine); } public function testMapFormsToDataIgnoresUnmapped() { + $initialEngine = new \stdClass(); $car = new \stdClass(); + $car->engine = $initialEngine; $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setMapped(false); - $form = $this->getForm($config); + $form = new SubmittedForm($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($initialEngine, $car->engine); } public function testMapFormsToDataIgnoresUnsubmittedForms() { + $initialEngine = new \stdClass(); $car = new \stdClass(); + $car->engine = $initialEngine; $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); - $form = $this->getForm($config, true, false); + $form = new Form($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($initialEngine, $car->engine); } public function testMapFormsToDataIgnoresEmptyData() { + $initialEngine = new \stdClass(); $car = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); + $car->engine = $initialEngine; + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData(null); - $form = $this->getForm($config); + $form = new Form($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($initialEngine, $car->engine); } public function testMapFormsToDataIgnoresUnsynchronized() { + $initialEngine = new \stdClass(); $car = new \stdClass(); + $car->engine = $initialEngine; $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); - $form = $this->getForm($config, false); + $form = new NotSynchronizedForm($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($initialEngine, $car->engine); } public function testMapFormsToDataIgnoresDisabled() { + $initialEngine = new \stdClass(); $car = new \stdClass(); + $car->engine = $initialEngine; $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->never()) - ->method('setValue'); + $propertyPath = new PropertyPath('engine'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setDisabled(true); - $form = $this->getForm($config); + $form = new Form($config); $this->mapper->mapFormsToData([$form], $car); + + $this->assertSame($initialEngine, $car->engine); } /** @@ -365,24 +307,19 @@ public function testMapFormsToDataDoesNotChangeEqualDateTimeInstance($date) { $article = []; $publishedAt = $date; - $article['publishedAt'] = clone $publishedAt; - $propertyPath = $this->getPropertyPath('[publishedAt]'); - - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->willReturn($article['publishedAt']) - ; - $this->propertyAccessor->expects($this->never()) - ->method('setValue') - ; + $publishedAtValue = clone $publishedAt; + $article['publishedAt'] = $publishedAtValue; + $propertyPath = new PropertyPath('[publishedAt]'); $config = new FormConfigBuilder('publishedAt', \get_class($publishedAt), $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $config->setData($publishedAt); - $form = $this->getForm($config); + $form = new SubmittedForm($config); $this->mapper->mapFormsToData([$form], $article); + + $this->assertSame($publishedAtValue, $article['publishedAt']); } public function provideDate() @@ -393,3 +330,19 @@ public function provideDate() ]; } } + +class SubmittedForm extends Form +{ + public function isSubmitted() + { + return true; + } +} + +class NotSynchronizedForm extends Form +{ + public function isSynchronized() + { + return false; + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index 193aba91ab3b8..8cdbb1959a79e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -95,9 +95,7 @@ public function testReverseTransform() $transformer = new IntegerToLocalizedStringTransformer(); $this->assertEquals(1, $transformer->reverseTransform('1')); - $this->assertEquals(1, $transformer->reverseTransform('1,5')); - $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); - $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); + $this->assertEquals(12345, $transformer->reverseTransform('12345')); } public function testReverseTransformEmpty() @@ -116,10 +114,10 @@ public function testReverseTransformWithGrouping() $transformer = new IntegerToLocalizedStringTransformer(null, true); - $this->assertEquals(1234, $transformer->reverseTransform('1.234,5')); - $this->assertEquals(12345, $transformer->reverseTransform('12.345,912')); - $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); - $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); + $this->assertEquals(1234, $transformer->reverseTransform('1.234')); + $this->assertEquals(12345, $transformer->reverseTransform('12.345')); + $this->assertEquals(1234, $transformer->reverseTransform('1234')); + $this->assertEquals(12345, $transformer->reverseTransform('12345')); } public function reverseTransformWithRoundingProvider() @@ -203,6 +201,29 @@ public function testReverseTransformExpectsValidNumber() $transformer->reverseTransform('foo'); } + /** + * @dataProvider floatNumberProvider + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformExpectsInteger($number, $locale) + { + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault($locale); + + $transformer = new IntegerToLocalizedStringTransformer(); + + $transformer->reverseTransform($number); + } + + public function floatNumberProvider() + { + return [ + ['12345.912', 'en'], + ['1.234,5', 'de_DE'], + ]; + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php index d9fafdff13a35..c5bffe4d96e65 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php @@ -17,6 +17,18 @@ class MoneyToLocalizedStringTransformerTest extends TestCase { + private $previousLocale; + + protected function setUp() + { + $this->previousLocale = setlocale(LC_ALL, '0'); + } + + protected function tearDown() + { + setlocale(LC_ALL, $this->previousLocale); + } + public function testTransform() { // Since we test against "de_AT", we need the full implementation @@ -73,7 +85,7 @@ public function testReverseTransformEmpty() $this->assertNull($transformer->reverseTransform('')); } - public function testFloatToIntConversionMismatchOnReversTransform() + public function testFloatToIntConversionMismatchOnReverseTransform() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); IntlTestHelper::requireFullIntl($this, false); @@ -90,4 +102,16 @@ public function testFloatToIntConversionMismatchOnTransform() $this->assertSame('10,20', $transformer->transform(1020)); } + + public function testValidNumericValuesWithNonDotDecimalPointCharacter() + { + // calling setlocale() here is important as it changes the representation of floats when being cast to strings + setlocale(LC_ALL, 'de_AT.UTF-8'); + + $transformer = new MoneyToLocalizedStringTransformer(4, null, null, 100); + IntlTestHelper::requireFullIntl($this, false); + \Locale::setDefault('de_AT'); + + $this->assertSame('0,0035', $transformer->transform(12 / 34)); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 0182aa23d301e..e00cb9e9e1978 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; use Symfony\Component\Form\Form; -use Symfony\Component\Form\FormConfigInterface; +use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; class FixUrlProtocolListenerTest extends TestCase @@ -22,7 +23,7 @@ class FixUrlProtocolListenerTest extends TestCase public function testFixHttpUrl() { $data = 'www.symfony.com'; - $form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock()); + $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); @@ -34,7 +35,7 @@ public function testFixHttpUrl() public function testSkipKnownUrl() { $data = 'http://www.symfony.com'; - $form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock()); + $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); @@ -59,7 +60,7 @@ public function provideUrlsWithSupportedProtocols() */ public function testSkipOtherProtocol($url) { - $form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock()); + $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $url); $filter = new FixUrlProtocolListener('http'); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php index 6f46c9d7fab37..5944537927de9 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormFactoryBuilder; class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest { @@ -22,6 +24,6 @@ protected function getData(array $data) protected function getBuilder($name = 'name') { - return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory); + return new FormBuilder($name, '\ArrayObject', new EventDispatcher(), (new FormFactoryBuilder())->getFormFactory()); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php index c0f3d59734bcb..4f19a3ff8e777 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormFactoryBuilder; class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest { @@ -22,6 +24,6 @@ protected function getData(array $data) protected function getBuilder($name = 'name') { - return new FormBuilder($name, null, $this->dispatcher, $this->factory); + return new FormBuilder($name, null, new EventDispatcher(), (new FormFactoryBuilder())->getFormFactory()); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php index 76bdc7682366b..4be3b4babae98 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject; class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest @@ -23,6 +25,6 @@ protected function getData(array $data) protected function getBuilder($name = 'name') { - return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory); + return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', new EventDispatcher(), (new FormFactoryBuilder())->getFormFactory()); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index 98cd78385a80d..8c691dffc1d75 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -17,21 +17,15 @@ abstract class MergeCollectionListenerTest extends TestCase { - protected $dispatcher; - protected $factory; protected $form; protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); $this->form = $this->getForm('axes'); } protected function tearDown() { - $this->dispatcher = null; - $this->factory = null; $this->form = null; } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 84a8c1db88847..ae7d2db4678dd 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -13,36 +13,37 @@ use Doctrine\Common\Collections\ArrayCollection; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormFactoryBuilder; class ResizeFormListenerTest extends TestCase { - private $dispatcher; private $factory; private $form; protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); + $this->factory = (new FormFactoryBuilder())->getFormFactory(); $this->form = $this->getBuilder() ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); } protected function tearDown() { - $this->dispatcher = null; $this->factory = null; $this->form = null; } protected function getBuilder($name = 'name') { - return new FormBuilder($name, null, $this->dispatcher, $this->factory); + return new FormBuilder($name, null, new EventDispatcher(), $this->factory); } protected function getForm($name = 'name') @@ -50,31 +51,14 @@ protected function getForm($name = 'name') return $this->getBuilder($name)->getForm(); } - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getDataMapper() - { - return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock(); - } - public function testPreSetDataResizesForm() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); - $this->factory->expects($this->at(0)) - ->method('createNamed') - ->with(1, 'text', null, ['property_path' => '[1]', 'attr' => ['maxlength' => 10], 'auto_initialize' => false]) - ->will($this->returnValue($this->getForm('1'))); - $this->factory->expects($this->at(1)) - ->method('createNamed') - ->with(2, 'text', null, ['property_path' => '[2]', 'attr' => ['maxlength' => 10], 'auto_initialize' => false]) - ->will($this->returnValue($this->getForm('2'))); - $data = [1 => 'string', 2 => 'string']; $event = new FormEvent($this->form, $data); - $listener = new ResizeFormListener('text', ['attr' => ['maxlength' => 10]], false, false); + $listener = new ResizeFormListener(TextType::class, ['attr' => ['maxlength' => 10]], false, false); $listener->preSetData($event); $this->assertFalse($this->form->has('0')); @@ -95,26 +79,21 @@ public function testPreSetDataRequiresArrayOrTraversable() public function testPreSetDataDealsWithNullData() { - $this->factory->expects($this->never())->method('createNamed'); - $data = null; $event = new FormEvent($this->form, $data); - $listener = new ResizeFormListener('text', [], false, false); + $listener = new ResizeFormListener(TextType::class, [], false, false); $listener->preSetData($event); + + $this->assertSame(0, $this->form->count()); } public function testPreSubmitResizesUpIfAllowAdd() { $this->form->add($this->getForm('0')); - $this->factory->expects($this->once()) - ->method('createNamed') - ->with(1, 'text', null, ['property_path' => '[1]', 'attr' => ['maxlength' => 10], 'auto_initialize' => false]) - ->will($this->returnValue($this->getForm('1'))); - $data = [0 => 'string', 1 => 'string']; $event = new FormEvent($this->form, $data); - $listener = new ResizeFormListener('text', ['attr' => ['maxlength' => 10]], true, false); + $listener = new ResizeFormListener(TextType::class, ['attr' => ['maxlength' => 10]], true, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); @@ -293,12 +272,12 @@ public function testOnSubmitDeleteEmptyCompoundEntriesIfAllowDelete() $this->form->setData(['0' => ['name' => 'John'], '1' => ['name' => 'Jane']]); $form1 = $this->getBuilder('0') ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $form1->add($this->getForm('name')); $form2 = $this->getBuilder('1') ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $form2->add($this->getForm('name')); $this->form->add($form1); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php index 78dae1bd82231..a61fb86a39b6e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Form; -use Symfony\Component\Form\FormConfigInterface; +use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; class TrimListenerTest extends TestCase @@ -22,7 +23,7 @@ class TrimListenerTest extends TestCase public function testTrim() { $data = ' Foo! '; - $form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock()); + $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $data); $filter = new TrimListener(); @@ -34,7 +35,7 @@ public function testTrim() public function testTrimSkipNonStrings() { $data = 1234; - $form = new Form($this->getMockBuilder(FormConfigInterface::class)->getMock()); + $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); $event = new FormEvent($form, $data); $filter = new TrimListener(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php index 92eff38669ff2..62654fc618376 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php @@ -12,12 +12,15 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\TypeTestCase; +use Symfony\Component\Form\Tests\VersionAwareTest; /** * @author Bernhard Schussek */ abstract class BaseTypeTest extends TypeTestCase { + use VersionAwareTest; + const TESTED_TYPE = ''; public function testPassDisabledAsOption() diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php index c1e0571ec7862..ea012c451e885 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\NativeRequestHandler; use Symfony\Component\Form\RequestHandlerInterface; +use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\UploadedFile; class FileTypeTest extends BaseTypeTest @@ -24,9 +25,7 @@ class FileTypeTest extends BaseTypeTest public function testSetData() { $form = $this->factory->createBuilder(static::TESTED_TYPE)->getForm(); - $data = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File') - ->setConstructorArgs([__DIR__.'/../../../Fixtures/foo', 'foo']) - ->getMock(); + $data = new File(__DIR__.'/../../../Fixtures/foo', false); $form->setData($data); @@ -40,7 +39,7 @@ public function testSetData() public function testSubmit(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE)->setRequestHandler($requestHandler)->getForm(); - $data = $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'); + $data = $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'); $form->submit($data); @@ -57,8 +56,8 @@ public function testSetDataMultiple(RequestHandlerInterface $requestHandler) ])->setRequestHandler($requestHandler)->getForm(); $data = [ - $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), - $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), + $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), + $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), ]; $form->setData($data); @@ -75,8 +74,8 @@ public function testSubmitMultiple(RequestHandlerInterface $requestHandler) ])->setRequestHandler($requestHandler)->getForm(); $data = [ - $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), - $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), + $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), + $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), ]; $form->submit($data); @@ -94,7 +93,7 @@ public function testDontPassValueToView(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE)->setRequestHandler($requestHandler)->getForm(); $form->submit([ - 'file' => $this->createUploadedFileMock($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), + 'file' => $this->createUploadedFile($requestHandler, __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), ]); $this->assertEquals('', $form->createView()->vars['value']); @@ -152,8 +151,8 @@ public function testMultipleSubmittedFilePathsAreDropped(RequestHandlerInterface ->getForm(); $form->submit([ 'file:///etc/passwd', - $this->createUploadedFileMock(new HttpFoundationRequestHandler(), __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), - $this->createUploadedFileMock(new NativeRequestHandler(), __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), + $this->createUploadedFile(new HttpFoundationRequestHandler(), __DIR__.'/../../../Fixtures/foo', 'foo.jpg'), + $this->createUploadedFile(new NativeRequestHandler(), __DIR__.'/../../../Fixtures/foo2', 'foo2.jpg'), ]); $this->assertCount(1, $form->getData()); @@ -185,7 +184,7 @@ public function requestHandlerProvider() ]; } - private function createUploadedFileMock(RequestHandlerInterface $requestHandler, $path, $originalName) + private function createUploadedFile(RequestHandlerInterface $requestHandler, $path, $originalName) { if ($requestHandler instanceof HttpFoundationRequestHandler) { return new UploadedFile($path, $originalName, null, 10, null, true); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php index 273402aefeb32..c5c7dd9161b7e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -24,14 +24,15 @@ protected function setUp() parent::setUp(); } - public function testSubmitCastsToInteger() + public function testSubmitRejectsFloats() { $form = $this->factory->create(static::TESTED_TYPE); $form->submit('1.678'); - $this->assertSame(1, $form->getData()); - $this->assertSame('1', $form->getViewData()); + $this->assertTrue($form->isSubmitted()); + $this->assertFalse($form->isValid()); + $this->assertFalse($form->isSynchronized()); } public function testSubmitNull($expected = null, $norm = null, $view = null) @@ -50,4 +51,45 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = '10', $expectedD $this->assertSame($expectedData, $form->getNormData()); $this->assertSame($expectedData, $form->getData()); } + + public function testSubmittedLargeIntegersAreNotCastToFloat() + { + if (4 === \PHP_INT_SIZE) { + $this->markTestSkipped('This test requires a 64bit PHP.'); + } + + $form = $this->factory->create(static::TESTED_TYPE); + $form->submit('201803221011791'); + + $this->assertSame(201803221011791, $form->getData()); + $this->assertSame('201803221011791', $form->getViewData()); + } + + public function testTooSmallIntegersAreNotValid() + { + if (4 === \PHP_INT_SIZE) { + $min = '-2147483649'; + } else { + $min = '-9223372036854775808'; + } + + $form = $this->factory->create(static::TESTED_TYPE); + $form->submit($min); + + $this->assertFalse($form->isSynchronized()); + } + + public function testTooGreatIntegersAreNotValid() + { + if (4 === \PHP_INT_SIZE) { + $max = '2147483648'; + } else { + $max = '9223372036854775808'; + } + + $form = $this->factory->create(static::TESTED_TYPE); + $form->submit($max); + + $this->assertFalse($form->isSynchronized()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 43e9acad057c4..5876b092b9da0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -12,9 +12,13 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormFactoryBuilder; +use Symfony\Component\Security\Csrf\CsrfTokenManager; class CsrfValidationListenerTest extends TestCase { @@ -25,11 +29,11 @@ class CsrfValidationListenerTest extends TestCase protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); - $this->tokenManager = $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock(); + $this->dispatcher = new EventDispatcher(); + $this->factory = (new FormFactoryBuilder())->getFormFactory(); + $this->tokenManager = new CsrfTokenManager(); $this->form = $this->getBuilder() - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); } @@ -46,11 +50,6 @@ protected function getBuilder() return new FormBuilder('post', null, $this->dispatcher, $this->factory, ['compound' => true]); } - protected function getDataMapper() - { - return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock(); - } - // https://github.com/symfony/symfony/pull/5838 public function testStringFormData() { @@ -64,6 +63,16 @@ public function testStringFormData() $this->assertSame($data, $event->getData()); } + public function testArrayCsrfToken() + { + $event = new FormEvent($this->form, ['csrf' => []]); + + $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.'); + $validation->preSubmit($event); + + $this->assertNotEmpty($this->form->getErrors()); + } + public function testMaxPostSizeExceeded() { $serverParams = $this diff --git a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php index b78bd67ae0f3a..375fbfc7021a1 100644 --- a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php @@ -12,7 +12,8 @@ namespace Symfony\Component\Form\Tests\Extension\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\FormTypeGuesserInterface; @@ -21,19 +22,16 @@ class DependencyInjectionExtensionTest extends TestCase { public function testGetTypeExtensions() { - $container = $this->createContainerMock(); - $container->expects($this->never())->method('get'); - - $typeExtension1 = $this->createFormTypeExtensionMock('test'); - $typeExtension2 = $this->createFormTypeExtensionMock('test'); - $typeExtension3 = $this->createFormTypeExtensionMock('other'); + $typeExtension1 = new DummyExtension('test'); + $typeExtension2 = new DummyExtension('test'); + $typeExtension3 = new DummyExtension('other'); $extensions = [ 'test' => new \ArrayIterator([$typeExtension1, $typeExtension2]), 'other' => new \ArrayIterator([$typeExtension3]), ]; - $extension = new DependencyInjectionExtension($container, $extensions, []); + $extension = new DependencyInjectionExtension(new ContainerBuilder(), $extensions, []); $this->assertTrue($extension->hasTypeExtensions('test')); $this->assertTrue($extension->hasTypeExtensions('other')); @@ -47,14 +45,11 @@ public function testGetTypeExtensions() */ public function testThrowExceptionForInvalidExtendedType() { - $container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(); - $container->expects($this->never())->method('get'); - $extensions = [ - 'test' => new \ArrayIterator([$this->createFormTypeExtensionMock('unmatched')]), + 'test' => new \ArrayIterator([new DummyExtension('unmatched')]), ]; - $extension = new DependencyInjectionExtension($container, $extensions, []); + $extension = new DependencyInjectionExtension(new ContainerBuilder(), $extensions, []); $extension->getTypeExtensions('test'); } @@ -65,23 +60,15 @@ public function testThrowExceptionForInvalidExtendedType() */ public function testLegacyGetTypeExtensions() { - $container = $this->createContainerMock(); - - $services = [ - 'extension1' => $typeExtension1 = $this->createFormTypeExtensionMock('test'), - 'extension2' => $typeExtension2 = $this->createFormTypeExtensionMock('test'), - 'extension3' => $typeExtension3 = $this->createFormTypeExtensionMock('other'), - ]; + $container = new ContainerBuilder(); - $container->expects($this->any()) - ->method('get') - ->willReturnCallback(function ($id) use ($services) { - if (isset($services[$id])) { - return $services[$id]; - } + $typeExtension1 = new DummyExtension('test'); + $typeExtension2 = new DummyExtension('test'); + $typeExtension3 = new DummyExtension('other'); - throw new ServiceNotFoundException($id); - }); + $container->set('extension1', $typeExtension1); + $container->set('extension2', $typeExtension2); + $container->set('extension3', $typeExtension3); $extension = new DependencyInjectionExtension($container, [], ['test' => ['extension1', 'extension2'], 'other' => ['extension3']], []); @@ -97,14 +84,10 @@ public function testLegacyGetTypeExtensions() */ public function testLegacyThrowExceptionForInvalidExtendedType() { - $formTypeExtension = $this->createFormTypeExtensionMock('unmatched'); - - $container = $this->createContainerMock(); + $formTypeExtension = new DummyExtension('unmatched'); - $container->expects($this->any()) - ->method('get') - ->with('extension') - ->willReturn($formTypeExtension); + $container = new ContainerBuilder(); + $container->set('extension', $formTypeExtension); $extension = new DependencyInjectionExtension($container, [], ['test' => ['extension']], []); @@ -116,16 +99,14 @@ public function testLegacyThrowExceptionForInvalidExtendedType() public function testGetTypeGuesser() { - $container = $this->createContainerMock(); - $extension = new DependencyInjectionExtension($container, [], [$this->getMockBuilder(FormTypeGuesserInterface::class)->getMock()]); + $extension = new DependencyInjectionExtension(new ContainerBuilder(), [], [$this->getMockBuilder(FormTypeGuesserInterface::class)->getMock()]); $this->assertInstanceOf(FormTypeGuesserChain::class, $extension->getTypeGuesser()); } public function testGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigured() { - $container = $this->createContainerMock(); - $extension = new DependencyInjectionExtension($container, [], []); + $extension = new DependencyInjectionExtension(new ContainerBuilder(), [], []); $this->assertNull($extension->getTypeGuesser()); } @@ -135,12 +116,9 @@ public function testGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigure */ public function testLegacyGetTypeGuesser() { - $container = $this->createContainerMock(); - $container - ->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($this->getMockBuilder(FormTypeGuesserInterface::class)->getMock()); + $container = new ContainerBuilder(); + $container->set('foo', new DummyTypeGuesser()); + $extension = new DependencyInjectionExtension($container, [], [], ['foo']); $this->assertInstanceOf(FormTypeGuesserChain::class, $extension->getTypeGuesser()); @@ -151,24 +129,42 @@ public function testLegacyGetTypeGuesser() */ public function testLegacyGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigured() { - $container = $this->createContainerMock(); - $extension = new DependencyInjectionExtension($container, [], [], []); + $extension = new DependencyInjectionExtension(new ContainerBuilder(), [], [], []); $this->assertNull($extension->getTypeGuesser()); } +} + +class DummyExtension extends AbstractTypeExtension +{ + private $extendedType; + + public function __construct($extendedType) + { + $this->extendedType = $extendedType; + } - private function createContainerMock() + public function getExtendedType() { - return $this->getMockBuilder('Psr\Container\ContainerInterface') - ->setMethods(['get', 'has']) - ->getMock(); + return $this->extendedType; } +} - private function createFormTypeExtensionMock($extendedType) +class DummyTypeGuesser implements FormTypeGuesserInterface +{ + public function guessType($class, $property) { - $extension = $this->getMockBuilder('Symfony\Component\Form\FormTypeExtensionInterface')->getMock(); - $extension->expects($this->any())->method('getExtendedType')->willReturn($extendedType); + } - return $extension; + public function guessRequired($class, $property) + { + } + + public function guessMaxLength($class, $property) + { + } + + public function guessPattern($class, $property) + { } } diff --git a/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index 5597e835542df..2b134511830e7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -47,7 +47,7 @@ protected function getRequestHandler() return new HttpFoundationRequestHandler($this->serverParams); } - protected function getMockFile($suffix = '') + protected function getUploadedFile($suffix = '') { return new UploadedFile(__DIR__.'/../../Fixtures/foo'.$suffix, 'foo'.$suffix); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 399f2d70cafb5..7581f7698c12c 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -11,18 +11,26 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormFactoryBuilder; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\SubmitButtonBuilder; +use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\Context\ExecutionContext; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; +use Symfony\Component\Validator\Validation; /** * @author Bernhard Schussek @@ -30,43 +38,31 @@ class FormValidatorTest extends ConstraintValidatorTestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EventDispatcherInterface */ private $dispatcher; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var FormFactoryInterface */ private $factory; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $serverParams; - protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); - $this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(['getNormalizedIniPostMaxSize', 'getContentLength'])->getMock(); + $this->dispatcher = new EventDispatcher(); + $this->factory = (new FormFactoryBuilder())->getFormFactory(); parent::setUp(); $this->constraint = new Form(); } - protected function createValidator() - { - return new FormValidator($this->serverParams); - } - public function testValidate() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $options = ['validation_groups' => ['group1', 'group2']]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -77,7 +73,7 @@ public function testValidate() public function testValidateConstraints() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $constraint1 = new NotNull(['groups' => ['group1', 'group2']]); $constraint2 = new NotBlank(['groups' => 'group2']); @@ -85,9 +81,8 @@ public function testValidateConstraints() 'validation_groups' => ['group1', 'group2'], 'constraints' => [$constraint1, $constraint2], ]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); // First default constraints $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -103,20 +98,19 @@ public function testValidateConstraints() public function testValidateChildIfValidConstraint() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parent = $this->getBuilder('parent') ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $options = [ 'validation_groups' => ['group1', 'group2'], 'constraints' => [new Valid()], ]; - $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); + $form = $this->getCompoundForm($object, $options); $parent->add($form); - - $form->setData($object); + $parent->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -127,11 +121,11 @@ public function testValidateChildIfValidConstraint() public function testDontValidateIfParentWithoutValidConstraint() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parent = $this->getBuilder('parent', null) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $options = ['validation_groups' => ['group1', 'group2']]; $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); @@ -149,8 +143,8 @@ public function testDontValidateIfParentWithoutValidConstraint() public function testMissingConstraintIndex() { $object = new \stdClass(); - $form = new FormBuilder('name', '\stdClass', $this->dispatcher, $this->factory); - $form = $form->setData($object)->getForm(); + $form = $this->getCompoundForm($object); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['Default']); @@ -161,22 +155,21 @@ public function testMissingConstraintIndex() public function testValidateConstraintsOptionEvenIfNoValidConstraint() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $constraint1 = new NotNull(['groups' => ['group1', 'group2']]); $constraint2 = new NotBlank(['groups' => 'group2']); $parent = $this->getBuilder('parent', null) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $options = [ 'validation_groups' => ['group1', 'group2'], 'constraints' => [$constraint1, $constraint2], ]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); $parent->add($form); + $parent->submit([]); $this->expectValidateValueAt(0, 'data', $object, $constraint1, 'group1'); $this->expectValidateValueAt(1, 'data', $object, $constraint2, 'group2'); @@ -188,7 +181,7 @@ public function testValidateConstraintsOptionEvenIfNoValidConstraint() public function testDontValidateIfNoValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $form = $this->getBuilder('name', '\stdClass', [ 'validation_groups' => [], @@ -207,13 +200,11 @@ public function testDontValidateIfNoValidationGroups() public function testDontValidateConstraintsIfNoValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); - $constraint1 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock(); - $constraint2 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock(); + $object = new \stdClass(); $options = [ 'validation_groups' => [], - 'constraints' => [$constraint1, $constraint2], + 'constraints' => [new NotBlank(), new NotNull()], ]; $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) @@ -231,7 +222,7 @@ public function testDontValidateConstraintsIfNoValidationGroups() public function testDontValidateIfNotSynchronized() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $form = $this->getBuilder('name', '\stdClass', [ 'invalid_message' => 'invalid_message_key', @@ -265,7 +256,7 @@ function () { throw new TransformationFailedException(); } public function testAddInvalidErrorEvenIfNoValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $form = $this->getBuilder('name', '\stdClass', [ 'invalid_message' => 'invalid_message_key', @@ -300,14 +291,12 @@ function () { throw new TransformationFailedException(); } public function testDontValidateConstraintsIfNotSynchronized() { - $object = $this->getMockBuilder('\stdClass')->getMock(); - $constraint1 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock(); - $constraint2 = $this->getMockBuilder('Symfony\Component\Validator\Constraint')->getMock(); + $object = new \stdClass(); $options = [ 'invalid_message' => 'invalid_message_key', 'validation_groups' => ['group1', 'group2'], - 'constraints' => [$constraint1, $constraint2], + 'constraints' => [new NotBlank(), new NotBlank()], ]; $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) @@ -335,7 +324,8 @@ function () { throw new TransformationFailedException(); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); + $object->child = 'bar'; $failingTransformer = new CallbackTransformer( function ($data) { return $data; }, @@ -346,7 +336,7 @@ function () { throw new TransformationFailedException(); } ->setData($object) ->addViewTransformer($failingTransformer) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->add( $this->getBuilder('child') ->addViewTransformer($failingTransformer) @@ -365,11 +355,10 @@ function () { throw new TransformationFailedException(); } public function testHandleGroupSequenceValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $options = ['validation_groups' => new GroupSequence(['group1', 'group2'])]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, new GroupSequence(['group1', 'group2'])); $this->expectValidateAt(1, 'data', $object, new GroupSequence(['group1', 'group2'])); @@ -381,11 +370,10 @@ public function testHandleGroupSequenceValidationGroups() public function testHandleCallbackValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $options = ['validation_groups' => [$this, 'getValidationGroups']]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -396,11 +384,10 @@ public function testHandleCallbackValidationGroups() public function testDontExecuteFunctionNames() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $options = ['validation_groups' => 'header']; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['header']); @@ -411,13 +398,12 @@ public function testDontExecuteFunctionNames() public function testHandleClosureValidationGroups() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $options = ['validation_groups' => function (FormInterface $form) { return ['group1', 'group2']; }]; - $form = $this->getBuilder('name', '\stdClass', $options) - ->setData($object) - ->getForm(); + $form = $this->getCompoundForm($object, $options); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -428,11 +414,11 @@ public function testHandleClosureValidationGroups() public function testUseValidationGroupOfClickedButton() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parent = $this->getBuilder('parent') ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', [ 'validation_groups' => 'form_group', @@ -455,13 +441,13 @@ public function testUseValidationGroupOfClickedButton() public function testDontUseValidationGroupOfUnclickedButton() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parent = $this->getBuilder('parent') ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); - $form = $this->getForm('name', '\stdClass', [ + $form = $this->getCompoundForm($object, [ 'validation_groups' => 'form_group', 'constraints' => [new Valid()], ]); @@ -471,7 +457,7 @@ public function testDontUseValidationGroupOfUnclickedButton() 'validation_groups' => 'button_group', ])); - $form->setData($object); + $parent->submit([]); $this->expectValidateAt(0, 'data', $object, ['form_group']); @@ -482,18 +468,17 @@ public function testDontUseValidationGroupOfUnclickedButton() public function testUseInheritedValidationGroup() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parentOptions = ['validation_groups' => 'group']; $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $formOptions = ['constraints' => [new Valid()]]; - $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); + $form = $this->getCompoundForm($object, $formOptions); $parent->add($form); - - $form->setData($object); + $parent->submit([]); $this->expectValidateAt(0, 'data', $object, ['group']); @@ -504,18 +489,17 @@ public function testUseInheritedValidationGroup() public function testUseInheritedCallbackValidationGroup() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parentOptions = ['validation_groups' => [$this, 'getValidationGroups']]; $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $formOptions = ['constraints' => [new Valid()]]; - $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); + $form = $this->getCompoundForm($object, $formOptions); $parent->add($form); - - $form->setData($object); + $parent->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -526,22 +510,21 @@ public function testUseInheritedCallbackValidationGroup() public function testUseInheritedClosureValidationGroup() { - $object = $this->getMockBuilder('\stdClass')->getMock(); + $object = new \stdClass(); $parentOptions = [ - 'validation_groups' => function (FormInterface $form) { + 'validation_groups' => function () { return ['group1', 'group2']; }, ]; $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->getForm(); $formOptions = ['constraints' => [new Valid()]]; - $form = $this->getBuilder('name', '\stdClass', $formOptions)->getForm(); + $form = $this->getCompoundForm($object, $formOptions); $parent->add($form); - - $form->setData($object); + $parent->submit([]); $this->expectValidateAt(0, 'data', $object, ['group1', 'group2']); @@ -552,10 +535,9 @@ public function testUseInheritedClosureValidationGroup() public function testAppendPropertyPath() { - $object = $this->getMockBuilder('\stdClass')->getMock(); - $form = $this->getBuilder('name', '\stdClass') - ->setData($object) - ->getForm(); + $object = new \stdClass(); + $form = $this->getCompoundForm($object); + $form->submit([]); $this->expectValidateAt(0, 'data', $object, ['Default']); @@ -581,7 +563,7 @@ public function testViolationIfExtraData() { $form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!']) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->add($this->getBuilder('child')) ->getForm(); @@ -602,7 +584,7 @@ public function testViolationFormatIfMultipleExtraFields() { $form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!']) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->add($this->getBuilder('child')) ->getForm(); @@ -621,22 +603,21 @@ public function testViolationFormatIfMultipleExtraFields() public function testNoViolationIfAllowExtraData() { - $context = $this->getMockExecutionContext(); - $form = $this ->getBuilder('parent', null, ['allow_extra_fields' => true]) ->setCompound(true) - ->setDataMapper($this->getDataMapper()) + ->setDataMapper(new PropertyPathMapper()) ->add($this->getBuilder('child')) ->getForm(); - $form->submit(['foo' => 'bar']); + $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $context->expects($this->never()) - ->method('addViolation'); + $form->submit(['foo' => 'bar']); $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertCount(0, $context->getViolations()); } /** @@ -649,22 +630,30 @@ public function getValidationGroups(FormInterface $form) return ['group1', 'group2']; } - private function getMockExecutionContext() + public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint() { - $context = $this->getMockBuilder('Symfony\Component\Validator\Context\ExecutionContextInterface')->getMock(); - $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); - $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock(); + $form = $this + ->getBuilder('form', null, ['constraints' => [new NotBlank(['groups' => ['foo']])]]) + ->setCompound(true) + ->setDataMapper(new PropertyPathMapper()) + ->getForm(); + $form->submit([ + 'extra_data' => 'foo', + ]); - $validator->expects($this->any()) - ->method('inContext') - ->with($context) - ->will($this->returnValue($contextualValidator)); + $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); + $constraint = new Form(); - $context->expects($this->any()) - ->method('getValidator') - ->will($this->returnValue($validator)); + $this->validator->initialize($context); + $this->validator->validate($form, $constraint); - return $context; + $this->assertCount(1, $context->getViolations()); + $this->assertSame($constraint, $context->getViolations()->get(0)->getConstraint()); + } + + protected function createValidator() + { + return new FormValidator(); } /** @@ -689,18 +678,19 @@ private function getForm($name = 'name', $dataClass = null, array $options = []) return $this->getBuilder($name, $dataClass, $options)->getForm(); } + private function getCompoundForm($data, array $options = []) + { + return $this->getBuilder('name', \get_class($data), $options) + ->setData($data) + ->setCompound(true) + ->setDataMapper(new PropertyPathMapper()) + ->getForm(); + } + private function getSubmitButton($name = 'name', array $options = []) { $builder = new SubmitButtonBuilder($name, $options); return $builder->getForm(); } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getDataMapper() - { - return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock(); - } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 855a90d2e3479..76bc07b2ee981 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -12,40 +12,41 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\Validator\Constraints\Form as FormConstraint; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; +use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; -use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\ConstraintViolationInterface; +use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Validator\Validation; +use Symfony\Component\Validator\Validator\ValidatorInterface; class ValidationListenerTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EventDispatcherInterface */ private $dispatcher; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var FormFactoryInterface */ private $factory; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ValidatorInterface */ private $validator; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $violationMapper; - /** * @var ValidationListener */ @@ -59,40 +60,18 @@ class ValidationListenerTest extends TestCase protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->factory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(); - $this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); - $this->violationMapper = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface')->getMock(); - $this->listener = new ValidationListener($this->validator, $this->violationMapper); + $this->dispatcher = new EventDispatcher(); + $this->factory = (new FormFactoryBuilder())->getFormFactory(); + $this->validator = Validation::createValidator(); + $this->listener = new ValidationListener($this->validator, new ViolationMapper()); $this->message = 'Message'; $this->messageTemplate = 'Message template'; $this->params = ['foo' => 'bar']; } - private function getConstraintViolation($code = null) - { - return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code, new FormConstraint()); - } - - private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) - { - $builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory); - $builder->setPropertyPath(new PropertyPath($propertyPath ?: $name)); - $builder->setAttribute('error_mapping', []); - $builder->setErrorBubbling(false); - $builder->setMapped(true); - - return $builder; - } - - private function getForm($name = 'name', $propertyPath = null, $dataClass = null) - { - return $this->getBuilder($name, $propertyPath, $dataClass)->getForm(); - } - private function createForm($name = '', $compound = false) { - $config = new FormBuilder($name, null, $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), $this->getMockBuilder(FormFactoryInterface::class)->getMock()); + $config = new FormBuilder($name, null, new EventDispatcher(), (new FormFactoryBuilder())->getFormFactory()); $config->setCompound($compound); if ($compound) { @@ -105,35 +84,29 @@ private function createForm($name = '', $compound = false) // More specific mapping tests can be found in ViolationMapperTest public function testMapViolation() { - $violation = $this->getConstraintViolation(); - $form = $this->getForm('street'); + $violation = new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'data', null, null, null, new FormConstraint()); + $form = new Form(new FormConfigBuilder('street', null, new EventDispatcher())); + $form->submit(null); - $this->validator->expects($this->once()) - ->method('validate') - ->will($this->returnValue([$violation])); + $validator = new DummyValidator($violation); + $listener = new ValidationListener($validator, new ViolationMapper()); + $listener->validateForm(new FormEvent($form, null)); - $this->violationMapper->expects($this->once()) - ->method('mapViolation') - ->with($violation, $form, false); - - $this->listener->validateForm(new FormEvent($form, null)); + $this->assertCount(1, $form->getErrors()); + $this->assertSame($violation, $form->getErrors()[0]->getCause()); } public function testMapViolationAllowsNonSyncIfInvalid() { - $violation = $this->getConstraintViolation(FormConstraint::NOT_SYNCHRONIZED_ERROR); - $form = $this->getForm('street'); + $violation = new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'data', null, null, FormConstraint::NOT_SYNCHRONIZED_ERROR, new FormConstraint()); + $form = new SubmittedNotSynchronizedForm(new FormConfigBuilder('street', null, new EventDispatcher())); - $this->validator->expects($this->once()) - ->method('validate') - ->will($this->returnValue([$violation])); + $validator = new DummyValidator($violation); + $listener = new ValidationListener($validator, new ViolationMapper()); + $listener->validateForm(new FormEvent($form, null)); - $this->violationMapper->expects($this->once()) - ->method('mapViolation') - // pass true now - ->with($violation, $form, true); - - $this->listener->validateForm(new FormEvent($form, null)); + $this->assertCount(1, $form->getErrors()); + $this->assertSame($violation, $form->getErrors()[0]->getCause()); } public function testValidateIgnoresNonRoot() @@ -143,36 +116,72 @@ public function testValidateIgnoresNonRoot() $form = $this->createForm('', true); $form->add($childForm); - $this->validator->expects($this->never()) - ->method('validate'); - - $this->violationMapper->expects($this->never()) - ->method('mapViolation'); + $form->submit(['child' => null]); $this->listener->validateForm(new FormEvent($childForm, null)); + + $this->assertTrue($childForm->isValid()); } public function testValidateWithEmptyViolationList() { $form = $this->createForm(); + $form->submit(null); - $this->validator - ->expects($this->once()) - ->method('validate') - ->will($this->returnValue(new ConstraintViolationList())); + $this->listener->validateForm(new FormEvent($form, null)); - $this->violationMapper - ->expects($this->never()) - ->method('mapViolation'); + $this->assertTrue($form->isValid()); + } +} - $this->listener->validateForm(new FormEvent($form, null)); +class SubmittedNotSynchronizedForm extends Form +{ + public function isSubmitted() + { + return true; } - public function testValidatorInterface() + public function isSynchronized() { - $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); + return false; + } +} + +class DummyValidator implements ValidatorInterface +{ + private $violation; - $listener = new ValidationListener($validator, $this->violationMapper); - $this->assertAttributeSame($validator, 'validator', $listener); + public function __construct(ConstraintViolationInterface $violation) + { + $this->violation = $violation; + } + + public function getMetadataFor($value) + { + } + + public function hasMetadataFor($value) + { + } + + public function validate($value, $constraints = null, $groups = null) + { + return [$this->violation]; + } + + public function validateProperty($object, $propertyName, $groups = null) + { + } + + public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null) + { + } + + public function startContext() + { + } + + public function inContext(ExecutionContextInterface $context) + { } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 8437d6f0975e8..53d29a19112c7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; -use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\Forms; use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; @@ -56,14 +55,6 @@ public function testValidConstraint() $this->assertSame([$valid], $form->getConfig()->getOption('constraints')); } - public function testValidatorInterface() - { - $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); - - $formTypeValidatorExtension = new FormTypeValidatorExtension($validator); - $this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension); - } - public function testGroupSequenceWithConstraintsOption() { $form = Forms::createFormFactoryBuilder() diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php index 7d4178bc83ea6..c4d8e8d948610 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php @@ -15,23 +15,17 @@ use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; class UploadValidatorExtensionTest extends TypeTestCase { public function testPostMaxSizeTranslation() { - $translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock(); - - $translator->expects($this->any()) - ->method('trans') - ->with($this->equalTo('old max {{ max }}!')) - ->willReturn('translated max {{ max }}!'); - - $extension = new UploadValidatorExtension($translator); + $extension = new UploadValidatorExtension(new DummyTranslator()); $resolver = new OptionsResolver(); $resolver->setDefault('post_max_size_message', 'old max {{ max }}!'); - $resolver->setDefault('upload_max_size_message', function (Options $options, $message) { + $resolver->setDefault('upload_max_size_message', function (Options $options) { return function () use ($options) { return $options['post_max_size_message']; }; @@ -43,3 +37,25 @@ public function testPostMaxSizeTranslation() $this->assertEquals('translated max {{ max }}!', \call_user_func($options['upload_max_size_message'])); } } + +class DummyTranslator implements TranslatorInterface +{ + public function trans($id, array $parameters = [], $domain = null, $locale = null) + { + return 'translated max {{ max }}!'; + } + + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) + { + return 'translated max {{ max }}!'; + } + + public function setLocale($locale) + { + } + + public function getLocale() + { + return 'en'; + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php index 0803e18de9e83..049876246c507 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; class ServerParamsTest extends TestCase { @@ -32,8 +33,8 @@ public function testGetContentLengthFromSuperglobals() public function testGetContentLengthFromRequest() { $request = Request::create('http://foo', 'GET', [], [], [], ['CONTENT_LENGTH' => 1024]); - $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(['getCurrentRequest'])->getMock(); - $requestStack->expects($this->once())->method('getCurrentRequest')->will($this->returnValue($request)); + $requestStack = new RequestStack(); + $requestStack->push($request); $serverParams = new ServerParams($requestStack); $this->assertEquals(1024, $serverParams->getContentLength()); @@ -42,11 +43,7 @@ public function testGetContentLengthFromRequest() /** @dataProvider getGetPostMaxSizeTestData */ public function testGetPostMaxSize($size, $bytes) { - $serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(['getNormalizedIniPostMaxSize'])->getMock(); - $serverParams - ->expects($this->any()) - ->method('getNormalizedIniPostMaxSize') - ->will($this->returnValue(strtoupper($size))); + $serverParams = new DummyServerParams($size); $this->assertEquals($bytes, $serverParams->getPostMaxSize()); } @@ -70,3 +67,20 @@ public function getGetPostMaxSizeTestData() ]; } } + +class DummyServerParams extends ServerParams +{ + private $size; + + public function __construct($size) + { + parent::__construct(); + + $this->size = $size; + } + + public function getNormalizedIniPostMaxSize() + { + return $this->size; + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php index ce18d0b6c5718..136086a5e5ba8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -12,37 +12,118 @@ namespace Symfony\Component\Form\Tests\Extension\Validator; use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Validator\Constraints\Form as FormConstraint; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryBuilder; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Mapping\CascadingStrategy; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; +use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; +use Symfony\Component\Validator\Mapping\TraversalStrategy; +use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; +use Symfony\Component\Validator\Validation; class ValidatorExtensionTest extends TestCase { public function test2Dot5ValidationApi() { - $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator') - ->disableOriginalConstructor() - ->getMock(); - $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') - ->setMethods(['addConstraint', 'addPropertyConstraint']) - ->disableOriginalConstructor() - ->getMock(); + $metadata = new ClassMetadata(Form::class); - $validator->expects($this->once()) - ->method('getMetadataFor') - ->with($this->identicalTo('Symfony\Component\Form\Form')) - ->will($this->returnValue($metadata)); + $metadataFactory = new FakeMetadataFactory(); + $metadataFactory->addMetadata($metadata); - // Verify that the constraints are added - $metadata->expects($this->once()) - ->method('addConstraint') - ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); - - $metadata->expects($this->once()) - ->method('addPropertyConstraint') - ->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid')); + $validator = Validation::createValidatorBuilder() + ->setMetadataFactory($metadataFactory) + ->getValidator(); $extension = new ValidatorExtension($validator); - $guesser = $extension->loadTypeGuesser(); - $this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser); + $this->assertInstanceOf(ValidatorTypeGuesser::class, $extension->loadTypeGuesser()); + + $this->assertCount(1, $metadata->getConstraints()); + $this->assertInstanceOf(FormConstraint::class, $metadata->getConstraints()[0]); + + $this->assertSame(CascadingStrategy::CASCADE, $metadata->getPropertyMetadata('children')[0]->cascadingStrategy); + $this->assertSame(TraversalStrategy::IMPLICIT, $metadata->getPropertyMetadata('children')[0]->traversalStrategy); + } + + public function testDataConstraintsInvalidateFormEvenIfFieldIsNotSubmitted() + { + $form = $this->createForm(FooType::class); + $form->submit(['baz' => 'foobar'], false); + + $this->assertTrue($form->isSubmitted()); + $this->assertFalse($form->isValid()); + $this->assertFalse($form->get('bar')->isSubmitted()); + $this->assertCount(1, $form->get('bar')->getErrors()); + } + + public function testFieldConstraintsDoNotInvalidateFormIfFieldIsNotSubmitted() + { + $form = $this->createForm(FooType::class); + $form->submit(['bar' => 'foobar'], false); + + $this->assertTrue($form->isSubmitted()); + $this->assertTrue($form->isValid()); + } + + public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted() + { + $form = $this->createForm(FooType::class); + $form->submit(['bar' => 'foobar', 'baz' => ''], false); + + $this->assertTrue($form->isSubmitted()); + $this->assertFalse($form->isValid()); + $this->assertTrue($form->get('bar')->isSubmitted()); + $this->assertTrue($form->get('bar')->isValid()); + $this->assertTrue($form->get('baz')->isSubmitted()); + $this->assertFalse($form->get('baz')->isValid()); + } + + private function createForm($type) + { + $validator = Validation::createValidatorBuilder() + ->setMetadataFactory(new LazyLoadingMetadataFactory(new StaticMethodLoader())) + ->getValidator(); + $formFactoryBuilder = new FormFactoryBuilder(); + $formFactoryBuilder->addExtension(new ValidatorExtension($validator)); + $formFactory = $formFactoryBuilder->getFormFactory(); + + return $formFactory->create($type); + } +} + +class Foo +{ + public $bar; + public $baz; + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('bar', new NotBlank()); + } +} + +class FooType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add('bar') + ->add('baz', null, [ + 'constraints' => [new NotBlank()], + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('data_class', Foo::class); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index d14c89c2cbda1..878bbfad21bc5 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -23,6 +23,8 @@ use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; +use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; /** * @author franek @@ -45,18 +47,15 @@ class ValidatorTypeGuesserTest extends TestCase private $metadata; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MetadataFactoryInterface */ private $metadataFactory; protected function setUp() { $this->metadata = new ClassMetadata(self::TEST_CLASS); - $this->metadataFactory = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface')->getMock(); - $this->metadataFactory->expects($this->any()) - ->method('getMetadataFor') - ->with(self::TEST_CLASS) - ->will($this->returnValue($this->metadata)); + $this->metadataFactory = new FakeMetadataFactory(); + $this->metadataFactory->addMetadata($this->metadata); $this->guesser = new ValidatorTypeGuesser($this->metadataFactory); } 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 1278a86e22c2a..2fa3e928926ee 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -12,8 +12,11 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; @@ -34,7 +37,7 @@ class ViolationMapperTest extends TestCase const LEVEL_2 = 3; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EventDispatcherInterface */ private $dispatcher; @@ -60,7 +63,7 @@ class ViolationMapperTest extends TestCase protected function setUp() { - $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $this->dispatcher = new EventDispatcher(); $this->mapper = new ViolationMapper(); $this->message = 'Message'; $this->messageTemplate = 'Message template'; @@ -76,7 +79,7 @@ protected function getForm($name = 'name', $propertyPath = null, $dataClass = nu $config->setInheritData($inheritData); $config->setPropertyPath($propertyPath); $config->setCompound(true); - $config->setDataMapper($this->getDataMapper()); + $config->setDataMapper(new PropertyPathMapper()); if (!$synchronized) { $config->addViewTransformer(new CallbackTransformer( @@ -88,14 +91,6 @@ function () { throw new TransformationFailedException(); } return new Form($config); } - /** - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getDataMapper() - { - return $this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock(); - } - /** * @param $propertyPath * @@ -210,7 +205,7 @@ public function testAbortDotRuleMappingIfNotSynchronized() $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } - public function testAbortMappingIfNotSubmitted() + public function testMappingIfNotSubmitted() { $violation = $this->getConstraintViolation('children[address].data.street'); $parent = $this->getForm('parent'); @@ -230,10 +225,10 @@ public function testAbortMappingIfNotSubmitted() $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + $this->assertCount(1, $grandChild->getErrors(), $grandChild->getName().' should have one error'); } - public function testAbortDotRuleMappingIfNotSubmitted() + public function testDotRuleMappingIfNotSubmitted() { $violation = $this->getConstraintViolation('data.address'); $parent = $this->getForm('parent'); @@ -255,7 +250,7 @@ public function testAbortDotRuleMappingIfNotSubmitted() $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + $this->assertCount(1, $grandChild->getErrors(), $grandChild->getName().' should have one error'); } public function provideDefaultTests() diff --git a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php index 39758e781884a..006724014a2a1 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php @@ -26,7 +26,7 @@ public function __construct(array $array = null) public function offsetExists($offset) { - return array_key_exists($offset, $this->array); + return \array_key_exists($offset, $this->array); } public function offsetGet($offset) diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt index 391c3e694d974..1824c46a7e5f8 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt @@ -15,10 +15,9 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain ---------------- --------------------%s Allowed values - %s ---------------- --------------------%s - Normalizer Closure%s{%w - parameters: 2 %s + Normalizer Closure%s{%A file: "%s%eExtension%eCore%eType%eChoiceType.php"%w - line: "%s to %s" %s + line: %s } %s ---------------- --------------------%s diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt index 846d6f384684c..780a4e5cb3589 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt @@ -8,15 +8,13 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data) Default Value: null %s %s Closure(s): [ %s - Closure%s{%w - parameters: 1 %s + Closure%s{%A file: "%s%eExtension%eCore%eType%eFormType.php"%w - line: "%s to %s" %s + line: %s }, %s - Closure%s{%w - parameters: 2 %s + Closure%s{%A file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w - line: "%s to %s" %s + line: %s } %s ] %s ---------------- ----------------------%s diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt index 8cc88a550ab70..ca203a285b2c2 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt @@ -16,10 +16,9 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo) "baz" %s ] %s ---------------- --------------------%s - Normalizer Closure%s{%w - parameters: 2 %s + Normalizer Closure%s{%A file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w - line: "%s to %s" %s + line: %s } %s ---------------- --------------------%s diff --git a/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php b/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php index e768b1d7cfac9..29391160968e2 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php @@ -25,7 +25,7 @@ public function __construct(array $mapping) public function transform($value) { - if (!array_key_exists($value, $this->mapping)) { + if (!\array_key_exists($value, $this->mapping)) { throw new TransformationFailedException(sprintf('No mapping for value "%s"', $value)); } diff --git a/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php b/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php index 077f477d4a23a..25a4716650755 100644 --- a/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php +++ b/src/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php @@ -179,6 +179,59 @@ public function testMethodOverrideHeaderIgnoredIfNotPost() $this->assertFalse($form->isSubmitted()); } + public function testFormIgnoresMethodFieldIfRequestMethodIsMatched() + { + $form = $this->createForm('foo', 'PUT', true); + $form->add($this->createForm('bar')); + + $this->setRequestData('PUT', [ + 'foo' => [ + '_method' => 'PUT', + 'bar' => 'baz', + ], + ]); + + $this->requestHandler->handleRequest($form, $this->request); + + $this->assertSame([], $form->getExtraData()); + } + + public function testFormDoesNotIgnoreMethodFieldIfRequestMethodIsNotMatched() + { + $form = $this->createForm('foo', 'PUT', true); + $form->add($this->createForm('bar')); + + $this->setRequestData('PUT', [ + 'foo' => [ + '_method' => 'DELETE', + 'bar' => 'baz', + ], + ]); + + $this->requestHandler->handleRequest($form, $this->request); + + $this->assertSame(['_method' => 'DELETE'], $form->getExtraData()); + } + + public function testMethodSubFormIsSubmitted() + { + $form = $this->createForm('foo', 'PUT', true); + $form->add($this->createForm('_method')); + $form->add($this->createForm('bar')); + + $this->setRequestData('PUT', [ + 'foo' => [ + '_method' => 'PUT', + 'bar' => 'baz', + ], + ]); + + $this->requestHandler->handleRequest($form, $this->request); + + $this->assertTrue($form->get('_method')->isSubmitted()); + $this->assertSame('PUT', $form->get('_method')->getData()); + } + protected function setRequestData($method, $data, $files = []) { if ('GET' === $method) { @@ -201,7 +254,7 @@ protected function getRequestHandler() return new NativeRequestHandler($this->serverParams); } - protected function getMockFile($suffix = '') + protected function getUploadedFile($suffix = '') { return [ 'name' => 'upload'.$suffix.'.txt', diff --git a/src/Symfony/Component/Form/Tests/VersionAwareTest.php b/src/Symfony/Component/Form/Tests/VersionAwareTest.php new file mode 100644 index 0000000000000..2b8489a6a27cf --- /dev/null +++ b/src/Symfony/Component/Form/Tests/VersionAwareTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +trait VersionAwareTest +{ + protected static $supportedFeatureSetVersion = 304; + + /** + * @param int $requiredFeatureSetVersion + */ + protected function requiresFeatureSet($requiredFeatureSetVersion) + { + if ($requiredFeatureSetVersion > static::$supportedFeatureSetVersion) { + $this->markTestSkipped(sprintf('Test requires features from symfony/form %.2f but only version %.2f is supported.', $requiredFeatureSetVersion / 100, static::$supportedFeatureSetVersion / 100)); + } + } +} diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index 937afe6b7acdd..9798173e649bf 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -112,7 +112,7 @@ public function get($key, $default = null, $first = true) $key = str_replace('_', '-', strtolower($key)); $headers = $this->all(); - if (!array_key_exists($key, $headers)) { + if (!\array_key_exists($key, $headers)) { if (null === $default) { return $first ? null : []; } @@ -168,7 +168,7 @@ public function set($key, $values, $replace = true) */ public function has($key) { - return array_key_exists(str_replace('_', '-', strtolower($key)), $this->all()); + return \array_key_exists(str_replace('_', '-', strtolower($key)), $this->all()); } /** @@ -245,7 +245,7 @@ public function addCacheControlDirective($key, $value = true) */ public function hasCacheControlDirective($key) { - return array_key_exists($key, $this->cacheControl); + return \array_key_exists($key, $this->cacheControl); } /** @@ -257,7 +257,7 @@ public function hasCacheControlDirective($key) */ public function getCacheControlDirective($key) { - return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; + return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; } /** diff --git a/src/Symfony/Component/HttpFoundation/ParameterBag.php b/src/Symfony/Component/HttpFoundation/ParameterBag.php index 3c6ba46a6a08e..f05e4a2154ecb 100644 --- a/src/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/src/Symfony/Component/HttpFoundation/ParameterBag.php @@ -81,7 +81,7 @@ public function add(array $parameters = []) */ public function get($key, $default = null) { - return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; + return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; } /** @@ -104,7 +104,7 @@ public function set($key, $value) */ public function has($key) { - return array_key_exists($key, $this->parameters); + return \array_key_exists($key, $this->parameters); } /** diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php index 970d82b5a29a7..5e1dfe58507fb 100644 --- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -42,7 +42,7 @@ public function __construct($url, $status = 302, $headers = []) throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } - if (301 == $status && !array_key_exists('cache-control', $headers)) { + if (301 == $status && !\array_key_exists('cache-control', $headers)) { $this->headers->remove('cache-control'); } } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 8dc01b91ea714..f6ff0f509954d 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -303,10 +303,10 @@ public static function createFromGlobals() // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields. $server = $_SERVER; if ('cli-server' === \PHP_SAPI) { - if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) { + if (\array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) { $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH']; } - if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { + if (\array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']; } } @@ -691,7 +691,7 @@ public static function setTrustedHeaderName($key, $value) $key = self::HEADER_CLIENT_PROTO; } elseif ('client_port' === $key) { $key = self::HEADER_CLIENT_PORT; - } elseif (!array_key_exists($key, self::$trustedHeaders)) { + } elseif (!\array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); } @@ -722,7 +722,7 @@ public static function getTrustedHeaderName($key) @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead.', __METHOD__), E_USER_DEPRECATED); } - if (!array_key_exists($key, self::$trustedHeaders)) { + if (!\array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); } diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index dc721a9deefab..1dc8dc2c5f651 100644 --- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -160,7 +160,7 @@ public function remove($key) */ public function hasCacheControlDirective($key) { - return array_key_exists($key, $this->computedCacheControl); + return \array_key_exists($key, $this->computedCacheControl); } /** @@ -168,7 +168,7 @@ public function hasCacheControlDirective($key) */ public function getCacheControlDirective($key) { - return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; + return \array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; } public function setCookie(Cookie $cookie) diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php index b5666f8543e38..07118e891b5de 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php @@ -63,7 +63,7 @@ public function getStorageKey() */ public function has($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -71,7 +71,7 @@ public function has($name) */ public function get($name, $default = null) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -107,7 +107,7 @@ public function replace(array $attributes) public function remove($name) { $retval = null; - if (array_key_exists($name, $this->attributes)) { + if (\array_key_exists($name, $this->attributes)) { $retval = $this->attributes[$name]; unset($this->attributes[$name]); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php index 95e48253bfb0d..bbf2e39c81059 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php @@ -44,7 +44,7 @@ public function has($name) return false; } - return array_key_exists($name, $attributes); + return \array_key_exists($name, $attributes); } /** @@ -60,7 +60,7 @@ public function get($name, $default = null) return $default; } - return array_key_exists($name, $attributes) ? $attributes[$name] : $default; + return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; } /** @@ -81,7 +81,7 @@ public function remove($name) $retval = null; $attributes = &$this->resolveAttributePath($name); $name = $this->resolveKey($name); - if (null !== $attributes && array_key_exists($name, $attributes)) { + if (null !== $attributes && \array_key_exists($name, $attributes)) { $retval = $attributes[$name]; unset($attributes[$name]); } @@ -123,7 +123,7 @@ protected function &resolveAttributePath($name, $writeContext = false) unset($parts[\count($parts) - 1]); foreach ($parts as $part) { - if (null !== $array && !array_key_exists($part, $array)) { + if (null !== $array && !\array_key_exists($part, $array)) { if (!$writeContext) { $null = null; diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php index 12345c8238c78..451c4a5a1d089 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php @@ -53,7 +53,7 @@ public function initialize(array &$flashes) // The logic: messages from the last request will be stored in new, so we move them to previous // This request we will show what is in 'display'. What is placed into 'new' this time round will // be moved to display next time round. - $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; + $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; $this->flashes['new'] = []; } @@ -78,7 +78,7 @@ public function peek($type, array $default = []) */ public function peekAll() { - return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : []; + return \array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : []; } /** @@ -132,7 +132,7 @@ public function set($type, $messages) */ public function has($type) { - return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; + return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php index 19baabb943b6e..f5d984af081b2 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php @@ -123,7 +123,7 @@ public function setAll(array $messages) */ public function has($type) { - return array_key_exists($type, $this->flashes) && $this->flashes[$type]; + return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; } /** diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 758e9043da2a3..e657f6143075f 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -131,7 +131,7 @@ protected function doGetArguments(Request $request, $controller, array $paramete $attributes = $request->attributes->all(); $arguments = []; foreach ($parameters as $param) { - if (array_key_exists($param->name, $attributes)) { + if (\array_key_exists($param->name, $attributes)) { if ($this->supportsVariadic && $param->isVariadic() && \is_array($attributes[$param->name])) { $arguments = array_merge($arguments, array_values($attributes[$param->name])); } else { diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 4a257ff5f8ee6..4346e0ec0f8e1 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -40,9 +40,6 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable */ private $cloner; - /** - * @internal - */ public function serialize() { $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); @@ -51,9 +48,6 @@ public function serialize() return $isCalledFromOverridingMethod ? $this->data : serialize($this->data); } - /** - * @internal - */ public function unserialize($data) { $this->data = \is_array($data) ? $data : unserialize($data); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index e25e4fb37d719..4266b22fec9b9 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -176,9 +176,6 @@ public function reset() $this->clonesIndex = 0; } - /** - * @internal - */ public function serialize() { if ($this->clonesCount !== $this->clonesIndex) { @@ -198,9 +195,6 @@ public function serialize() return $ser; } - /** - * @internal - */ public function unserialize($data) { $this->data = unserialize($data); diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php index 67db029af173f..e7e36d188bdea 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php @@ -56,13 +56,12 @@ public function onKernelException(GetResponseForExceptionEvent $event) } catch (\Exception $e) { $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', \get_class($e), $e->getMessage(), $e->getFile(), $e->getLine())); - $wrapper = $e; - - while ($prev = $wrapper->getPrevious()) { + $prev = $e; + do { if ($exception === $wrapper = $prev) { throw $e; } - } + } while ($prev = $wrapper->getPrevious()); $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); $prev->setAccessible(true); diff --git a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php index 73defb9d3ef7e..ce88bd45dea26 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php @@ -80,7 +80,7 @@ public function render($uri, Request $request, array $options = []) return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging - // the response that comes back is simply ignored + // the response that comes back is ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 168e9564b0c99..862bac557dd77 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -5,10 +5,6 @@ * * (c) Fabien Potencier * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -28,30 +24,69 @@ */ class ResponseCacheStrategy implements ResponseCacheStrategyInterface { - private $cacheable = true; + /** + * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. + */ + private static $overrideDirectives = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; + + /** + * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. + */ + private static $inheritDirectives = ['public', 'immutable']; + private $embeddedResponses = 0; - private $ttls = []; - private $maxAges = []; private $isNotCacheableResponseEmbedded = false; + private $age = 0; + private $flagDirectives = [ + 'no-cache' => null, + 'no-store' => null, + 'no-transform' => null, + 'must-revalidate' => null, + 'proxy-revalidate' => null, + 'public' => null, + 'private' => null, + 'immutable' => null, + ]; + private $ageDirectives = [ + 'max-age' => null, + 's-maxage' => null, + 'expires' => null, + ]; /** * {@inheritdoc} */ public function add(Response $response) { - if (!$response->isFresh() || !$response->isCacheable()) { - $this->cacheable = false; - } else { - $maxAge = $response->getMaxAge(); - $this->ttls[] = $response->getTtl(); - $this->maxAges[] = $maxAge; - - if (null === $maxAge) { - $this->isNotCacheableResponseEmbedded = true; + ++$this->embeddedResponses; + + foreach (self::$overrideDirectives as $directive) { + if ($response->headers->hasCacheControlDirective($directive)) { + $this->flagDirectives[$directive] = true; } } - ++$this->embeddedResponses; + foreach (self::$inheritDirectives as $directive) { + if (false !== $this->flagDirectives[$directive]) { + $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); + } + } + + $age = $response->getAge(); + $this->age = max($this->age, $age); + + if ($this->willMakeFinalResponseUncacheable($response)) { + $this->isNotCacheableResponseEmbedded = true; + + return; + } + + $this->storeRelativeAgeDirective('max-age', $response->headers->getCacheControlDirective('max-age'), $age); + $this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age); + + $expires = $response->getExpires(); + $expires = null !== $expires ? $expires->format('U') - $response->getDate()->format('U') : null; + $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0); } /** @@ -64,33 +99,124 @@ public function update(Response $response) return; } - // Remove validation related headers in order to avoid browsers using - // their own cache, because some of the response content comes from - // at least one embedded response (which likely has a different caching strategy). - if ($response->isValidateable()) { - $response->setEtag(null); - $response->setLastModified(null); + // Remove validation related headers of the master response, + // because some of the response content comes from at least + // one embedded response (which likely has a different caching strategy). + $response->setEtag(null); + $response->setLastModified(null); + + $this->add($response); + + $response->headers->set('Age', $this->age); + + if ($this->isNotCacheableResponseEmbedded) { + $response->setExpires($response->getDate()); + + if ($this->flagDirectives['no-store']) { + $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); + } else { + $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); + } + + return; + } + + $flags = array_filter($this->flagDirectives); + + if (isset($flags['must-revalidate'])) { + $flags['no-cache'] = true; } - if (!$response->isFresh() || !$response->isCacheable()) { - $this->cacheable = false; + $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); + + $maxAge = null; + $sMaxage = null; + + if (\is_numeric($this->ageDirectives['max-age'])) { + $maxAge = $this->ageDirectives['max-age'] + $this->age; + $response->headers->addCacheControlDirective('max-age', $maxAge); } - if (!$this->cacheable) { - $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); + if (\is_numeric($this->ageDirectives['s-maxage'])) { + $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; - return; + if ($maxAge !== $sMaxage) { + $response->headers->addCacheControlDirective('s-maxage', $sMaxage); + } + } + + if (\is_numeric($this->ageDirectives['expires'])) { + $date = clone $response->getDate(); + $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); + $response->setExpires($date); } + } - $this->ttls[] = $response->getTtl(); - $this->maxAges[] = $response->getMaxAge(); + /** + * RFC2616, Section 13.4. + * + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 + * + * @return bool + */ + private function willMakeFinalResponseUncacheable(Response $response) + { + // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 + // MAY be stored by a cache […] unless a cache-control directive prohibits caching. + if ($response->headers->hasCacheControlDirective('no-cache') + || $response->headers->getCacheControlDirective('no-store') + ) { + return true; + } - if ($this->isNotCacheableResponseEmbedded) { - $response->headers->removeCacheControlDirective('s-maxage'); - } elseif (null !== $maxAge = min($this->maxAges)) { - $response->setSharedMaxAge($maxAge); - $response->headers->set('Age', $maxAge - min($this->ttls)); + // Last-Modified and Etag headers cannot be merged, they render the response uncacheable + // by default (except if the response also has max-age etc.). + if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) + && null === $response->getLastModified() + && null === $response->getEtag() + ) { + return false; + } + + // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) + // MUST NOT be returned in a reply to a subsequent request unless there are + // cache-control directives or another header(s) that explicitly allow it. + $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; + foreach ($cacheControl as $key) { + if ($response->headers->hasCacheControlDirective($key)) { + return false; + } + } + + if ($response->headers->has('Expires')) { + return false; + } + + return true; + } + + /** + * Store lowest max-age/s-maxage/expires for the final response. + * + * The response might have been stored in cache a while ago. To keep things comparable, + * we have to subtract the age so that the value is normalized for an age of 0. + * + * If the value is lower than the currently stored value, we update the value, to keep a rolling + * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response. + * + * @param string $directive + * @param int|null $value + * @param int $age + */ + private function storeRelativeAgeDirective($directive, $value, $age) + { + if (null === $value) { + $this->ageDirectives[$directive] = false; + } + + if (false !== $this->ageDirectives[$directive]) { + $value = $value - $age; + $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; } - $response->setMaxAge(0); } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 54bcfd171946f..1a985a4c910b9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,11 +67,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.22'; - const VERSION_ID = 30422; + const VERSION = '3.4.23'; + const VERSION_ID = 30423; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 22; + const RELEASE_VERSION = 23; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index 6d67a177398c2..22cadf7129528 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -237,4 +237,233 @@ public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombi $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); $this->assertFalse($masterResponse->isValidateable()); } + + /** + * @dataProvider cacheControlMergingProvider + */ + public function testCacheControlMerging(array $expects, array $master, array $surrogates) + { + $cacheStrategy = new ResponseCacheStrategy(); + $buildResponse = function ($config) { + $response = new Response(); + + foreach ($config as $key => $value) { + switch ($key) { + case 'age': + $response->headers->set('Age', $value); + break; + + case 'expires': + $expires = clone $response->getDate(); + $expires->modify('+'.$value.' seconds'); + $response->setExpires($expires); + break; + + case 'max-age': + $response->setMaxAge($value); + break; + + case 's-maxage': + $response->setSharedMaxAge($value); + break; + + case 'private': + $response->setPrivate(); + break; + + case 'public': + $response->setPublic(); + break; + + default: + $response->headers->addCacheControlDirective($key, $value); + } + } + + return $response; + }; + + foreach ($surrogates as $config) { + $cacheStrategy->add($buildResponse($config)); + } + + $response = $buildResponse($master); + $cacheStrategy->update($response); + + foreach ($expects as $key => $value) { + if ('expires' === $key) { + $this->assertSame($value, $response->getExpires()->format('U') - $response->getDate()->format('U')); + } elseif ('age' === $key) { + $this->assertSame($value, $response->getAge()); + } elseif (true === $value) { + $this->assertTrue($response->headers->hasCacheControlDirective($key), sprintf('Cache-Control header must have "%s" flag', $key)); + } elseif (false === $value) { + $this->assertFalse( + $response->headers->hasCacheControlDirective($key), + sprintf('Cache-Control header must NOT have "%s" flag', $key) + ); + } else { + $this->assertSame($value, $response->headers->getCacheControlDirective($key), sprintf('Cache-Control flag "%s" should be "%s"', $key, $value)); + } + } + } + + public function cacheControlMergingProvider() + { + yield 'result is public if all responses are public' => [ + ['private' => false, 'public' => true], + ['public' => true], + [ + ['public' => true], + ], + ]; + + yield 'result is private by default' => [ + ['private' => true, 'public' => false], + ['public' => true], + [ + [], + ], + ]; + + yield 'combines public and private responses' => [ + ['must-revalidate' => false, 'private' => true, 'public' => false], + ['public' => true], + [ + ['private' => true], + ], + ]; + + yield 'inherits no-cache from surrogates' => [ + ['no-cache' => true, 'public' => false], + ['public' => true], + [ + ['no-cache' => true], + ], + ]; + + yield 'inherits no-store from surrogate' => [ + ['no-store' => true, 'public' => false], + ['public' => true], + [ + ['no-store' => true], + ], + ]; + + yield 'resolve to lowest possible max-age' => [ + ['public' => false, 'private' => true, 's-maxage' => false, 'max-age' => '60'], + ['public' => true, 'max-age' => 3600], + [ + ['private' => true, 'max-age' => 60], + ], + ]; + + yield 'resolves multiple max-age' => [ + ['public' => false, 'private' => true, 's-maxage' => false, 'max-age' => '60'], + ['private' => true, 'max-age' => 100], + [ + ['private' => true, 'max-age' => 3600], + ['public' => true, 'max-age' => 60, 's-maxage' => 60], + ['private' => true, 'max-age' => 60], + ], + ]; + + yield 'merge max-age and s-maxage' => [ + ['public' => true, 's-maxage' => '60', 'max-age' => null], + ['public' => true, 's-maxage' => 3600], + [ + ['public' => true, 'max-age' => 60], + ], + ]; + + yield 'result is private when combining private responses' => [ + ['no-cache' => false, 'must-revalidate' => false, 'private' => true], + ['s-maxage' => 60, 'private' => true], + [ + ['s-maxage' => 60, 'private' => true], + ], + ]; + + yield 'result can have s-maxage and max-age' => [ + ['public' => true, 'private' => false, 's-maxage' => '60', 'max-age' => '30'], + ['s-maxage' => 100, 'max-age' => 2000], + [ + ['s-maxage' => 1000, 'max-age' => 30], + ['s-maxage' => 500, 'max-age' => 500], + ['s-maxage' => 60, 'max-age' => 1000], + ], + ]; + + yield 'does not set headers without value' => [ + ['max-age' => null, 's-maxage' => null, 'public' => null], + ['private' => true], + [ + ['private' => true], + ], + ]; + + yield 'max-age 0 is sent to the client' => [ + ['private' => true, 'max-age' => '0'], + ['max-age' => 0, 'private' => true], + [ + ['max-age' => 60, 'private' => true], + ], + ]; + + yield 'max-age is relative to age' => [ + ['max-age' => '240', 'age' => 60], + ['max-age' => 180], + [ + ['max-age' => 600, 'age' => 60], + ], + ]; + + yield 'retains lowest age of all responses' => [ + ['max-age' => '160', 'age' => 60], + ['max-age' => 600, 'age' => 60], + [ + ['max-age' => 120, 'age' => 20], + ], + ]; + + yield 'max-age can be less than age, essentially expiring the response' => [ + ['age' => 120, 'max-age' => '90'], + ['max-age' => 90, 'age' => 120], + [ + ['max-age' => 120, 'age' => 60], + ], + ]; + + yield 'max-age is 0 regardless of age' => [ + ['max-age' => '0'], + ['max-age' => 60], + [ + ['max-age' => 0, 'age' => 60], + ], + ]; + + yield 'max-age is not negative' => [ + ['max-age' => '0'], + ['max-age' => 0], + [ + ['max-age' => 0, 'age' => 60], + ], + ]; + + yield 'calculates lowest Expires header' => [ + ['expires' => 60], + ['expires' => 60], + [ + ['expires' => 120], + ], + ]; + + yield 'calculates Expires header relative to age' => [ + ['expires' => 210, 'age' => 120], + ['expires' => 90], + [ + ['expires' => 600, 'age' => '120'], + ], + ]; + } } diff --git a/src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php b/src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php index 5e0c0a6a1ba6c..11b1b6b6d82d1 100644 --- a/src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php +++ b/src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php @@ -157,7 +157,7 @@ private function generateLocaleName($locale, $displayLocale) // the name sorting // $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region); - // Some languages are simply not translated + // Some languages are not translated // Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans) if (null === ($name = $this->languageDataProvider->getName($lang, $displayLocale))) { return; diff --git a/src/Symfony/Component/Intl/Data/Util/RecursiveArrayAccess.php b/src/Symfony/Component/Intl/Data/Util/RecursiveArrayAccess.php index c133932c9e6ff..09dd551dafa5e 100644 --- a/src/Symfony/Component/Intl/Data/Util/RecursiveArrayAccess.php +++ b/src/Symfony/Component/Intl/Data/Util/RecursiveArrayAccess.php @@ -25,7 +25,7 @@ public static function get($array, array $indices) foreach ($indices as $index) { // Use array_key_exists() for arrays, isset() otherwise if (\is_array($array)) { - if (array_key_exists($index, $array)) { + if (\array_key_exists($index, $array)) { $array = $array[$index]; continue; } diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index e0c6c236adc84..9ba821eac8009 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -460,7 +460,7 @@ public function getPattern() */ public function getSymbol($attr) { - return array_key_exists($this->style, self::$enSymbols) && array_key_exists($attr, self::$enSymbols[$this->style]) ? self::$enSymbols[$this->style][$attr] : false; + return \array_key_exists($this->style, self::$enSymbols) && \array_key_exists($attr, self::$enSymbols[$this->style]) ? self::$enSymbols[$this->style][$attr] : false; } /** @@ -474,7 +474,7 @@ public function getSymbol($attr) */ public function getTextAttribute($attr) { - return array_key_exists($this->style, self::$enTextAttributes) && array_key_exists($attr, self::$enTextAttributes[$this->style]) ? self::$enTextAttributes[$this->style][$attr] : false; + return \array_key_exists($this->style, self::$enTextAttributes) && \array_key_exists($attr, self::$enTextAttributes[$this->style]) ? self::$enTextAttributes[$this->style][$attr] : false; } /** diff --git a/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php b/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php index 146c18bf28236..bacb70b0b04b3 100644 --- a/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php +++ b/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php @@ -32,7 +32,7 @@ public function __construct(OptionsResolver $optionsResolver) throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option)); } - if (!array_key_exists($option, $this->{$property})) { + if (!\array_key_exists($option, $this->{$property})) { throw new NoConfigurationException($message); } diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php index 82efa15e3e23e..8ed03c2af20a7 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php +++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php @@ -175,7 +175,7 @@ public function setDefault($option, $value) // to resolve options with lazy closures, normalizers or validation // rules, none of which can exist for undefined options // If the option was resolved before, update the resolved value - if (!isset($this->defined[$option]) || array_key_exists($option, $this->resolved)) { + if (!isset($this->defined[$option]) || \array_key_exists($option, $this->resolved)) { $this->resolved[$option] = $value; } @@ -215,7 +215,7 @@ public function setDefaults(array $defaults) */ public function hasDefault($option) { - return array_key_exists($option, $this->defaults); + return \array_key_exists($option, $this->defaults); } /** @@ -280,7 +280,7 @@ public function getRequiredOptions() */ public function isMissing($option) { - return isset($this->required[$option]) && !array_key_exists($option, $this->defaults); + return isset($this->required[$option]) && !\array_key_exists($option, $this->defaults); } /** @@ -694,12 +694,12 @@ public function offsetGet($option) } // Shortcut for resolved options - if (array_key_exists($option, $this->resolved)) { + if (\array_key_exists($option, $this->resolved)) { return $this->resolved[$option]; } // Check whether the option is set at all - if (!array_key_exists($option, $this->defaults)) { + if (!\array_key_exists($option, $this->defaults)) { if (!isset($this->defined[$option])) { throw new NoSuchOptionException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $option, implode('", "', array_keys($this->defined)))); } @@ -908,7 +908,7 @@ public function offsetExists($option) throw new AccessException('Array access is only supported within closures of lazy options and normalizers.'); } - return array_key_exists($option, $this->defaults); + return \array_key_exists($option, $this->defaults); } /** diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index ac2ade04c8d82..83b0f1ce13269 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -260,7 +260,7 @@ private static function throwInvalidArgumentException($message, $trace, $i) return; } - if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file'] && array_key_exists(0, $trace[$i]['args'])) { + if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file'] && \array_key_exists(0, $trace[$i]['args'])) { $pos = strpos($message, $delim = 'must be of the type ') ?: (strpos($message, $delim = 'must be an instance of ') ?: strpos($message, $delim = 'must implement interface ')); $pos += \strlen($delim); $type = $trace[$i]['args'][0]; @@ -362,7 +362,7 @@ private function readPropertiesUntil($zval, PropertyPathInterface $propertyPath, if ($isIndex) { // Create missing nested arrays on demand if (($zval[self::VALUE] instanceof \ArrayAccess && !$zval[self::VALUE]->offsetExists($property)) || - (\is_array($zval[self::VALUE]) && !isset($zval[self::VALUE][$property]) && !array_key_exists($property, $zval[self::VALUE])) + (\is_array($zval[self::VALUE]) && !isset($zval[self::VALUE][$property]) && !\array_key_exists($property, $zval[self::VALUE])) ) { if (!$ignoreInvalidIndices) { if (!\is_array($zval[self::VALUE])) { diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php index 4852e8d58ff98..4b18e725ae9e4 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php @@ -26,7 +26,7 @@ public function __construct(array $array = null) public function offsetExists($offset) { - return array_key_exists($offset, $this->array); + return \array_key_exists($offset, $this->array); } public function offsetGet($offset) diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php index 9803a11f848fc..b075286f4a70e 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php @@ -26,7 +26,7 @@ public function __construct(array $array = null) public function offsetExists($offset) { - return array_key_exists($offset, $this->array); + return \array_key_exists($offset, $this->array); } public function offsetGet($offset) diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php index 702de4505ecc3..6f348095e8d68 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php @@ -100,7 +100,7 @@ private function extract($method, array $arguments) // Calling rawurlencode escapes special characters not allowed in PSR-6's keys $key = rawurlencode($method.'.'.$serializedArguments); - if (array_key_exists($key, $this->arrayCache)) { + if (\array_key_exists($key, $this->arrayCache)) { return $this->arrayCache[$key]; } diff --git a/src/Symfony/Component/Routing/Generator/UrlGenerator.php b/src/Symfony/Component/Routing/Generator/UrlGenerator.php index 4409796ed669e..b87f4bb5c45f7 100644 --- a/src/Symfony/Component/Routing/Generator/UrlGenerator.php +++ b/src/Symfony/Component/Routing/Generator/UrlGenerator.php @@ -139,9 +139,9 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; foreach ($tokens as $token) { if ('variable' === $token[0]) { - if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { - // check requirement - if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { + if (!$optional || !\array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); } @@ -195,7 +195,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { - if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php b/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php index ff7325b807fbb..84ee1892d3b7c 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php @@ -120,7 +120,7 @@ protected function setParent(self $parent) */ public function hasAttribute($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** diff --git a/src/Symfony/Component/Routing/RequestContext.php b/src/Symfony/Component/Routing/RequestContext.php index df33ec2d21bbd..8ebad8e2538db 100644 --- a/src/Symfony/Component/Routing/RequestContext.php +++ b/src/Symfony/Component/Routing/RequestContext.php @@ -316,7 +316,7 @@ public function getParameter($name) */ public function hasParameter($name) { - return array_key_exists($name, $this->parameters); + return \array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 5cebf094a9cde..759b6f3b6e66e 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -314,7 +314,7 @@ public function getOption($name) */ public function hasOption($name) { - return array_key_exists($name, $this->options); + return \array_key_exists($name, $this->options); } /** @@ -383,7 +383,7 @@ public function getDefault($name) */ public function hasDefault($name) { - return array_key_exists($name, $this->defaults); + return \array_key_exists($name, $this->defaults); } /** @@ -468,7 +468,7 @@ public function getRequirement($key) */ public function hasRequirement($key) { - return array_key_exists($key, $this->requirements); + return \array_key_exists($key, $this->requirements); } /** diff --git a/src/Symfony/Component/Routing/Router.php b/src/Symfony/Component/Routing/Router.php index 5fa85a538acc9..27c32e14ae8c6 100644 --- a/src/Symfony/Component/Routing/Router.php +++ b/src/Symfony/Component/Routing/Router.php @@ -142,7 +142,7 @@ public function setOptions(array $options) // check option names and live merge, if errors are encountered Exception will be thrown $invalid = []; foreach ($options as $key => $value) { - if (array_key_exists($key, $this->options)) { + if (\array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { $invalid[] = $key; @@ -164,7 +164,7 @@ public function setOptions(array $options) */ public function setOption($key, $value) { - if (!array_key_exists($key, $this->options)) { + if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } @@ -182,7 +182,7 @@ public function setOption($key, $value) */ public function getOption($key) { - if (!array_key_exists($key, $this->options)) { + if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } diff --git a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php index d92161c05c336..7f64a1f378326 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php @@ -703,6 +703,23 @@ public function testFragmentsCanBeDefinedAsDefaults() $this->assertEquals('/app.php/testing#fragment', $url); } + /** + * @dataProvider provideLookAroundRequirementsInPath + */ + public function testLookRoundRequirementsInPath($expected, $path, $requirement) + { + $routes = $this->getRoutes('test', new Route($path, [], ['foo' => $requirement, 'baz' => '.+?'])); + $this->assertSame($expected, $this->getGenerator($routes)->generate('test', ['foo' => 'a/b', 'baz' => 'c/d/e'])); + } + + public function provideLookAroundRequirementsInPath() + { + yield ['/app.php/a/b/b%28ar/c/d/e', '/{foo}/b(ar/{baz}', '.+(?=/b\\(ar/)']; + yield ['/app.php/a/b/bar/c/d/e', '/{foo}/bar/{baz}', '.+(?!$)']; + yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<=/bar/).+']; + yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -193,7 +193,7 @@ public function hasAttribute($name) */ public function getAttribute($name) { - if (!array_key_exists($name, $this->attributes)) { + if (!\array_key_exists($name, $this->attributes)) { throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name)); } diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index 39cca72b7b9bc..82e7cd459f2f0 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -43,7 +43,7 @@ class AccessDecisionManager implements AccessDecisionManagerInterface public function __construct($voters = [], $strategy = self::STRATEGY_AFFIRMATIVE, $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true) { $strategyMethod = 'decide'.ucfirst($strategy); - if (!\is_callable([$this, $strategyMethod])) { + if ('' === $strategy || !\is_callable([$this, $strategyMethod])) { throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy)); } diff --git a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php index 75ccb4d778675..f79eed1961fd5 100644 --- a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php +++ b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php @@ -33,7 +33,7 @@ public function getEncoder($user) $encoderKey = null; if ($user instanceof EncoderAwareInterface && (null !== $encoderName = $user->getEncoderName())) { - if (!array_key_exists($encoderName, $this->encoders)) { + if (!\array_key_exists($encoderName, $this->encoders)) { throw new \RuntimeException(sprintf('The encoder "%s" was not configured.', $encoderName)); } diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index de14c9b5e9daa..5d38065ff63bf 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/security-core": "~2.8|~3.0|~4.0", + "symfony/security-core": "~3.4.22|^4.2.3", "symfony/security-http": "^3.3.13|~4.0" }, "require-dev": { diff --git a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php index 63d73d235aa10..99c8fcab4e645 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php @@ -107,7 +107,7 @@ protected function attemptAuthentication(Request $request) $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); } - if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) { + if (!\is_string($username) && (!\is_object($username) || !\method_exists($username, '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username))); } diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 79193ece79b04..f80d2ec2caf47 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -83,6 +83,10 @@ public function handle(GetResponseEvent $event) return; } + if (null === $this->tokenStorage->getToken()) { + throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); + } + if (self::EXIT_VALUE === $username) { $this->tokenStorage->setToken($this->attemptExitUser($request)); } else { @@ -164,7 +168,7 @@ private function attemptSwitchUser(Request $request, $username) */ private function attemptExitUser(Request $request) { - if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) { + if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index aea883a04c78d..2f54156732948 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -85,7 +85,7 @@ protected function attemptAuthentication(Request $request) $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); } - if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) { + if (!\is_string($username) && (!\is_object($username) || !\method_exists($username, '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username))); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index d29665d55eb74..709bc4c862f9e 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -267,6 +267,17 @@ public function testSwitchUserWithReplacedToken() $this->assertSame($replacedToken, $this->tokenStorage->getToken()); } + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + */ + public function testSwitchtUserThrowsAuthenticationExceptionIfNoCurrentToken() + { + $this->tokenStorage->setToken(null); + $this->request->query->set('_switch_user', 'username'); + $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + public function testSwitchUserStateless() { $token = new UsernamePasswordToken('username', '', 'key', ['ROLE_FOO']); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 198ee6566dfdd..f1536db6d25a6 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -81,7 +81,7 @@ public function testHandleWhenUsernameLength($username, $ok) * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * @expectedExceptionMessage The key "_username" must be a string, "array" given. */ - public function testHandleNonStringUsername($postOnly) + public function testHandleNonStringUsernameWithArray($postOnly) { $request = Request::create('/login_check', 'POST', ['_username' => []]); $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); @@ -99,6 +99,79 @@ public function testHandleNonStringUsername($postOnly) $listener->handle($event); } + /** + * @dataProvider postOnlyDataProvider + * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @expectedExceptionMessage The key "_username" must be a string, "integer" given. + */ + public function testHandleNonStringUsernameWithInt($postOnly) + { + $request = Request::create('/login_check', 'POST', ['_username' => 42]); + $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); + $listener = new UsernamePasswordFormAuthenticationListener( + new TokenStorage(), + $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), + new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE), + $httpUtils = new HttpUtils(), + 'foo', + new DefaultAuthenticationSuccessHandler($httpUtils), + new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), + ['require_previous_session' => false, 'post_only' => $postOnly] + ); + $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + $listener->handle($event); + } + + /** + * @dataProvider postOnlyDataProvider + * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @expectedExceptionMessage The key "_username" must be a string, "object" given. + */ + public function testHandleNonStringUsernameWithObject($postOnly) + { + $request = Request::create('/login_check', 'POST', ['_username' => new \stdClass()]); + $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); + $listener = new UsernamePasswordFormAuthenticationListener( + new TokenStorage(), + $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), + new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE), + $httpUtils = new HttpUtils(), + 'foo', + new DefaultAuthenticationSuccessHandler($httpUtils), + new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), + ['require_previous_session' => false, 'post_only' => $postOnly] + ); + $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + $listener->handle($event); + } + + /** + * @dataProvider postOnlyDataProvider + */ + public function testHandleNonStringUsernameWith__toString($postOnly) + { + $usernameClass = $this->getMockBuilder(DummyUserClass::class)->getMock(); + $usernameClass + ->expects($this->atLeastOnce()) + ->method('__toString') + ->will($this->returnValue('someUsername')); + + $request = Request::create('/login_check', 'POST', ['_username' => $usernameClass]); + $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); + $listener = new UsernamePasswordFormAuthenticationListener( + new TokenStorage(), + $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), + new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE), + $httpUtils = new HttpUtils(), + 'foo', + new DefaultAuthenticationSuccessHandler($httpUtils), + new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), + ['require_previous_session' => false, 'post_only' => $postOnly] + ); + $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + $listener->handle($event); + } + public function postOnlyDataProvider() { return [ @@ -115,3 +188,11 @@ public function getUsernameForLength() ]; } } + +class DummyUserClass +{ + public function __toString() + { + return ''; + } +} diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index dd43846820cbc..3f181e4e99a55 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -343,14 +343,14 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref $allowed = false === $allowedAttributes || \in_array($paramName, $allowedAttributes); $ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context); if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) { - if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { + if ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) { if (!\is_array($data[$paramName])) { throw new RuntimeException(sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name)); } $params = array_merge($params, $data[$paramName]); } - } elseif ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { + } elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) { $parameterData = $data[$key]; if (null === $parameterData && $constructorParameter->allowsNull()) { $params[] = null; diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index a4b628ef906cd..a36549c3b225c 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -144,7 +144,7 @@ private function formatDateTimeErrors(array $errors) private function getTimezone(array $context) { - $dateTimeZone = array_key_exists(self::TIMEZONE_KEY, $context) ? $context[self::TIMEZONE_KEY] : $this->timezone; + $dateTimeZone = \array_key_exists(self::TIMEZONE_KEY, $context) ? $context[self::TIMEZONE_KEY] : $this->timezone; if (null === $dateTimeZone) { return null; diff --git a/src/Symfony/Component/Templating/TemplateReference.php b/src/Symfony/Component/Templating/TemplateReference.php index 88f71f95b07dd..195616e5d89c0 100644 --- a/src/Symfony/Component/Templating/TemplateReference.php +++ b/src/Symfony/Component/Templating/TemplateReference.php @@ -41,7 +41,7 @@ public function __toString() */ public function set($name, $value) { - if (array_key_exists($name, $this->parameters)) { + if (\array_key_exists($name, $this->parameters)) { $this->parameters[$name] = $value; } else { throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name)); @@ -55,7 +55,7 @@ public function set($name, $value) */ public function get($name) { - if (array_key_exists($name, $this->parameters)) { + if (\array_key_exists($name, $this->parameters)) { return $this->parameters[$name]; } diff --git a/src/Symfony/Component/Translation/Dumper/FileDumper.php b/src/Symfony/Component/Translation/Dumper/FileDumper.php index 20d9e55212524..102f9285842f8 100644 --- a/src/Symfony/Component/Translation/Dumper/FileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/FileDumper.php @@ -65,7 +65,7 @@ public function setBackup($backup) */ public function dump(MessageCatalogue $messages, $options = []) { - if (!array_key_exists('path', $options)) { + if (!\array_key_exists('path', $options)) { throw new InvalidArgumentException('The file dumper needs a path option.'); } diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index a26d94987e888..cd867b0967908 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -27,11 +27,11 @@ class XliffFileDumper extends FileDumper public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) { $xliffVersion = '1.2'; - if (array_key_exists('xliff_version', $options)) { + if (\array_key_exists('xliff_version', $options)) { $xliffVersion = $options['xliff_version']; } - if (array_key_exists('default_locale', $options)) { + if (\array_key_exists('default_locale', $options)) { $defaultLocale = $options['default_locale']; } else { $defaultLocale = \Locale::getDefault(); @@ -58,7 +58,7 @@ protected function getExtension() private function dumpXliff1($defaultLocale, MessageCatalogue $messages, $domain, array $options = []) { $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony']; - if (array_key_exists('tool_info', $options)) { + if (\array_key_exists('tool_info', $options)) { $toolInfo = array_merge($toolInfo, $options['tool_info']); } @@ -195,6 +195,6 @@ private function dumpXliff2($defaultLocale, MessageCatalogue $messages, $domain, */ private function hasMetadataArrayInfo($key, $metadata = null) { - return null !== $metadata && array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || \is_array($metadata[$key])); + return null !== $metadata && \array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || \is_array($metadata[$key])); } } diff --git a/src/Symfony/Component/Translation/Resources/bin/translation-status.php b/src/Symfony/Component/Translation/Resources/bin/translation-status.php new file mode 100644 index 0000000000000..acc8b4e227222 --- /dev/null +++ b/src/Symfony/Component/Translation/Resources/bin/translation-status.php @@ -0,0 +1,195 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$usageInstructions = << false, + // NULL = analyze all locales + 'locale_to_analyze' => null, + // the reference files all the other translations are compared to + 'original_files' => [ + 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf', + 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf', + 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf', + ], +]; + +$argc = $_SERVER['argc']; +$argv = $_SERVER['argv']; + +if ($argc > 3) { + echo str_replace('translation-status.php', $argv[0], $usageInstructions); + exit(1); +} + +foreach (array_slice($argv, 1) as $argumentOrOption) { + if (0 === strpos($argumentOrOption, '-')) { + $config['verbose_output'] = true; + } else { + $config['locale_to_analyze'] = $argumentOrOption; + } +} + +foreach ($config['original_files'] as $originalFilePath) { + if (!file_exists($originalFilePath)) { + echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', PHP_EOL, $originalFilePath); + exit(1); + } +} + +$totalMissingTranslations = 0; + +foreach ($config['original_files'] as $originalFilePath) { + $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']); + $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths); + + $totalMissingTranslations += array_sum(array_map(function ($translation) { + return \count($translation['missingKeys']); + }, array_values($translationStatus))); + + printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']); +} + +exit($totalMissingTranslations > 0 ? 1 : 0); + +function findTranslationFiles($originalFilePath, $localeToAnalyze) +{ + $translations = []; + + $translationsDir = dirname($originalFilePath); + $originalFileName = basename($originalFilePath); + $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName); + + $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern); + foreach ($translationFiles as $filePath) { + $locale = extractLocaleFromFilePath($filePath); + + if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) { + continue; + } + + $translations[$locale] = $filePath; + } + + return $translations; +} + +function calculateTranslationStatus($originalFilePath, $translationFilePaths) +{ + $translationStatus = []; + $allTranslationKeys = extractTranslationKeys($originalFilePath); + + foreach ($translationFilePaths as $locale => $translationPath) { + $translatedKeys = extractTranslationKeys($translationPath); + $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys); + + $translationStatus[$locale] = [ + 'total' => \count($allTranslationKeys), + 'translated' => \count($translatedKeys), + 'missingKeys' => $missingKeys, + ]; + } + + return $translationStatus; +} + +function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput) +{ + printTitle($originalFilePath); + printTable($translationStatus, $verboseOutput); + echo PHP_EOL.PHP_EOL; +} + +function extractLocaleFromFilePath($filePath) +{ + $parts = explode('.', $filePath); + + return $parts[count($parts) - 2]; +} + +function extractTranslationKeys($filePath) +{ + $translationKeys = []; + $contents = new \SimpleXMLElement(file_get_contents($filePath)); + + foreach ($contents->file->body->{'trans-unit'} as $translationKey) { + $translationId = (string) $translationKey['id']; + $translationKey = (string) $translationKey->source; + + $translationKeys[$translationId] = $translationKey; + } + + return $translationKeys; +} + +function printTitle($title) +{ + echo $title.PHP_EOL; + echo str_repeat('=', strlen($title)).PHP_EOL.PHP_EOL; +} + +function printTable($translations, $verboseOutput) +{ + $longestLocaleNameLength = max(array_map('strlen', array_keys($translations))); + + foreach ($translations as $locale => $translation) { + $isTranslationCompleted = $translation['translated'] === $translation['total']; + if ($isTranslationCompleted) { + textColorGreen(); + } + + echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).PHP_EOL; + + textColorNormal(); + + if (true === $verboseOutput && \count($translation['missingKeys']) > 0) { + echo str_repeat('-', 80).PHP_EOL; + echo '| Missing Translations:'.PHP_EOL; + + foreach ($translation['missingKeys'] as $id => $content) { + echo sprintf('| (id=%s) %s', $id, $content).PHP_EOL; + } + + echo str_repeat('-', 80).PHP_EOL; + } + } +} + +function textColorGreen() +{ + echo "\033[32m"; +} + +function textColorNormal() +{ + echo "\033[0m"; +} diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index ae27ba21635ee..b1a5e0c1a2b7e 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -122,7 +122,7 @@ public function __construct($options = null) } if ($options && \is_array($options) && \is_string(key($options))) { foreach ($options as $option => $value) { - if (array_key_exists($option, $knownOptions)) { + if (\array_key_exists($option, $knownOptions)) { $this->$option = $value; unset($missingOptions[$option]); } else { @@ -136,7 +136,7 @@ public function __construct($options = null) throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint %s', \get_class($this))); } - if (array_key_exists($option, $knownOptions)) { + if (\array_key_exists($option, $knownOptions)) { $this->$option = $options; unset($missingOptions[$option]); } else { diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php index fec0080fe02e9..3c95c097e8e9a 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php @@ -13,7 +13,7 @@ use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -29,7 +29,7 @@ abstract class AbstractComparisonValidator extends ConstraintValidator { private $propertyAccessor; - public function __construct(PropertyAccessor $propertyAccessor = null) + public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor; } diff --git a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php index e3a297329d1c8..3b67e40a5c3d4 100644 --- a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php @@ -50,7 +50,7 @@ public function validate($value, Constraint $constraint) foreach ($constraint->fields as $field => $fieldConstraint) { // bug fix issue #2779 - $existsInArray = \is_array($value) && array_key_exists($field, $value); + $existsInArray = \is_array($value) && \array_key_exists($field, $value); $existsInArrayAccess = $value instanceof \ArrayAccess && $value->offsetExists($field); if ($existsInArray || $existsInArrayAccess) { diff --git a/src/Symfony/Component/Validator/Constraints/IbanValidator.php b/src/Symfony/Component/Validator/Constraints/IbanValidator.php index fc14eea7dbe47..3dcedb47dc1ea 100644 --- a/src/Symfony/Component/Validator/Constraints/IbanValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IbanValidator.php @@ -181,7 +181,7 @@ public function validate($value, Constraint $constraint) } // ...have a format available - if (!array_key_exists($countryCode, self::$formats)) { + if (!\array_key_exists($countryCode, self::$formats)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/LessThanOrEqual.php b/src/Symfony/Component/Validator/Constraints/LessThanOrEqual.php index 74f7aeb8fadea..806ca4990fa02 100644 --- a/src/Symfony/Component/Validator/Constraints/LessThanOrEqual.php +++ b/src/Symfony/Component/Validator/Constraints/LessThanOrEqual.php @@ -20,7 +20,7 @@ */ class LessThanOrEqual extends AbstractComparison { - const TOO_HIGH_ERROR = '079d7420-2d13-460c-8756-de810eeb37d2'; + const TOO_HIGH_ERROR = '30fbb013-d015-4232-8b3b-8f3be97a7e14'; protected static $errorNames = [ self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', diff --git a/src/Symfony/Component/Validator/Constraints/Regex.php b/src/Symfony/Component/Validator/Constraints/Regex.php index a71e4de2590e6..dc9e5ea8859d9 100644 --- a/src/Symfony/Component/Validator/Constraints/Regex.php +++ b/src/Symfony/Component/Validator/Constraints/Regex.php @@ -79,7 +79,7 @@ public function getHtmlPattern() // Unescape the delimiter $pattern = str_replace('\\'.$delimiter, $delimiter, substr($this->pattern, 1, -1)); - // If the pattern is inverted, we can simply wrap it in + // If the pattern is inverted, we can wrap it in // ((?!pattern).)* if (!$this->match) { return '((?!'.$pattern.').)*'; diff --git a/src/Symfony/Component/Validator/Constraints/Traverse.php b/src/Symfony/Component/Validator/Constraints/Traverse.php index 4572c9b2193c4..78d115fdbbc74 100644 --- a/src/Symfony/Component/Validator/Constraints/Traverse.php +++ b/src/Symfony/Component/Validator/Constraints/Traverse.php @@ -25,7 +25,7 @@ class Traverse extends Constraint public function __construct($options = null) { - if (\is_array($options) && array_key_exists('groups', $options)) { + if (\is_array($options) && \array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__)); } diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index 210d55ea42cea..03b0ae6d8f575 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -371,7 +371,7 @@ public function mergeConstraints(self $source) */ public function hasPropertyMetadata($property) { - return array_key_exists($property, $this->members); + return \array_key_exists($property, $this->members); } /** diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php b/src/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php index e48e241ab8d5f..1b6f07ac8eed8 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php @@ -86,8 +86,8 @@ public function hasPropertyMetadata($property); /** * Returns all metadata instances for the given named property. * - * If your implementation does not support properties, simply throw an - * exception in this method (for example a BadMethodCallException). + * If your implementation does not support properties, throw an exception + * in this method (for example a BadMethodCallException). * * @param string $property The property name * diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf index 177bb0038f523..731e64aa7f2a4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf @@ -222,6 +222,118 @@ Unsupported card type or invalid card number. Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer. + + This is not a valid International Bank Account Number (IBAN). + Hierdie is nie 'n geldige Internationale Bank Rekening Nommer (IBAN) nie. + + + This value is not a valid ISBN-10. + Hierdie waarde is nie 'n geldige ISBN-10 nie. + + + This value is not a valid ISBN-13. + Hierdie waarde is nie 'n geldige ISBN-13 nie. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Hierdie waarde is nie 'n geldige ISBN-10 of ISBN-13 nie. + + + This value is not a valid ISSN. + Hierdie waarde is nie 'n geldige ISSN nie. + + + This value is not a valid currency. + Hierdie waarde is nie 'n geldige geldeenheid nie. + + + This value should be equal to {{ compared_value }}. + Hierdie waarde moet gelyk aan {{ compared_value }} wees. + + + This value should be greater than {{ compared_value }}. + Hierdie waarde moet meer as {{ compared_value }} wees. + + + This value should be greater than or equal to {{ compared_value }}. + Hierdie waarde moet meer of gelyk aan {{ compared_value }} wees. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Hierdie waarde moet identies aan {{ compared_value_type }} {{ compared_value }} wees. + + + This value should be less than {{ compared_value }}. + Hierdie waarde moet minder as {{ compared_value }} wees. + + + This value should be less than or equal to {{ compared_value }}. + Hierdie waarde moet minder of gelyk aan {{ compared_value }} wees. + + + This value should not be equal to {{ compared_value }}. + Hierdie waarde moet nie dieselfde as {{ compared_value }} wees nie. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Hierdie waarde moet nie identies as {{ compared_value_type }} {{ compared_value }} wees nie. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Die beeld aspek is te groot ({{ ratio }}). Die maksimum toegelate aspek is {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Die beeld aspek is te klein ({{ ratio }}). Die minimum toegelate aspek is {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Die beeld is vierkantig ({{ width }}x{{ height }}px). Vierkantige beelde word nie toegelaat nie. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Die beeld is landskap georiënteerd ({{ width }}x{{ height }}px). Landskap georiënteerde beelde word nie toegelaat nie. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Die beeld dis portret georiënteerd ({{ width }}x{{ height }}px). Portret georiënteerde beelde word nie toegelaat nie. + + + An empty file is not allowed. + 'n Leë lêer word nie toegelaat nie. + + + The host could not be resolved. + Die gasheer kon nie opgelos word nie. + + + This value does not match the expected {{ charset }} charset. + Die waarde stem nie ooreen met die verwagte {{ charset }} karakterstel nie. + + + This is not a valid Business Identifier Code (BIC). + Hierdie is nie 'n geldige Besigheids Identifikasie Kode (BIC) nie. + + + Error + Fout + + + This is not a valid UUID. + Hierdie is nie 'n geldige UUID nie. + + + This value should be a multiple of {{ compared_value }}. + Hierdie waarde moet 'n veelvoud van {{ compared_value }} wees. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Hierdie Besigheids Identifikasie Kode (BIK) is nie geassosieer met IBAN {{ iban }} nie. + + + This value should be valid JSON. + Hierdie waarde moet geldige JSON wees. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index 4950e0ccd1183..eacd8d777ddec 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -310,6 +310,26 @@ This value does not match the expected {{ charset }} charset. هذه القيمة غير متطابقة مع صيغة التحويل {{ charset }}. + + This is not a valid Business Identifier Code (BIC). + هذه القيمة ليست رمز معرّف نشاط تجاري صالح (BIC). + + + Error + خطأ + + + This is not a valid UUID. + هذا ليس UUID صالح. + + + This value should be a multiple of {{ compared_value }}. + هذه القيمة يجب أن تكون مضاعف ل {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + رمز المعرّف نشاط تجاري (BIC) هذا لا يرتبط مع IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf index dc6f95ff130fa..bd09da5d0ef0a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf @@ -318,6 +318,22 @@ Error Грешка + + This is not a valid UUID. + Това не е валиден UUID. + + + This value should be a multiple of {{ compared_value }}. + Тази стойност трябва да бъде кратно число на {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Този бизнес идентификационен код (BIC) не е свързана с IBAN {{ iban }}. + + + This value should be valid JSON. + Тази стойност трябва да е валидна JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf index 078a25d052d10..d6ae6e91bce2a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf @@ -301,11 +301,35 @@ An empty file is not allowed. No està permès un fixter buit. + + + The host could not be resolved. + No s'ha pogut resoldre l'amfitrió. + + + This value does not match the expected {{ charset }} charset. + Aquest valor no coincideix amb l'esperat {{ charset }} joc de caràcters. + + + This is not a valid Business Identifier Code (BIC). + Aquest no és un codi d'identificació bancari (BIC) vàlid. + + + Error + Error This is not a valid UUID. Aquest valor no és un UUID vàlid. + + This value should be a multiple of {{ compared_value }}. + Aquest valor ha de ser múltiple de {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Aquest Codi d'identificació bancari (BIC) no està associat amb l'IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf index da7cb9aab2986..752b6c2ae5143 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf @@ -222,6 +222,114 @@ Unsupported card type or invalid card number. Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys. + + This is not a valid International Bank Account Number (IBAN). + Nid yw hwn yn Rhif Cyfrif Banc Rhyngwladol (IBAN) dilys. + + + This value is not a valid ISBN-10. + Nid yw'r gwerth hwn yn ISBN-10 dilys. + + + This value is not a valid ISBN-13. + Nid yw'r gwerth hwn yn ISBN-13 dilys. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Nid yw'r gwerth hwn yn Rhif ISBN-10 dilys nac yn ISBN-13 dilys. + + + This value is not a valid ISSN. + Nid yw'r gwerth hwn yn ISSN dilys. + + + This value is not a valid currency. + Nid yw'r gwerth hwn yn arian dilys. + + + This value should be equal to {{ compared_value }}. + Dylai'r gwerth hwn fod yn gyfartal â {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Dylai'r gwerth hwn fod yn fwy na {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Dylai'r gwerth hwn fod yn fwy na neu'n hafal i {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Dylai'r gwerth hwn fod yn union yr un fath â {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Dylai'r gwerth hwn fod yn llai na {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Dylai'r gwerth hwn fod yn llai na neu'n hafal i {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Ni ddylai'r gwerth hwn fod yn hafal i {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Ni ddylai'r gwerth hwn fod yn union yr un fath â {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Mae'r gymhareb delwedd yn rhy fawr ({{ ratio }}). Y gymhareb uchaf a ganiateir yw {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Mae'r gymhareb delwedd yn rhy fach ({{ ratio }}). Y gymhareb isaf a ddisgwylir yw {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Mae'r ddelwedd yn sgwâr ({{ width }}x{{ height }}px). Ni chaniateir delweddau sgwâr. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Mae'r ddelwedd mewn fformat tirlun ({{ width }}x{{ height }}px). Ni chaniateir delweddau mewn fformat tirlun. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Mae'r ddelwedd mewn fformat portread ({{ width }}x{{ height }}px). Ni chaniateir delweddau mewn fformat portread. + + + An empty file is not allowed. + Ni chaniateir ffeil wag. + + + The host could not be resolved. + Ni fu modd datrys y gwesteiwr. + + + This value does not match the expected {{ charset }} charset. + Nid yw'r gwerth hwn yn cyfateb â'r {{ charset }} set nodau ddisgwyliedig. + + + This is not a valid Business Identifier Code (BIC). + Nid yw hwn yn God Adnabod Busnes (BIC) dilys. + + + Error + Gwall + + + This is not a valid UUID. + Nid yw hyn yn UUID dilys. + + + This value should be a multiple of {{ compared_value }}. + Dylai'r gwerth hwn fod yn luosrif o {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Nid yw'r Cod Adnabod Busnes (BIC) hwn yn gysylltiedig ag IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 3e44e1e284b8c..aab53e727b9e4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -322,6 +322,14 @@ This is not a valid UUID. Dies ist keine gültige UUID. + + This value should be a multiple of {{ compared_value }}. + Dieser Wert sollte ein Vielfaches von {{ compared_value }} sein. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Diese internationale Bankleitzahl (BIC) ist nicht mit der IBAN {{ iban }} assoziiert. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf index a3199bcc9d79e..3b9bbef66e5a4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf @@ -278,6 +278,58 @@ This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Η αναλογία πλάτους-ύψους της εικόνας είναι πολύ μεγάλη ({{ ratio }}). Μέγιστη επιτρεπτή αναλογία {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Η αναλογία πλάτους-ύψους της εικόνας είναι πολύ μικρή ({{ ratio }}). Ελάχιστη επιτρεπτή αναλογία {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Η εικόνα είναι τετράγωνη ({{ width }}x{{ height }}px). Δεν επιτρέπονται τετράγωνες εικόνες. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Η εικόνα έχει οριζόντιο προσανατολισμό ({{ width }}x{{ height }}px). Δεν επιτρέπονται εικόνες με οριζόντιο προσανατολισμό. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Η εικόνα έχει κάθετο προσανατολισμό ({{ width }}x{{ height }}px). Δεν επιτρέπονται εικόνες με κάθετο προσανατολισμό. + + + An empty file is not allowed. + Δεν επιτρέπεται κενό αρχείο. + + + The host could not be resolved. + Η διεύθυνση δεν μπόρεσε να επιλυθεί. + + + This value does not match the expected {{ charset }} charset. + Αυτή η τιμή δεν ταιριάζει στο αναμενόμενο {{ charset }} σύνολο χαρακτήρων. + + + This is not a valid Business Identifier Code (BIC). + Αυτός δεν έιναι ένας έγκυρος κωδικός BIC. + + + Error + Σφάλμα + + + This is not a valid UUID. + Αυτό δεν είναι ένα έγκυρο UUID. + + + This value should be a multiple of {{ compared_value }}. + Αυτή η τιμή θα έπρεπε να είναι πολλαπλάσιο του {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Αυτός ο κωδικός BIC δεν σχετίζεται με το IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index 4bb2760b418e3..465ad220d8790 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -326,6 +326,14 @@ This value should be a multiple of {{ compared_value }}. This value should be a multiple of {{ compared_value }}. + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + + + This value should be valid JSON. + This value should be valid JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf index 25d5b8a5d33a7..69ab34e8b29ce 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf @@ -322,6 +322,14 @@ This is not a valid UUID. Este valor no es un UUID válido. + + This value should be a multiple of {{ compared_value }}. + Este valor debería ser múltiplo de {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Este Código de Identificación Bancaria (BIC) no está asociado con el IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf index d311dedb5e62e..ee9529e3e3ba4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf @@ -278,6 +278,42 @@ This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar. + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Irudiaren proportzioa oso handia da ({{ ratio }}). Onartutako proportzio handienda {{ max_ratio }} da. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Irudiaren proportzioa oso txikia da ({{ ratio }}). Onartutako proportzio txikiena {{ min_ratio }} da. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Irudia karratua da ({{ width }}x{{ height }}px). Karratuak diren irudiak ez dira onartzen. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Irudia horizontalki bideratua dago ({{ width }}x{{ height }}px). Horizontalki bideratutako irudiak ez dira onartzen. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Irudia bertikalki bideratua dago ({{ width }}x{{ height }}px). Bertikalki bideratutako irudiak ez dira onartzen. + + + An empty file is not allowed. + Hutsik dagoen fitxategia ez da onartzen. + + + The host could not be resolved. + Host-a ezin da ebatzi. + + + This value does not match the expected {{ charset }} charset. + Balio honen karaktere kodea ez da esperotakoa {{ charset }}. + + + This is not a valid Business Identifier Code (BIC). + Ez da balizko Banku Identifikazioko Kodea (BIC). + Error Errore @@ -286,6 +322,14 @@ This is not a valid UUID. Balio hau ez da onartutako UUID bat. + + This value should be a multiple of {{ compared_value }}. + Balio honek {{ compared_value }}-ren multiploa izan beharko luke. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Banku Identifikazioko Kode hau ez dago lotuta {{ IBAN }} IBAN-rekin. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf index 98b4bd66f08e8..ff1aa7c0b1ec0 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf @@ -278,6 +278,58 @@ This value should not be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد. + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + ابعاد {{ ratio }} عکس بیش از حد بزرگ است.حداکثر ابعاد مجاز {{ max_ratio }} است. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + ابعاد {{ ratio }} عکس بیش از حد کوچک است.حداقل ابعاد مجاز {{ min_ratio }} است. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + این عکس مربع width }}x{{ height }}px}} می باشد.عکس مربع مجاز نمی باشد. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + این عکس افقی width }}x{{ height }}px}} می باشد.عکس افقی مجاز نمی باشد. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + این عکس عمودی width }}x{{ height }}px}} می باشد.عکس عمودی مجاز نمی باشد. + + + An empty file is not allowed. + فایل خالی مجاز نمی باشد. + + + The host could not be resolved. + هاست قابل حل نیست. + + + This value does not match the expected {{ charset }} charset. + این مقدار مورد نظر نمی باشد. مقدار مورد نظر {{ charset }} می باشد. + + + This is not a valid Business Identifier Code (BIC). + این مقدار یک BIC درست نیست. + + + Error + خطا + + + This is not a valid UUID. + این مقدار یک UUID درست نیست. + + + This value should be a multiple of {{ compared_value }}. + این مقدار باید چند برابر {{ compared_value }} باشد. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + این BIC با IBAN ارتباط ندارد. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 382acb975ce66..7b1799d53315c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -322,6 +322,18 @@ This is not a valid UUID. Ceci n'est pas un UUID valide. + + This value should be a multiple of {{ compared_value }}. + Cette valeur doit être un multiple de {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Ce code d'identification d'entreprise (BIC) n'est pas associé à l'IBAN {{ iban }}. + + + This value should be valid JSON. + Cette valeur doit être un JSON valide. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf index ecb7155cac892..71df1d240bde7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf @@ -314,6 +314,22 @@ This is not a valid Business Identifier Code (BIC). Non é un Código de Identificación Bancaria (BIC) válido. + + Error + Erro + + + This is not a valid UUID. + Isto non é un UUID válido. + + + This value should be a multiple of {{ compared_value }}. + Este valor debería ser multiplo de {{ compared_value }}. + + + 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 }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf index 126ef90332e30..ab033a11c3b01 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf @@ -318,6 +318,22 @@ Error Greška + + This is not a valid UUID. + Ovo nije validan UUID. + + + This value should be a multiple of {{ compared_value }}. + Ova vrijednost treba biti višekratnik od {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Poslovni identifikacijski broj (BIC) nije povezan sa IBAN brojem {{ iban }}. + + + This value should be valid JSON. + Ova vrijednost treba biti validan JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf index 1011d5481829b..30c3cc399d3ef 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf @@ -322,6 +322,14 @@ This is not a valid UUID. Érvénytelen egyedi azonosító (UUID). + + This value should be a multiple of {{ compared_value }}. + Ennek az értéknek oszthatónak kell lennie a következővel: {{ compared_value }} + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Ez a Bankazonosító kód (BIC) nem kapcsolódik az IBAN kódhoz ({{ iban }}). + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf index 535bdac08238c..bf4b85deefc35 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf @@ -318,6 +318,18 @@ Error Galat + + This is not a valid UUID. + Ini bukan UUID yang sah. + + + This value should be a multiple of {{ compared_value }}. + Nilai ini harus kelipatan dari {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Business Identifier Code (BIC) ini tidak terkait dengan IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf index f19544701d637..235d44d1bbee9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf @@ -322,6 +322,14 @@ This is not a valid UUID. Questo non è un UUID valido. + + This value should be a multiple of {{ compared_value }}. + Questo valore dovrebbe essere un multiplo di {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Questo codice identificativo bancario (BIC) non è associato all'IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf index bdbc9da09c88c..4c3579fb58478 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf @@ -322,6 +322,18 @@ This is not a valid UUID. Dëst ass keng gëlteg UUID. + + This value should be a multiple of {{ compared_value }}. + Dëse Wäert sollt e puer vun {{ compared_value }} sinn. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Dëse "Business Identifier Code" (BIC) ass net mat IBAN verbonnen {{ iban }}. + + + This value should be valid JSON. + Dëse Wäert sollt gëlteg JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf index 60641b5e68dbd..02eece5965d14 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf @@ -302,10 +302,38 @@ An empty file is not allowed. Failas negali būti tuščias. + + The host could not be resolved. + Serveris nepasiekiamas. + + + This value does not match the expected {{ charset }} charset. + Ši reikšmė neatitinka {{ charset }} koduotės. + + + This is not a valid Business Identifier Code (BIC). + Bendrovės Identifikavimo Kodas (BIC) nėra tinkamas. + Error Klaida + + This is not a valid UUID. + Ši reikšmė nėra tinkamas UUID. + + + This value should be a multiple of {{ compared_value }}. + Ši reikšmė turi būti skaičiaus {{ compared_value }} kartotinis. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Šis bendrovės identifikavimo kodas (BIC) nesusijęs su IBAN {{ iban }}. + + + This value should be valid JSON. + Ši reikšmė turi būti tinkamo JSON formato. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf index 2ad19cd283c18..4c0e192521d27 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf @@ -310,6 +310,30 @@ This value does not match the expected {{ charset }} charset. Šī vērtība neatbilst sagaidāmajai rakstzīmju kopai {{ charset }}. + + This is not a valid Business Identifier Code (BIC). + Šī vērtība nav derīgs Biznesa Identifikācijas Kods (BIC). + + + Error + Kļūda + + + This is not a valid UUID. + Šis nav derīgs UUID. + + + This value should be a multiple of {{ compared_value }}. + Šai vērtībai jābūt vairākas reizes atkārtotai {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Šis Biznesa Identifikācijas Kods (BIC) neatbilst {{ iban }} konta numuram (IBAN). + + + This value should be valid JSON. + Šai vērtībai jābūt derīgam JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf index 250576531cfe4..db534528d1d99 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf @@ -314,6 +314,26 @@ This is not a valid Business Identifier Code (BIC). Dette er ikke en gyldig BIC. + + Error + Feil + + + This is not a valid UUID. + Dette er ikke en gyldig UUID. + + + This value should be a multiple of {{ compared_value }}. + Verdien skal være flertall av {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Business Identifier Code (BIC) er ikke tilknyttet en IBAN {{ iban }}. + + + This value should be valid JSON. + Verdien er ikke gyldig JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf index bee0ab3b55a8f..52815e8e721f3 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf @@ -302,6 +302,10 @@ An empty file is not allowed. Lege bestanden zijn niet toegestaan. + + The host could not be resolved. + De hostnaam kon niet worden bepaald. + This value does not match the expected {{ charset }} charset. Deze waarde is niet in de verwachte tekencodering {{ charset }}. @@ -318,6 +322,14 @@ This is not a valid UUID. Dit is geen geldige UUID. + + This value should be a multiple of {{ compared_value }}. + Deze waarde zou een meervoud van {{ compared_value }} moeten zijn. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Deze bedrijfsidentificatiecode (BIC) is niet gekoppeld aan IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf index 250576531cfe4..db534528d1d99 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf @@ -314,6 +314,26 @@ This is not a valid Business Identifier Code (BIC). Dette er ikke en gyldig BIC. + + Error + Feil + + + This is not a valid UUID. + Dette er ikke en gyldig UUID. + + + This value should be a multiple of {{ compared_value }}. + Verdien skal være flertall av {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Business Identifier Code (BIC) er ikke tilknyttet en IBAN {{ iban }}. + + + This value should be valid JSON. + Verdien er ikke gyldig JSON. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf index e7ad1eca8de23..888e73b157007 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf @@ -326,6 +326,10 @@ This value should be a multiple of {{ compared_value }}. Ta wartość powinna być wielokrotnością {{ compared_value }}. + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Ten kod BIC (Business Identifier Code) nie jest powiązany z międzynarodowym numerem rachunku bankowego (IBAN) {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf index 0561c048f512c..e5cf660686358 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf @@ -302,10 +302,34 @@ An empty file is not allowed. Ficheiro vazio não é permitido. + + The host could not be resolved. + O host não pode ser resolvido. + + + This value does not match the expected {{ charset }} charset. + O valor não corresponde ao conjunto de caracteres {{ charset }} esperado. + + + This is not a valid Business Identifier Code (BIC). + O Código de Identificação de Empresa (BIC) não é válido. + Error Erro + + This is not a valid UUID. + Este valor não é um UUID válido. + + + This value should be a multiple of {{ compared_value }}. + Este valor deve ser um múltiplo de {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + O Código de Identificação de Empresa (BIC) não está associado ao IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf index b61706231887f..8616edf4b9096 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf @@ -314,6 +314,26 @@ This is not a valid Business Identifier Code (BIC). Este não é um Código Identificador Bancário (BIC) válido. + + Error + Erro + + + This is not a valid UUID. + Este não é um UUID válido. + + + This value should be a multiple of {{ compared_value }}. + Este valor deve ser múltiplo de {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Este Código Identificador Bancário (BIC) não está associado ao IBAN {{ iban }}. + + + This value should be valid JSON. + Este valor deve ser um JSON válido. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 11bfead5e505c..b77e04e8471c8 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -310,10 +310,26 @@ This value does not match the expected {{ charset }} charset. Значение не совпадает с ожидаемой {{ charset }} кодировкой. + + This is not a valid Business Identifier Code (BIC). + Значение не соответствует формату BIC. + Error Ошибка + + This is not a valid UUID. + Значение не соответствует формату UUID. + + + This value should be a multiple of {{ compared_value }}. + Значение должно быть кратно {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Данный BIC не связан с IBAN {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf index ffc8ccf2f9831..569ebca47f02e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf @@ -24,15 +24,15 @@ You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. - Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa. + Duhet të zgjedhni së paku {{ limit }} alternativë.|Duhet të zgjedhni së paku {{ limit }} alternativa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. - Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa. + Duhet të zgjedhni më së shumti {{ limit }} alternativë.|Duhet të zgjedhni më së shumti {{ limit }} alternativa. One or more of the given values is invalid. - Një apo më shumë nga vlerat e dhëna nuk janë të sakta. + Një apo më shumë nga vlerat e dhëna janë të pavlefshme. This field was not expected. @@ -40,7 +40,7 @@ This field is missing. - Kjo fushë është zhdukur. + Kjo fushë mungon. This value is not a valid date. @@ -52,7 +52,7 @@ This value is not a valid email address. - Kjo vlerë nuk është e-mail adresë e vlefshme. + Kjo vlerë nuk është adresë email-i e vlefshme. The file could not be found. @@ -64,11 +64,11 @@ The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. - File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}. + File është shumë i madh ({{ size }} {{ suffix }}). Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. - Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}. + Lloji mime i file-it është i pavlefshëm ({{ type }}). Llojet mime të lejuara janë {{ 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. - Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere. + Kjo vlerë është shumë e gjatë. Duhet të përmbaj {{ limit }} karakter ose më pak.|Kjo vlerë është shumë e gjatë. Duhet të përmbaj {{ limit }} karaktere ose më pak. This value should be {{ limit }} or more. @@ -84,7 +84,7 @@ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere. + Kjo vlerë është shumë e shkurtër. Duhet të përmbaj {{ limit }} karakter ose më shumë.|Kjo vlerë është shumë e shkurtër. Duhet të përmbaj {{ limit }} karaktere ose më shumë. This value should not be blank. @@ -136,7 +136,7 @@ This is not a valid IP address. - Kjo vlerë nuk është IP adresë e vlefshme. + Kjo adresë IP nuk është e vlefshme. This value is not a valid language. @@ -144,7 +144,7 @@ This value is not a valid locale. - Kjo vlerë nuk është përcaktim rajonal i vlefshëm. + Kjo vlerë nuk është nje locale i vlefshëm. This value is not a valid country. @@ -156,7 +156,7 @@ The size of the image could not be detected. - Madhësia e këtij imazhi nuk mund të zbulohet. + Madhësia e imazhit nuk mund të zbulohet. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. @@ -180,7 +180,7 @@ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere. + Kjo vlerë duhet të ketë saktësisht {{ limit }} karakter.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere. The file was only partially uploaded. @@ -200,27 +200,135 @@ A PHP extension caused the upload to fail. - Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files. + Një ekstension i PHP-së shkaktoi dështimin e ngarkimit. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. + Ky koleksion duhet të përmbajë {{ limit }} element ose më shumë.|Ky koleksion duhet të përmbajë {{ limit }} elemente ose më shumë. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. + Ky koleksion duhet të përmbajë {{ limit }} element ose më pak.|Ky koleksion duhet të përmbajë {{ limit }} elemente ose më pak. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. - Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente. + Ky koleksion duhet të përmbajë saktësisht {{ limit }} element.|Ky koleksion duhet të përmbajë saktësisht {{ limit }} elemente. Invalid card number. - Numër kartele i pavlefshëm. + Numër karte i pavlefshëm. Unsupported card type or invalid card number. - Lloj kartele i pambështetur ose numër kartele i pavlefshëm. + Lloj karte i papranuar ose numër karte i pavlefshëm. + + + This is not a valid International Bank Account Number (IBAN). + Ky nuk është një numër i vlefshëm ndërkombëtar i llogarisë bankare (IBAN). + + + This value is not a valid ISBN-10. + Kjo vlerë nuk është një ISBN-10 e vlefshme. + + + This value is not a valid ISBN-13. + Kjo vlerë nuk është një ISBN-13 e vlefshme. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Kjo vlerë nuk është as ISBN-10 e vlefshme as ISBN-13 e vlefshme. + + + This value is not a valid ISSN. + Kjo vlerë nuk është një ISSN e vlefshme. + + + This value is not a valid currency. + Kjo vlerë nuk është një monedhë e vlefshme. + + + This value should be equal to {{ compared_value }}. + Kjo vlerë duhet të jetë e barabartë me {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Kjo vlerë duhet të jetë më e madhe se {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Kjo vlerë duhet të jetë më e madhe ose e barabartë me {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Kjo vlerë duhet të jetë identike me {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Kjo vlerë duhet të jetë më vogël se {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Kjo vlerë duhet të jetë më e vogël ose e barabartë me {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Kjo vlerë nuk duhet të jetë e barabartë me {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Kjo vlerë nuk duhet të jetë identike me {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Raporti i imazhit është shumë i madh ({{ ratio }}). Raporti maksimal i lejuar është {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Raporti i imazhit është shumë i vogël ({{ ratio }}). Raporti minimal pritet të jetë {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Imazhi është katror ({{ width }}x{{ height }}px). Imazhet katrore nuk janë të lejuara. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Imazhi është i orientuar horizontalisht ({{ width }}x{{ height }}px). Imazhet e orientuara horizontalisht nuk lejohen. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Imazhi është i orientuar vertikalisht ({{ width }}x{{ height }}px). Imazhet orientuara vertikalisht nuk lejohen. + + + An empty file is not allowed. + Një file i zbrazët nuk lejohet. + + + The host could not be resolved. + Host-i nuk mund te zbulohej. + + + This value does not match the expected {{ charset }} charset. + Kjo vlerë nuk përputhet me kodifikimin e karaktereve {{ charset }} që pritej. + + + This is not a valid Business Identifier Code (BIC). + Ky nuk është një Kod Identifikues i Biznesit (BIC) i vleflshem. + + + Error + Gabim + + + This is not a valid UUID. + Ky nuk është një UUID i vlefshëm. + + + This value should be a multiple of {{ compared_value }}. + Kjo vlerë duhet të jetë një shumëfish i {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Ky Kod Identifikues i Biznesit (BIC) nuk është i lidhur me IBAN {{ iban }}. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf index 60c093aebf795..9ac1ad6bce294 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf @@ -4,39 +4,39 @@ This value should be false. - Vrednost treba da bude netačna. + Vrednost bi trebalo da bude netačna. This value should be true. - Vrednost treba da bude tačna. + Vrednost bi trebalo da bude tačna. This value should be of type {{ type }}. - Vrednost treba da bude tipa {{ type }}. + Vrednost bi trebalo da bude tipa {{ type }}. This value should be blank. - Vrednost treba da bude prazna. + Vrednost bi trebalo da bude prazna. The value you selected is not a valid choice. - Vrednost treba da bude jedna od ponuđenih. + Odabrana vrednost nije validan izbor. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. - Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti. + Morate odabrati bar {{ limit }} mogućnost.|Morate odabrati bar {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. - Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti. + Morate odabrati najviše {{ limit }} mogućnost.|Morate odabrati najviše {{ limit }} mogućnosti. One or more of the given values is invalid. - Jedna ili više vrednosti je nevalidna. + Jedna ili više vrednosti nisu validne. This field was not expected. - Ovo polje ne očekuje. + Ovo polje nije bilo očekivano. This field is missing. @@ -48,7 +48,7 @@ This value is not a valid datetime. - Vrednost nije validan datum-vreme. + Vrednost nije validno vreme. This value is not a valid email address. @@ -68,39 +68,39 @@ The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. - Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. + MIME tip datoteke nije validan ({{ type }}). Dozvoljeni MIME tipovi su {{ types }}. This value should be {{ limit }} or less. - Vrednost treba da bude {{ limit }} ili manje. + Vrednost bi trebalo da bude {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje. + Vrednost je predugačka. Trebalo bi da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Trebalo bi da ima {{ limit }} karaktera ili manje. This value should be {{ limit }} or more. - Vrednost treba da bude {{ limit }} ili više. + Vrednost bi trebalo da bude {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više. + Vrednost je prekratka. Trebalo bi da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Trebalo bi da ima {{ limit }} karaktera ili više. This value should not be blank. - Vrednost ne treba da bude prazna. + Vrednost ne bi trebalo da bude prazna. This value should not be null. - Vrednost ne treba da bude null. + Vrednost ne bi trebalo da bude prazna. This value should be null. - Vrednost treba da bude null. + Vrednost bi trebalo da bude prazna. This value is not valid. - Vrednost je nevalidna. + Vrednost nije validna. This value is not a valid time. @@ -112,7 +112,7 @@ The two values should be equal. - Obe vrednosti treba da budu jednake. + Obe vrednosti bi trebalo da budu jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. @@ -128,7 +128,7 @@ This value should be a valid number. - Vrednost treba da bude validan broj. + Vrednost bi trebalo da bude validan broj. This file is not a valid image. @@ -144,11 +144,11 @@ This value is not a valid locale. - Vrednost nije validan lokal. + Vrednost nije validna međunarodna oznaka jezika. This value is not a valid country. - Vrednost nije validna zemlja. + Vrednost nije validna država. This value is already used. @@ -160,27 +160,27 @@ The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px. + Širina slike je prevelika ({{ width }} piksela). Najveća dozvoljena širina je {{ max_width }} piksela. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. + Širina slike je premala ({{ width }} piksela). Najmanja dozvoljena širina je {{ min_width }} piksela. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px. + Visina slike je prevelika ({{ height }} piksela). Najveća dozvoljena visina je {{ max_height }} piksela. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. + Visina slike je premala ({{ height }} piksela). Najmanja dozvoljena visina je {{ min_height }} piksela. This value should be the user's current password. - Vrednost treba da bude trenutna korisnička lozinka. + Vrednost bi trebalo da bude trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera. + Vrednost bi trebalo da ima tačno {{ limit }} karakter.|Vrednost bi trebalo da ima tačno {{ limit }} karaktera. The file was only partially uploaded. @@ -204,23 +204,23 @@ This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata. + Ova kolekcija bi trebalo da sadrži {{ limit }} ili više elemenata.|Ova kolekcija bi trebalo da sadrži {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata. + Ova kolekcija bi trebalo da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija bi trebalo da sadrži {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. - Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata. + Ova kolekcija bi trebalo da sadrži tačno {{ limit }} element.|Ova kolekcija bi trebalo da sadrži tačno {{ limit }} elemenata. Invalid card number. - Nevalidan broj kartice. + Broj kartice nije validan. Unsupported card type or invalid card number. - Nevalidan broj kartice ili tip kartice nije podržan. + Tip kartije nije podržan ili broj kartice nije validan. This is not a valid International Bank Account Number (IBAN). @@ -248,35 +248,35 @@ This value should be equal to {{ compared_value }}. - Ova vrednost treba da bude {{ compared_value }}. + Ova vrednost bi trebalo da bude jednaka {{ compared_value }}. This value should be greater than {{ compared_value }}. - Ova vrednost treba da bude veća od {{ compared_value }}. + Ova vrednost bi trebalo da bude veća od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. - Ova vrednost treba da bude veća ili jednaka {{ compared_value }}. + Ova vrednost bi trebalo da bude veća ili jednaka {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. - Ova vrednost treba da bude identična sa {{ compared_value_type }} {{ compared_value }}. + Ova vrednost bi trebalo da bude identična sa {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. - Ova vrednost treba da bude manja od {{ compared_value }}. + Ova vrednost bi trebalo da bude manja od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. - Ova vrednost treba da bude manja ili jednaka {{ compared_value }}. + Ova vrednost bi trebalo da bude manja ili jednaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. - Ova vrednost ne treba da bude jednaka {{ compared_value }}. + Ova vrednost ne bi trebalo da bude jednaka {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. - Ova vrednost ne treba da bude identična sa {{ compared_value_type }} {{ compared_value }}. + Ova vrednost ne bi trebalo da bude identična sa {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. @@ -288,15 +288,51 @@ The image is square ({{ width }}x{{ height }}px). Square images are not allowed. - Slika je kvadratna ({{ width }}x{{ height }}px). Kvadratne slike nisu dozvoljene. + Slika je kvadratna ({{ width }}x{{ height }} piksela). Kvadratne slike nisu dozvoljene. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. - Slika je orijentacije pejzaža ({{ width }}x{{ height }}px). Pejzažna orijentacija slika nije dozvoljena. + Slika je pejzažno orijentisana ({{ width }}x{{ height }} piksela). Pejzažna orijentisane slike nisu dozvoljene. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. - Slika je orijantacije portreta ({{ width }}x{{ height }}px). Portretna orijentacija slika nije dozvoljena. + Slika je portretno orijentisana ({{ width }}x{{ height }} piksela). Portretno orijentisane slike nisu dozvoljene. + + + An empty file is not allowed. + Prazna datoteka nije dozvoljena. + + + The host could not be resolved. + Nije moguće odrediti poslužitelja. + + + This value does not match the expected {{ charset }} charset. + Vrednost se ne poklapa sa očekivanim {{ charset }} setom karaktera. + + + This is not a valid Business Identifier Code (BIC). + Ovo nije validan BIC. + + + Error + Greška + + + This is not a valid UUID. + Ovo nije validan univerzalni unikatni identifikator (UUID). + + + This value should be a multiple of {{ compared_value }}. + Ova vrednost bi trebalo da bude višestruko veća od {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + BIC kod nije povezan sa IBAN {{ iban }}. + + + This value should be valid JSON. + Ova vrednost bi trebalo da bude validan JSON. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 5e19e3e5a3c66..a23c652b176e8 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -222,10 +222,114 @@ Unsupported card type or invalid card number. Desteklenmeyen kart tipi veya geçersiz kart numarası. + + This is not a valid International Bank Account Number (IBAN). + Bu geçerli bir Uluslararası Banka Hesap Numarası (IBAN) değildir. + + + This value is not a valid ISBN-10. + Bu değer geçerli bir ISBN-10 değildir. + + + This value is not a valid ISBN-13. + Bu değer geçerli bir ISBN-13 değildir. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Bu değer geçerli bir ISBN-10 veya ISBN-13 değildir. + + + This value is not a valid ISSN. + Bu değer geçerli bir ISSN değildir. + + + This value is not a valid currency. + Bu değer geçerli bir para birimi değil. + + + This value should be equal to {{ compared_value }}. + Bu değer {{ compared_value }} ile eşit olmalıdır. + + + This value should be greater than {{ compared_value }}. + Bu değer {{ compared_value }} değerinden büyük olmalıdır. + + + This value should be greater than or equal to {{ compared_value }}. + Bu değer {{ compared_value }} ile eşit veya büyük olmalıdır. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Bu değer {{ compared_value_type }} {{ compared_value }} ile aynı olmalıdır. + + + This value should be less than {{ compared_value }}. + Bu değer {{ compared_value }} değerinden düşük olmalıdır. + + + This value should be less than or equal to {{ compared_value }}. + .Bu değer {{ compared_value }} ile eşit veya düşük olmalıdır. + + + This value should not be equal to {{ compared_value }}. + Bu değer {{ compared_value }} ile eşit olmamalıdır. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Bu değer {{ compared_value_type }} {{ compared_value }} ile aynı olmamalıdır. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Resim oranı çok büyük ({{ ratio }}). İzin verilen maksimum oran: {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Resim oranı çok ufak ({{ ratio }}). Beklenen minimum oran {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Resim karesi ({{ width }}x{{ height }}px). Kare resimlerine izin verilmiyor. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Resim manzara odaklı ({{ width }}x{{ height }}px). Manzara odaklı resimlere izin verilmiyor. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Resim portre odaklı ({{ width }}x{{ height }}px). Portre odaklı resimlere izin verilmiyor. + + + An empty file is not allowed. + Boş bir dosyaya izin verilmiyor. + + + The host could not be resolved. + Sunucu çözülemedi. + + + This value does not match the expected {{ charset }} charset. + Bu değer beklenen {{ charset }} karakter kümesiyle eşleşmiyor. + + + This is not a valid Business Identifier Code (BIC). + Bu geçerli bir İşletme Tanımlayıcı Kodu (BIC) değildir. + Error Hata + + This is not a valid UUID. + Bu geçerli bir UUID değildir. + + + This value should be a multiple of {{ compared_value }}. + Bu değer {{ compare_value }} değerinin katlarından biri olmalıdır. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Bu İşletme Tanımlayıcı Kodu (BIC), IBAN {{ iban }} ile ilişkili değildir. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf index 6a92801c9b47d..5ddc429854e54 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf @@ -318,6 +318,18 @@ Error Помилка + + This is not a valid UUID. + Це не валідне значення UUID. + + + This value should be a multiple of {{ compared_value }}. + Це значення повинне бути кратним {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Банківський код (BIC) не пов’язаний із міжнародним номером банківського рахунку (IBAN) {{ iban }}. + diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php index ac48a512c6292..1edf1de0811db 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php @@ -26,7 +26,7 @@ public function __construct(array $array = null) public function offsetExists($offset) { - return array_key_exists($offset, $this->array); + return \array_key_exists($offset, $this->array); } public function offsetGet($offset) diff --git a/src/Symfony/Component/VarDumper/Caster/DoctrineCaster.php b/src/Symfony/Component/VarDumper/Caster/DoctrineCaster.php index 6adf9dd837623..696b87816ea8e 100644 --- a/src/Symfony/Component/VarDumper/Caster/DoctrineCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DoctrineCaster.php @@ -26,7 +26,7 @@ class DoctrineCaster public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, $isNested) { foreach (['__cloner__', '__initializer__'] as $k) { - if (array_key_exists($k, $a)) { + if (\array_key_exists($k, $a)) { unset($a[$k]); ++$stub->cut; } @@ -38,7 +38,7 @@ public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, $isNested) { foreach (['_entityPersister', '_identifier'] as $k) { - if (array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { unset($a[$k]); ++$stub->cut; } @@ -50,7 +50,7 @@ public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, $isNe public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, $isNested) { foreach (['snapshot', 'association', 'typeClass'] as $k) { - if (array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { $a[$k] = new CutStub($a[$k]); } } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 025aee359b976..bb5ee94d8b43b 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -259,7 +259,7 @@ public function seek($key) $children = $this->data[$item->position]; foreach ($keys as $key) { - if (isset($children[$key]) || array_key_exists($key, $children)) { + if (isset($children[$key]) || \array_key_exists($key, $children)) { $data = clone $this; $data->key = $key; $data->position = $item->position; diff --git a/src/Symfony/Component/VarDumper/Cloner/Stub.php b/src/Symfony/Component/VarDumper/Cloner/Stub.php index 08fba759301c6..27dd3ef32c4df 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Stub.php +++ b/src/Symfony/Component/VarDumper/Cloner/Stub.php @@ -39,22 +39,29 @@ class Stub public $position = 0; public $attr = []; + private static $defaultProperties = []; + /** * @internal */ public function __sleep() { - $this->serialized = [$this->class, $this->position, $this->cut, $this->type, $this->value, $this->handle, $this->refCount, $this->attr]; + $properties = []; - return ['serialized']; - } + if (!isset(self::$defaultProperties[$c = \get_class($this)])) { + self::$defaultProperties[$c] = get_class_vars($c); - /** - * @internal - */ - public function __wakeup() - { - list($this->class, $this->position, $this->cut, $this->type, $this->value, $this->handle, $this->refCount, $this->attr) = $this->serialized; - unset($this->serialized); + foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { + unset(self::$defaultProperties[$c][$k]); + } + } + + foreach (self::$defaultProperties[$c] as $k => $v) { + if ($this->$k !== $v) { + $properties[] = $k; + } + } + + return $properties; } } diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 7916c65384572..f418aa089488d 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -33,6 +33,7 @@ protected function doClone($var) $indexedArrays = []; // Map of queue indexes that hold numerically indexed arrays $hardRefs = []; // Map of original zval hashes to stub objects $objRefs = []; // Map of original object handles to their stub object counterpart + $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning $resRefs = []; // Map of original resource handles to their stub object counterpart $values = []; // Map of stub objects' hashes to original values $maxItems = $this->maxItems; @@ -200,6 +201,7 @@ protected function doClone($var) } if (empty($objRefs[$h])) { $objRefs[$h] = $stub; + $objects[] = $v; } else { $stub = $objRefs[$h]; ++$stub->refCount; diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index 72c8258a62ae9..30cd1a1b193d1 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -39,7 +39,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface /** * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput - * @param string $charset The default character encoding to use for non-UTF8 strings + * @param string|null $charset The default character encoding to use for non-UTF8 strings * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation */ public function __construct($output = null, $charset = null, $flags = 0) diff --git a/src/Symfony/Component/Workflow/DependencyInjection/ValidateWorkflowsPass.php b/src/Symfony/Component/Workflow/DependencyInjection/ValidateWorkflowsPass.php index 7100095735de3..57573823e1d2c 100644 --- a/src/Symfony/Component/Workflow/DependencyInjection/ValidateWorkflowsPass.php +++ b/src/Symfony/Component/Workflow/DependencyInjection/ValidateWorkflowsPass.php @@ -34,13 +34,13 @@ public function process(ContainerBuilder $container) $taggedServices = $container->findTaggedServiceIds($this->definitionTag, true); foreach ($taggedServices as $id => $tags) { foreach ($tags as $tag) { - if (!array_key_exists('name', $tag)) { + if (!\array_key_exists('name', $tag)) { throw new RuntimeException(sprintf('The "name" for the tag "%s" of service "%s" must be set.', $this->definitionTag, $id)); } - if (!array_key_exists('type', $tag)) { + if (!\array_key_exists('type', $tag)) { throw new RuntimeException(sprintf('The "type" for the tag "%s" of service "%s" must be set.', $this->definitionTag, $id)); } - if (!array_key_exists('marking_store', $tag)) { + if (!\array_key_exists('marking_store', $tag)) { throw new RuntimeException(sprintf('The "marking_store" for the tag "%s" of service "%s" must be set.', $this->definitionTag, $id)); } diff --git a/src/Symfony/Component/Workflow/Tests/Validator/StateMachineValidatorTest.php b/src/Symfony/Component/Workflow/Tests/Validator/StateMachineValidatorTest.php index c43292899b893..4e344560557d4 100644 --- a/src/Symfony/Component/Workflow/Tests/Validator/StateMachineValidatorTest.php +++ b/src/Symfony/Component/Workflow/Tests/Validator/StateMachineValidatorTest.php @@ -94,7 +94,7 @@ public function testValid() (new StateMachineValidator())->validate($definition, 'foo'); - // the test simply ensures that the validation does not fail (i.e. it does not throw any exceptions) + // the test ensures that the validation does not fail (i.e. it does not throw any exceptions) $this->addToAssertionCount(1); // The graph looks like: diff --git a/src/Symfony/Component/Workflow/Tests/Validator/WorkflowValidatorTest.php b/src/Symfony/Component/Workflow/Tests/Validator/WorkflowValidatorTest.php index cdf10ecdaba93..4a5c5a57dd85f 100644 --- a/src/Symfony/Component/Workflow/Tests/Validator/WorkflowValidatorTest.php +++ b/src/Symfony/Component/Workflow/Tests/Validator/WorkflowValidatorTest.php @@ -29,7 +29,7 @@ public function testSinglePlaceWorkflowValidatorAndSimpleWorkflow() (new WorkflowValidator(true))->validate($definition, 'foo'); - // the test simply ensures that the validation does not fail (i.e. it does not throw any exceptions) + // the test ensures that the validation does not fail (i.e. it does not throw any exceptions) $this->addToAssertionCount(1); } @@ -64,7 +64,7 @@ public function testSameTransitionNameButNotSamePlace() (new WorkflowValidator())->validate($definition, 'foo'); - // the test simply ensures that the validation does not fail (i.e. it does not throw any exceptions) + // the test ensures that the validation does not fail (i.e. it does not throw any exceptions) $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 67a71d00e333a..5d71a1f30f08c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -633,7 +633,7 @@ private static function evaluateScalar($scalar, $flags, $references = []) throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename); } - if (!array_key_exists($value, $references)) { + if (!\array_key_exists($value, $references)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename); } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index d40fde55f0aaa..cc094085c62b9 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -289,7 +289,7 @@ private function doParse($value, $flags) $allowOverwrite = true; if (isset($values['value'][0]) && '*' === $values['value'][0]) { $refName = substr(rtrim($values['value']), 1); - if (!array_key_exists($refName, $this->refs)) { + if (!\array_key_exists($refName, $this->refs)) { if (false !== $pos = array_search($refName, $this->refsBeingParsed, true)) { throw new ParseException(sprintf('Circular reference [%s, %s] detected for reference "%s".', implode(', ', \array_slice($this->refsBeingParsed, $pos)), $refName, $refName), $this->currentLineNb + 1, $this->currentLine, $this->filename); } @@ -698,7 +698,7 @@ private function parseValue($value, $flags, $context) $value = substr($value, 1); } - if (!array_key_exists($value, $this->refs)) { + if (!\array_key_exists($value, $this->refs)) { if (false !== $pos = array_search($value, $this->refsBeingParsed, true)) { throw new ParseException(sprintf('Circular reference [%s, %s] detected for reference "%s".', implode(', ', \array_slice($this->refsBeingParsed, $pos)), $value, $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); }