From c1b56cd1f8db3cb98e6d9d70175ee08c44b40f5d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:13:42 +0200 Subject: [PATCH 01/46] updated CHANGELOG for 3.4.41 --- CHANGELOG-3.4.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index 7fc92f86eb326..dfd39c33e34d0 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.41 (2020-05-31) + + * bug #36894 [Validator] never directly validate Existence (Required/Optional) constraints (xabbuh) + * bug #37007 [Console] Fix QuestionHelper::disableStty() (chalasr) + * bug #36865 [Form] validate subforms in all validation groups (xabbuh) + * bug #36907 Fixes sprintf(): Too few arguments in form transformer (pedrocasado) + * bug #37000 Add meaningful message when using ProcessHelper and Process is not installed (l-vo) + * bug #36987 Handle fetch mode deprecation of DBAL 2.11. (derrabus) + * bug #36974 [Security] Fixed handling of CSRF logout error (wouterj) + * bug #36920 [VarDumper] fix PHP 8 support (nicolas-grekas) + * bug #36917 [Cache] Accessing undefined constants raises an Error in php8 (derrabus) + * bug #36891 Address deprecation of ReflectionType::getClass() (derrabus) + * bug #36899 [VarDumper] ReflectionFunction::isDisabled() is deprecated (derrabus) + * bug #36905 [Validator] Catch expected ValueError (derrabus) + * bug #36906 [DomCrawler] Catch expected ValueError (derrabus) + * bug #36904 [PropertyAccess] Parse php 8 TypeErrors correctly (derrabus) + * bug #36896 [Config] Removed implicit cast of ReflectionProperty to string (derrabus) + * bug #36882 [PhpUnitBridge] fix installing under PHP >= 8 (nicolas-grekas) + * bug #36833 [HttpKernel] Fix that the `Store` would not save responses with the X-Content-Digest header present (mpdude) + * bug #36867 [PhpUnitBridge] fix bad detection of unsilenced deprecations (nicolas-grekas) + * bug #36855 [HttpKernel] Fix error logger when stderr is redirected to /dev/null (fabpot) + * bug #36592 [BrowserKit] Allow Referer set by history to be overridden (Slamdunk) + * bug #36794 [Serializer] fix issue with PHP 8 (nicolas-grekas) + * bug #36743 [Yaml] Fix escaped quotes in quoted multi-line string (ossinkine) + * bug #36569 [PhpUnitBridge] Mark parent class also covered in CoverageListener (lyrixx) + * bug #36690 [Yaml] prevent notice for invalid octal numbers on PHP 7.4 (xabbuh) + * bug #36497 [Filesystem] Handle paths on different drives (crishoj) + * bug #36678 [WebProfiler] Do not add src-elem CSP directives if they do not exist (ndench) + * bug #36501 [DX] Show the ParseException message in all YAML file loaders (fancyweb) + * bug #36683 [Yaml] fix parse error when unindented collections contain a comment (wdiesveld) + * bug #36672 [Validator] Skip validation when email is an empty object (acrobat) + * bug #36673 [PhpUnitBridge] fix PHP 5.3 compat again (nicolas-grekas) + * bug #36627 [Validator] fix lazy property usage. (bendavies) + * bug #36625 [PhpUnitBridge] fix compat with PHP 5.3 (nicolas-grekas) + * 3.4.40 (2020-04-28) * bug #36566 [PhpUnitBridge] Use COMPOSER_BINARY env var if available (fancyweb) From 46a783df634d8ae8e886329d8874ee97880f7c40 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:14:13 +0200 Subject: [PATCH 02/46] update CONTRIBUTORS for 3.4.41 --- CONTRIBUTORS.md | 88 +++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 449973d7578eb..baf025cfe0487 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -23,15 +23,15 @@ Symfony is the result of the work of many people who made the code better - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) - Yonel Ceruto (yonelceruto) - - Hugo Hamon (hhamon) - Wouter de Jong (wouterj) + - Hugo Hamon (hhamon) - Thomas Calvet (fancyweb) + - Alexander M. Turek (derrabus) - Abdellatif Ait boudad (aitboudad) - Samuel ROZE (sroze) - Romain Neutron (romain) - Pascal Borreli (pborreli) - Joseph Bielawski (stloyd) - - Alexander M. Turek (derrabus) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - Jules Pietri (heah) @@ -60,16 +60,16 @@ Symfony is the result of the work of many people who made the code better - Alexander Mols (asm89) - Konstantin Myakshin (koc) - Grégoire Paris (greg0ire) - - Bulat Shakirzyanov (avalanche123) - Valentin Udaltsov (vudaltsov) + - Bulat Shakirzyanov (avalanche123) - Kevin Bond (kbond) - Saša Stamenković (umpirsky) - Peter Rehm (rpet) - - Henrik Bjørnskov (henrikbjorn) - Gabriel Ostrolucký (gadelat) + - Henrik Bjørnskov (henrikbjorn) + - Gábor Egyed (1ed) - Miha Vrhovnik - David Maicher (dmaicher) - - Gábor Egyed (1ed) - Diego Saint Esteben (dii3g0) - Jan Schädlich (jschaedl) - Titouan Galopin (tgalopin) @@ -132,6 +132,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - excelwebzone + - Massimiliano Arione (garak) - Gordon Franke (gimler) - Joel Wurtz (brouznouf) - Fabien Pennequin (fabienpennequin) @@ -139,7 +140,6 @@ Symfony is the result of the work of many people who made the code better - Przemysław Bogusz (przemyslaw-bogusz) - Eric GELOEN (gelo) - Lars Strojny (lstrojny) - - Massimiliano Arione (garak) - Jannik Zschiesche (apfelbox) - Robert Schönthal (digitalkaoz) - Gregor Harlan (gharlan) @@ -161,6 +161,7 @@ Symfony is the result of the work of many people who made the code better - Yanick Witschi (toflar) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) + - Laurent VOULLEMIER (lvo) - SpacePossum - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) @@ -181,6 +182,7 @@ Symfony is the result of the work of many people who made the code better - jeremyFreeAgent (jeremyfreeagent) - Rouven Weßling (realityking) - Jérôme Parmentier (lctrs) + - Ben Davies (bendavies) - Andreas Schempp (aschempp) - Clemens Tolboom - Helmer Aaviksoo @@ -195,7 +197,7 @@ Symfony is the result of the work of many people who made the code better - Tyson Andre - GDIBass - Samuel NELA (snela) - - Ben Davies (bendavies) + - Saif (╯°□°)╯ (azjezz) - James Halsall (jaitsu) - Matthieu Napoli (mnapoli) - Florent Mata (fmata) @@ -204,6 +206,7 @@ Symfony is the result of the work of many people who made the code better - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - Marek Štípek (maryo) + - Filippo Tessarotto (slamdunk) - Daniel Espendiller - Possum - Dorian Villet (gnutix) @@ -211,11 +214,11 @@ Symfony is the result of the work of many people who made the code better - Sergey Linnik (linniksa) - Richard Miller (mr_r_miller) - Albert Casademont (acasademont) + - Wouter J - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) - DQNEO - Andre Rømcke (andrerom) - - Saif (╯°□°)╯ (azjezz) - mcfedr (mcfedr) - Gary PEGEOT (gary-p) - Ruben Gonzalez (rubenrua) @@ -232,7 +235,6 @@ Symfony is the result of the work of many people who made the code better - Stadly - Stepan Anchugov (kix) - bronze1man - - Filippo Tessarotto (slamdunk) - sun (sun) - Larry Garfield (crell) - Nikolay Labinskiy (e-moe) @@ -245,7 +247,6 @@ Symfony is the result of the work of many people who made the code better - fivestar - Dominique Bongiraud - Jeremy Livingston (jeremylivingston) - - Laurent VOULLEMIER (lvo) - Michael Lee (zerustech) - Matthieu Auger (matthieuauger) - Mathias Arlaud (mtarld) @@ -255,6 +256,7 @@ Symfony is the result of the work of many people who made the code better - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) + - Tien Vo (tienvx) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Michele Orselli (orso) @@ -269,7 +271,6 @@ Symfony is the result of the work of many people who made the code better - Tristan Darricau (nicofuma) - Victor Bocharsky (bocharsky_bw) - Tomas Norkūnas (norkunas) - - Wouter J - Smaine Milianni (ismail1432) - Marcel Beerta (mazen) - Christopher Hertel (chertel) @@ -295,7 +296,6 @@ Symfony is the result of the work of many people who made the code better - Marcos Sánchez - Elnur Abdurrakhimov (elnur) - Manuel Reinhard (sprain) - - Tien Vo (tienvx) - Danny Berger (dpb587) - Antonio J. García Lagar (ajgarlag) - Adam Prager (padam87) @@ -309,6 +309,7 @@ Symfony is the result of the work of many people who made the code better - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA - Patrick McDougle (patrick-mcdougle) + - Marc Weistroff (futurecat) - Alif Rachmawadi - Anton Chernikov (anton_ch1989) - Kristen Gilden (kgilden) @@ -318,6 +319,7 @@ Symfony is the result of the work of many people who made the code better - Jakub Kucharovic (jkucharovic) - Loick Piera (pyrech) - Uwe Jäger (uwej711) + - Martin Hujer (martinhujer) - Eugene Leonovich (rybakit) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) @@ -354,9 +356,9 @@ Symfony is the result of the work of many people who made the code better - Wouter Van Hecke - Peter Kruithof (pkruithof) - Michael Holm (hollo) + - Antonio Pauletich (x-coder264) - Arjen van der Meijden - Mathieu Lechat - - Marc Weistroff (futurecat) - Damien Alexandre (damienalexandre) - Simon Mönch (sm) - Christian Schmidt @@ -388,6 +390,7 @@ Symfony is the result of the work of many people who made the code better - Aurelijus Valeiša (aurelijus) - Jan Decavele (jandc) - Gustavo Piltcher + - Jesse Rushlow (geeshoe) - Stepan Tanasiychuk (stfalcon) - Tiago Ribeiro (fixe) - Hidde Boomsma (hboomsma) @@ -416,7 +419,9 @@ Symfony is the result of the work of many people who made the code better - Nicolas LEFEVRE (nicoweb) - alquerci - Oleg Andreyev + - Langlet Vincent (deviling) - Mateusz Sip (mateusz_sip) + - Alessandro Lai (jean85) - Francesco Levorato - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) @@ -427,14 +432,15 @@ Symfony is the result of the work of many people who made the code better - Tomasz Kowalczyk (thunderer) - Artur Eshenbrener - Timo Bakx (timobakx) - - Antonio Pauletich (x-coder264) - Thomas Perez (scullwm) - Felix Labrecque - Yaroslav Kiliba - Terje Bråten - Robbert Klarenbeek (robbertkl) + - soyuka - Eric Masoero (eric-masoero) - Denis Brumann (dbrumann) + - Gocha Ossinkine (ossinkine) - JhonnyL - Haralan Dobrev (hkdobrev) - hossein zolfi (ocean) @@ -449,10 +455,10 @@ Symfony is the result of the work of many people who made the code better - Philipp Kräutli (pkraeutli) - Grzegorz (Greg) Zdanowski (kiler129) - Iker Ibarguren (ikerib) + - Dimitri Gritsajuk (ottaviano) - Kirill chEbba Chebunin (chebba) - Rokas Mikalkėnas (rokasm) - Greg Thornton (xdissent) - - Martin Hujer (martinhujer) - Alex Bowers - Philipp Cordes - Costin Bereveanu (schniper) @@ -473,6 +479,7 @@ Symfony is the result of the work of many people who made the code better - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer + - Timothée Barray (tyx) - Shein Alexey - Romain Gautier (mykiwi) - Joe Lencioni @@ -489,7 +496,6 @@ Symfony is the result of the work of many people who made the code better - Xavier HAUSHERR - Albert Jessurum (ajessu) - Laszlo Korte - - Jesse Rushlow (geeshoe) - Miha Vrhovnik - Alessandro Desantis - hubert lecorche (hlecorche) @@ -501,6 +507,7 @@ Symfony is the result of the work of many people who made the code better - Christophe L. (christophelau) - Sander Toonen (xatoo) - Anthon Pang (robocoder) + - Marko Kaznovac (kaznovac) - Sébastien Santoro (dereckson) - Brian King - Michel Salib (michelsalib) @@ -524,7 +531,6 @@ Symfony is the result of the work of many people who made the code better - Mihai Stancu - Ivan Nikolaev (destillat) - Gildas Quéméner (gquemener) - - Alessandro Lai (jean85) - Desjardins Jérôme (jewome62) - Arturs Vonda - Josip Kruslin @@ -561,7 +567,6 @@ Symfony is the result of the work of many people who made the code better - Marek Pietrzak - Luc Vieillescazes (iamluc) - franek (franek) - - soyuka - Raulnet - Christian Wahler - Giso Stallenberg (gisostallenberg) @@ -571,7 +576,6 @@ Symfony is the result of the work of many people who made the code better - HypeMC - Soufian EZ-ZANTAR (soezz) - Zander Baldwin - - Gocha Ossinkine (ossinkine) - Adam Harvey - Anton Bakai - Martin Auswöger @@ -603,9 +607,9 @@ Symfony is the result of the work of many people who made the code better - Philipp Rieber (bicpi) - Manuel de Ruiter (manuel) - Nathanael Noblet (gnat) - - Dimitri Gritsajuk (ottaviano) - nikos.sotiropoulos - Eduardo Oliveira (entering) + - Oleksii Zhurbytskyi - Ilya Antipenko (aivus) - Ricardo Oliveira (ricardolotr) - Roy Van Ginneken (rvanginneken) @@ -645,9 +649,9 @@ Symfony is the result of the work of many people who made the code better - Gábor Fási - DUPUCH (bdupuch) - Nate (frickenate) - - Timothée Barray (tyx) - jhonnyL - Jacek Jędrzejewski (jacek.jedrzejewski) + - Stefan Kruppa - sasezaki - Bozhidar Hristov (warxcell) - Dawid Pakuła (zulusx) @@ -684,7 +688,6 @@ Symfony is the result of the work of many people who made the code better - Pavel Campr (pcampr) - Andrii Dembitskyi - Johnny Robeson (johnny) - - Marko Kaznovac (kaznovac) - Guilliam Xavier - Disquedur - Michiel Boeckaert (milio) @@ -711,6 +714,7 @@ Symfony is the result of the work of many people who made the code better - vitaliytv - Philippe Segatori - Dalibor Karlović (dkarlovi) + - Andrey Sevastianov - Sebastian Blum - Alexis Lefebvre - aubx @@ -728,6 +732,7 @@ Symfony is the result of the work of many people who made the code better - Sinan Eldem - BoShurik - Alexandre Dupuy (satchette) + - Michel Hunziker - Malte Blättermann - Simeon Kolev (simeon_kolev9) - Joost van Driel (j92) @@ -741,7 +746,6 @@ Symfony is the result of the work of many people who made the code better - Stefan Gehrig (sgehrig) - Hany el-Kerdany - Wang Jingyu - - Langlet Vincent (deviling) - Åsmund Garfors - Gunnstein Lye (glye) - Maxime Douailin @@ -847,8 +851,10 @@ Symfony is the result of the work of many people who made the code better - Michael Lutz - Koen Reiniers (koenre) - jochenvdv + - Michel Roca (mroca) - Reedy - Arturas Smorgun (asarturas) + - Michał (bambucha15) - Alexander Volochnev (exelenz) - Michael Piecko - Toni Peric (tperic) @@ -879,12 +885,12 @@ Symfony is the result of the work of many people who made the code better - Axel Guckelsberger (guite) - Jose Gonzalez - Jonathan (jls-esokia) - - Oleksii Zhurbytskyi - Dariusz Ruminski - Joshua Nye - Claudio Zizza - Dave Marshall (davedevelopment) - Jakub Kulhan (jakubkulhan) + - Nathan Dench (ndenc2) - Shaharia Azam - avorobiev - stoccc @@ -948,9 +954,11 @@ Symfony is the result of the work of many people who made the code better - GDIBass - Antoine Lamirault - Adrien Lucas (adrienlucas) + - Jeroen Thora (bolle) - Zhuravlev Alexander (scif) - Stefano Degenkamp (steef) - James Michael DuPont + - Carlos Buenosvinos (carlosbuenosvinos) - Tom Klingenberg - Christopher Hall (mythmakr) - Patrick Dawkins (pjcdawkins) @@ -982,6 +990,7 @@ Symfony is the result of the work of many people who made the code better - Julie Hourcade (juliehde) - Dmitry Parnas (parnas) - Paul LE CORRE + - Loïc Beurlet - Daniel Gorgan - Tony Malzhacker - Mathieu MARCHOIS @@ -1006,7 +1015,6 @@ Symfony is the result of the work of many people who made the code better - Jelle Kapitein - Benoît Bourgeois - mantulo - - Stefan Kruppa - corphi - JoppeDC - grizlik @@ -1049,6 +1057,7 @@ Symfony is the result of the work of many people who made the code better - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) + - Hugo Alliaume (kocal) - Marcos Gómez Vilches (markitosgv) - Matthew Davis (mdavis1982) - Markus S. (staabm) @@ -1062,6 +1071,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Cestari - Matt Janssen - David Lima + - Dmitriy Derepko - Stéphane Delprat - Brian Freytag (brianfreytag) - Samuele Lilli (doncallisto) @@ -1148,6 +1158,7 @@ Symfony is the result of the work of many people who made the code better - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) - Danilo Silva + - Giuseppe Campanelli - Arnaud PETITPAS (apetitpa) - Ken Stanley - Zachary Tong (polyfractal) @@ -1164,6 +1175,7 @@ Symfony is the result of the work of many people who made the code better - Tero Alén (tero) - Stanislav Kocanda - DerManoMann + - MatTheCat - Guillaume Royer - Artem (digi) - boite @@ -1184,7 +1196,6 @@ Symfony is the result of the work of many people who made the code better - Danijel Obradović - Pablo Borowicz - Mathieu Santostefano - - Michel Hunziker - Arjan Keeman - Máximo Cuadros (mcuadros) - Lukas Mencl @@ -1277,7 +1288,6 @@ Symfony is the result of the work of many people who made the code better - Jakub Sacha - Olaf Klischat - orlovv - - Andrey Sevastianov - Claude Dioudonnat - Jonathan Hedstrom - Peter Smeets (darkspartan) @@ -1297,12 +1307,10 @@ Symfony is the result of the work of many people who made the code better - James Hudson - Stephen Clouse - e-ivanov - - Michał (bambucha15) - Benjamin Dos Santos - Einenlum - Jérémy Jarrié (gagnar) - Jochen Bayer (jocl) - - Michel Roca (mroca) - Patrick Carlo-Hickman - Bruno MATEU - Jeremy Bush @@ -1416,6 +1424,7 @@ Symfony is the result of the work of many people who made the code better - Florian Hermann (fhermann) - Mo Di (modi) - Pablo Schläpfer + - Christian Rishøj - Patrick Berenschot - SuRiKmAn - Gert de Pagter @@ -1423,6 +1432,7 @@ Symfony is the result of the work of many people who made the code better - David Négrier (moufmouf) - Quique Porta (quiqueporta) - mohammadreza honarkhah + - Artem Oliynyk (artemoliynyk) - Andrea Quintino (dirk39) - Tomasz Szymczyk (karion) - Alex Vasilchenko @@ -1453,6 +1463,7 @@ Symfony is the result of the work of many people who made the code better - Andrei Igna - Adam Prickett - azine + - Anton Kroshilin - Dawid Sajdak - Ludek Stepan - Aaron Stephens (astephens) @@ -1605,6 +1616,7 @@ Symfony is the result of the work of many people who made the code better - Robert Queck - Peter Bouwdewijn - mlively + - Wouter Diesveld - Amine Matmati - caalholm - Nouhail AL FIDI (alfidi) @@ -1612,6 +1624,7 @@ Symfony is the result of the work of many people who made the code better - Felipy Tavares Amorim (felipyamorim) - Guillaume Loulier (guikingone) - Klaus Silveira (klaussilveira) + - Pedro Casado (pdr33n) - Pierre Grimaud (pgrimaud) - Thomas Chmielowiec (chmielot) - Jānis Lukss @@ -1724,6 +1737,7 @@ Symfony is the result of the work of many people who made the code better - Stanislav Gamayunov (happyproff) - Iwan van Staveren (istaveren) - Alexander McCullagh (mccullagh) + - Paul L McNeely (mcneely) - Povilas S. (povilas) - Laurent Negre (raulnet) - Evrard Boulou @@ -1809,6 +1823,7 @@ Symfony is the result of the work of many people who made the code better - Mathieu Dewet (mdewet) - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) + - Rémi Faivre (rfv) - Romaric Drigon (romaricdrigon) - Thierry Marianne (thierrymarianne) - Nick Stemerdink @@ -1816,6 +1831,7 @@ Symfony is the result of the work of many people who made the code better - jjanvier - Julius Beckmann - loru88 + - Thibaut Salanon - Romain Dorgueil - Christopher Parotat - Dennis Haarbrink @@ -1860,6 +1876,7 @@ Symfony is the result of the work of many people who made the code better - Chris - Farid Jalilov - Florent Olivaud + - Eric Hertwig - JakeFr - Simon Sargeant - efeen @@ -1920,6 +1937,7 @@ Symfony is the result of the work of many people who made the code better - Michael van Tricht - ReScO - Tim Strehle + - Sébastien COURJEAN - Sam Ward - Michael Voříšek - Walther Lalk @@ -1972,6 +1990,7 @@ Symfony is the result of the work of many people who made the code better - Martijn Boers (plebian) - Pedro Magalhães (pmmaga) - Rares Vlaseanu (raresvla) + - Sergii Dolgushev (serhey) - tante kinast (tante) - Stephen Lewis (tehanomalousone) - Ahmed Hannachi (tiecoders) @@ -1981,6 +2000,7 @@ Symfony is the result of the work of many people who made the code better - Darryl Hein (xmmedia) - Sadicov Vladimir (xtech) - Kevin EMO (zarcox) + - sdkawata - Andrzej - Alexander Zogheb - Rémi Blaise @@ -2016,6 +2036,7 @@ Symfony is the result of the work of many people who made the code better - Ashura - Götz Gottwald - Veres Lajos + - Ernest Hymel - Nick Chiu - grifx - Robert Campbell @@ -2045,6 +2066,7 @@ Symfony is the result of the work of many people who made the code better - Rowan Manning - Per Modin - David Windell + - Christian Scheb - Gabriel Birke - skafandri - Derek Bonner @@ -2088,7 +2110,6 @@ Symfony is the result of the work of many people who made the code better - baron (bastien) - Rosio (ben-rosio) - Simon Paarlberg (blamh) - - Jeroen Thora (bolle) - Brieuc THOMAS (brieucthomas) - Masao Maeda (brtriver) - Damien Harper (damien.harper) @@ -2148,6 +2169,7 @@ Symfony is the result of the work of many people who made the code better - Michael Orlitzky - Nicolas A. Bérard-Nault - Quentin Favrie + - Matthias Derer - Saem Ghani - Stefan Oderbolz - Curtis @@ -2173,7 +2195,6 @@ Symfony is the result of the work of many people who made the code better - Daniele Cesarini (ijanki) - Ismail Asci (ismailasci) - Jeffrey Moelands (jeffreymoelands) - - Hugo Alliaume (kocal) - Simon CONSTANS (kosssi) - Dennis Langen (nijusan) - Paulius Jarmalavičius (pjarmalavicius) @@ -2218,6 +2239,7 @@ Symfony is the result of the work of many people who made the code better - Antonio Angelino - Jens Schulze - Matt Fields + - Olatunbosun Egberinde - Niklas Keller - Andras Debreczeni - Vladimir Sazhin @@ -2352,11 +2374,11 @@ Symfony is the result of the work of many people who made the code better - Karolis Daužickas - Nicolas - Sergio Santoro - - Dmitriy Derepko - tirnanog06 - phc - Дмитрий Пацура - Signor Pedro + - Matthias Larisch - ilyes kooli - Ilia Lazarev - Michaël VEROUX @@ -2388,8 +2410,10 @@ Symfony is the result of the work of many people who made the code better - Christian Gripp (core23) - Christoph Schaefer (cvschaefer) - Damon Jones (damon__jones) + - Cătălin Dan (dancatalin) - Łukasz Giza (destroyer) - Daniel Londero (dlondero) + - Dmitrii Tarasov (dtarasov) - Sebastian Landwehr (dword123) - Adel ELHAIBA (eadel) - Damián Nohales (eagleoneraptor) From 8b909cef4b6e8efef4e4fd8573cd7d61ce46391d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:14:17 +0200 Subject: [PATCH 03/46] updated VERSION for 3.4.41 --- src/Symfony/Component/HttpKernel/Kernel.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index dc9cc048eb53f..00382a95c1e9b 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.40'; - const VERSION_ID = 30440; + const VERSION = '3.4.41'; + const VERSION_ID = 30441; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 40; + const RELEASE_VERSION = 41; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; From 351964749676cf0216e6718c4280b856278289ea Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:24:17 +0200 Subject: [PATCH 04/46] bumped Symfony version to 3.4.42 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 00382a95c1e9b..a0eb026f60fa9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.41'; - const VERSION_ID = 30441; + const VERSION = '3.4.42-DEV'; + const VERSION_ID = 30442; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 41; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 42; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From d45883fb7b92f3ec1f2eaa309a55a7271efdd75a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:29:28 +0200 Subject: [PATCH 05/46] bumped Symfony version to 4.4.10 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 49c7ab594a98f..f0a2ee8d29734 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '4.4.9'; - const VERSION_ID = 40409; + const VERSION = '4.4.10-DEV'; + const VERSION_ID = 40410; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; - const RELEASE_VERSION = 9; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 10; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023'; From 393c9d920ab5e84d5ab702bd47e3e9a1f5fa33f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Pr=C3=A9vot?= Date: Sun, 31 May 2020 14:33:19 -1000 Subject: [PATCH 06/46] =?UTF-8?q?[VarExporter]=20tfix:=C2=A0s/markAsSkippe?= =?UTF-8?q?d/markTestSkipped/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Symfony/Component/VarExporter/Tests/VarExporterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index 2dfb09d2ffc1f..8dbcc06e8ddc6 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -92,7 +92,7 @@ public function testExport(string $testName, $value, bool $staticValueExpected = } elseif (\PHP_VERSION_ID < 70400) { $fixtureFile = __DIR__.'/Fixtures/'.$testName.'-legacy.php'; } else { - $this->markAsSkipped('PHP >= 7.4.6 required.'); + $this->markTestSkipped('PHP >= 7.4.6 required.'); } $this->assertStringEqualsFile($fixtureFile, $dump); From 98fff211401be041a1fd466756fd04fa24c64f4e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 1 Jun 2020 19:29:37 +0200 Subject: [PATCH 07/46] take into account the context when preserving empty array objects --- .../Component/Serializer/Serializer.php | 3 ++- .../Serializer/Tests/SerializerTest.php | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 8e92abe29cdcf..470e9ed0010af 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -20,6 +20,7 @@ use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; +use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface; use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; @@ -157,7 +158,7 @@ public function normalize($data, $format = null, array $context = []) } if (\is_array($data) || $data instanceof \Traversable) { - if ($data instanceof \Countable && 0 === $data->count()) { + if (($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? false) === true && $data instanceof \Countable && 0 === $data->count()) { return $data; } diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index fe8f8de929692..dce864abfcf47 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -491,6 +491,27 @@ public function testNotNormalizableValueExceptionMessageForAResource() (new Serializer())->normalize(tmpfile()); } + public function testNormalizeTransformEmptyArrayObjectToArray() + { + $serializer = new Serializer( + [ + new PropertyNormalizer(), + new ObjectNormalizer(), + new ArrayDenormalizer(), + ], + [ + 'json' => new JsonEncoder(), + ] + ); + + $object = []; + $object['foo'] = new \ArrayObject(); + $object['bar'] = new \ArrayObject(['notempty']); + $object['baz'] = new \ArrayObject(['nested' => new \ArrayObject()]); + + $this->assertSame('{"foo":[],"bar":["notempty"],"baz":{"nested":[]}}', $serializer->serialize($object, 'json')); + } + public function testNormalizePreserveEmptyArrayObject() { $serializer = new Serializer( From 69547d9cfca3606e18fdd56701b3d5c8aea963d0 Mon Sep 17 00:00:00 2001 From: Jeroen Noten Date: Tue, 2 Jun 2020 14:57:19 +0200 Subject: [PATCH 08/46] [HttpClient] Throw JsonException instead of TransportException on empty response in Response::toArray() --- src/Symfony/Component/HttpClient/Response/ResponseTrait.php | 2 +- .../HttpClient/Tests/Response/MockResponseTest.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php index 786e995b16ffd..bb88aaa512c50 100644 --- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php @@ -137,7 +137,7 @@ public function getContent(bool $throw = true): string public function toArray(bool $throw = true): array { if ('' === $content = $this->getContent($throw)) { - throw new TransportException('Response body is empty.'); + throw new JsonException('Response body is empty.'); } if (null !== $this->jsonData) { diff --git a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php index 1b3ab16a843aa..a531da353597d 100644 --- a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php +++ b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php @@ -35,6 +35,12 @@ public function testToArrayError($content, $responseHeaders, $message) public function toArrayErrors() { + yield [ + 'content' => '', + 'responseHeaders' => [], + 'message' => 'Response body is empty.', + ]; + yield [ 'content' => '{}', 'responseHeaders' => ['content-type' => 'plain/text'], From cf4587b498f1c44607d5451ad9a751526af5a167 Mon Sep 17 00:00:00 2001 From: Bruno BOUTAREL Date: Tue, 2 Jun 2020 17:27:51 +0200 Subject: [PATCH 09/46] Move ajax clear event listener initialization on loadToolbar --- .../Resources/views/Profiler/base_js.html.twig | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index c65e278021a0f..58f3867c6f2f1 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -131,13 +131,6 @@ removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); } - - addEventListener(document.querySelector('.sf-toolbar-ajax-clear'), 'click', function() { - requestStack = []; - renderAjaxRequests(); - successStreak = 4; - document.querySelector('.sf-toolbar-ajax-request-list').innerHTML = ''; - }); }; var startAjaxRequest = function(index) { @@ -506,6 +499,12 @@ setPreference('toolbar/displayState', 'block'); }); renderAjaxRequests(); + addEventListener(document.querySelector('.sf-toolbar-ajax-clear'), 'click', function() { + requestStack = []; + renderAjaxRequests(); + successStreak = 4; + document.querySelector('.sf-toolbar-ajax-request-list').innerHTML = ''; + }); addEventListener(document.querySelector('.sf-toolbar-block-ajax'), 'mouseenter', function (event) { var elem = document.querySelector('.sf-toolbar-block-ajax .sf-toolbar-info'); elem.scrollTop = elem.scrollHeight; From bd6a06a8b302f57b8ae84c349582331ff8b84e54 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 4 Jun 2020 11:02:21 +0200 Subject: [PATCH 10/46] [PhpUnitBridge] fix undefined var on version 3.4 --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index f0c7c4085aba4..3c68def22710e 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -107,9 +107,9 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ } if (1 === \count($info['versions'])) { - $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi -s dev phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\""); + $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi -s dev phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\""); } else { - $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\""); + $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\""); } @copy("phpunit-$PHPUNIT_VERSION/phpunit.xsd", 'phpunit.xsd'); From 7df5298ddfbf2eeb10e4b25e93967bca8bbc1afc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 3 Jun 2020 15:32:40 +0200 Subject: [PATCH 11/46] properly cascade validation to child forms --- .../Validator/Constraints/FormValidator.php | 7 +-- .../Constraints/FormValidatorTest.php | 60 ++++++++++++++++++- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 6a8923ecbf0a5..6811dceb9832a 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -72,7 +72,6 @@ public function validate($form, Constraint $formConstraint) if ($groups instanceof GroupSequence) { // Validate the data, the form AND nested fields in sequence $violationsCount = $this->context->getViolations()->count(); - $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s'; foreach ($groups->groups as $group) { if ($validateDataGraph) { @@ -91,7 +90,7 @@ public function validate($form, Constraint $formConstraint) // in different steps without breaking early enough $this->resolvedGroups[$field] = (array) $group; $fieldFormConstraint = new Form(); - $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint); + $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint); } } @@ -100,8 +99,6 @@ public function validate($form, Constraint $formConstraint) } } } else { - $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s'; - if ($validateDataGraph) { $validator->atPath('data')->validate($data, null, $groups); } @@ -132,7 +129,7 @@ public function validate($form, Constraint $formConstraint) if ($field->isSubmitted()) { $this->resolvedGroups[$field] = $groups; $fieldFormConstraint = new Form(); - $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $fieldFormConstraint); + $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint); } } } 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 3d7111f85f3c1..927dd64f52071 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -18,6 +18,7 @@ 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\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\FormFactoryInterface; @@ -51,7 +52,9 @@ class FormValidatorTest extends ConstraintValidatorTestCase protected function setUp() { $this->dispatcher = new EventDispatcher(); - $this->factory = (new FormFactoryBuilder())->getFormFactory(); + $this->factory = (new FormFactoryBuilder()) + ->addExtension(new ValidatorExtension(Validation::createValidator())) + ->getFormFactory(); parent::setUp(); @@ -791,6 +794,61 @@ public function testCompositeConstraintValidatedInSequence() $this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath()); } + public function testCascadeValidationToChildFormsUsingPropertyPaths() + { + $form = $this->getCompoundForm([], [ + 'validation_groups' => ['group1', 'group2'], + ]) + ->add('field1', null, [ + 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'property_path' => '[foo]', + ]) + ->add('field2', null, [ + 'constraints' => [new NotBlank(['groups' => 'group2'])], + 'property_path' => '[bar]', + ]) + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + + $this->assertCount(2, $context->getViolations()); + $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); + $this->assertSame('children[field1].data', $context->getViolations()[0]->getPropertyPath()); + $this->assertSame('This value should not be blank.', $context->getViolations()[1]->getMessage()); + $this->assertSame('children[field2].data', $context->getViolations()[1]->getPropertyPath()); + } + + public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSequence() + { + $form = $this->getCompoundForm([], [ + 'validation_groups' => new GroupSequence(['group1', 'group2']), + ]) + ->add('field1', null, [ + 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'property_path' => '[foo]', + ]) + ; + + $form->submit([ + 'field1' => '', + ]); + + $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + + $this->assertCount(1, $context->getViolations()); + $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); + $this->assertSame('children[field1].data', $context->getViolations()[0]->getPropertyPath()); + } + protected function createValidator() { return new FormValidator(); From d3f9b7f833fd245ca23ae5d78de6c83a7419f62d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 4 Jun 2020 12:27:56 +0200 Subject: [PATCH 12/46] [PhpUnitBridge] Fix undefined index when output of "composer show" cannot be parsed --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 3c68def22710e..8951dbdea1b52 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -106,6 +106,11 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ } } + $info += [ + 'versions' => [], + 'requires' => ['php' => '*'], + ]; + if (1 === \count($info['versions'])) { $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi -s dev phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\""); } else { From dfb4614541963a4544646ca38b88a0b80d805b01 Mon Sep 17 00:00:00 2001 From: Thomas Landauer Date: Sat, 23 May 2020 00:39:09 +0200 Subject: [PATCH 13/46] Update AbstractController.php Removing `string` type-hint of $message at addFlash() Closes https://github.com/symfony/symfony/issues/28991 and https://github.com/symfony/symfony/issues/34645 Reasons: * `addFlash()` is just a convenience shortcut for `FlashBagInterface::add()` which doesn't have the type hint: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php#L28 . So removing it here improves consistency. * https://github.com/symfony/symfony/issues/28991#issuecomment-436755949 is a valid use case for having an object as `$message`. * Twig doesn't have any rendering helpers for the `message`, see https://symfony.com/doc/current/controller.html#flash-messages . And since users have to take care of displaying the `message` themselves, there's no reason to force a string upon them. --- .../Bundle/FrameworkBundle/Controller/ControllerTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 9d5640750af84..8858ca66c437b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -187,7 +187,7 @@ protected function file($file, $fileName = null, $disposition = ResponseHeaderBa * Adds a flash message to the current session for type. * * @param string $type The type - * @param string $message The message + * @param mixed $message The message * * @throws \LogicException * From 9f3b43ab4257fe0dac5725813d0276bec566ab06 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 4 Jun 2020 17:35:46 +0200 Subject: [PATCH 14/46] [PhpUnitBridge] fix syntax on PHP 5.3 --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 8951dbdea1b52..eae4cc3125147 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -106,10 +106,10 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ } } - $info += [ - 'versions' => [], - 'requires' => ['php' => '*'], - ]; + $info += array( + 'versions' => array(), + 'requires' => array('php' => '*'), + ); if (1 === \count($info['versions'])) { $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi -s dev phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\""); From d2a53f0bda892d523f072beb57c329279f9e31c9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 26 May 2020 08:30:07 +0200 Subject: [PATCH 15/46] [HttpClient] fix monitoring timeouts when other streams are active --- .../HttpClient/Internal/NativeClientState.php | 2 -- .../HttpClient/Response/NativeResponse.php | 16 +++---------- .../HttpClient/Response/ResponseTrait.php | 15 ++++++------ .../HttpClient/Tests/CurlHttpClientTest.php | 9 +++++++ .../HttpClient/Tests/HttpClientTestCase.php | 6 +++-- .../HttpClient/Tests/MockHttpClientTest.php | 4 ++++ .../HttpClient/Test/HttpClientTestCase.php | 24 +++++++++++++++++++ .../HttpClient/Test/TestHttpServer.php | 19 +++++++++------ 8 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Component/HttpClient/Internal/NativeClientState.php b/src/Symfony/Component/HttpClient/Internal/NativeClientState.php index 6578929dc5466..2a47dbcca0ec0 100644 --- a/src/Symfony/Component/HttpClient/Internal/NativeClientState.php +++ b/src/Symfony/Component/HttpClient/Internal/NativeClientState.php @@ -28,8 +28,6 @@ final class NativeClientState extends ClientState public $responseCount = 0; /** @var string[] */ public $dnsCache = []; - /** @var resource[] */ - public $handles = []; /** @var bool */ public $sleep = false; diff --git a/src/Symfony/Component/HttpClient/Response/NativeResponse.php b/src/Symfony/Component/HttpClient/Response/NativeResponse.php index 639957415f0dd..2ba1b010e41fb 100644 --- a/src/Symfony/Component/HttpClient/Response/NativeResponse.php +++ b/src/Symfony/Component/HttpClient/Response/NativeResponse.php @@ -220,11 +220,6 @@ private static function schedule(self $response, array &$runningResponses): void */ private static function perform(ClientState $multi, array &$responses = null): void { - // List of native handles for stream_select() - if (null !== $responses) { - $multi->handles = []; - } - foreach ($multi->openHandles as $i => [$h, $buffer, $onProgress]) { $hasActivity = false; $remaining = &$multi->openHandles[$i][3]; @@ -291,8 +286,6 @@ private static function perform(ClientState $multi, array &$responses = null): v $multi->handlesActivity[$i][] = $e; unset($multi->openHandles[$i]); $multi->sleep = false; - } elseif (null !== $responses) { - $multi->handles[] = $h; } } @@ -307,7 +300,7 @@ private static function perform(ClientState $multi, array &$responses = null): v } } - if (\count($multi->handles) >= $multi->maxHostConnections) { + if (\count($multi->openHandles) >= $multi->maxHostConnections) { return; } @@ -318,10 +311,6 @@ private static function perform(ClientState $multi, array &$responses = null): v $multi->sleep = false; self::perform($multi); - if (null !== $response->handle) { - $multi->handles[] = $response->handle; - } - break; } } @@ -335,7 +324,8 @@ private static function perform(ClientState $multi, array &$responses = null): v private static function select(ClientState $multi, float $timeout): int { $_ = []; + $handles = array_column($multi->openHandles, 0); - return (!$multi->sleep = !$multi->sleep) ? -1 : stream_select($multi->handles, $_, $_, (int) $timeout, (int) (1E6 * ($timeout - (int) $timeout))); + return (!$multi->sleep = !$multi->sleep) ? -1 : stream_select($handles, $_, $_, (int) $timeout, (int) (1E6 * ($timeout - (int) $timeout))); } } diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php index 786e995b16ffd..2eb92180e33db 100644 --- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php @@ -316,7 +316,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene } $lastActivity = microtime(true); - $isTimeout = false; + $enlapsedTimeout = 0; while (true) { $hasActivity = false; @@ -338,7 +338,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene } elseif (!isset($multi->openHandles[$j])) { unset($responses[$j]); continue; - } elseif ($isTimeout) { + } elseif ($enlapsedTimeout >= $timeoutMax) { $multi->handlesActivity[$j] = [new ErrorChunk($response->offset, sprintf('Idle timeout reached for "%s".', $response->getInfo('url')))]; } else { continue; @@ -346,7 +346,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene while ($multi->handlesActivity[$j] ?? false) { $hasActivity = true; - $isTimeout = false; + $enlapsedTimeout = 0; if (\is_string($chunk = array_shift($multi->handlesActivity[$j]))) { if (null !== $response->inflate && false === $chunk = @inflate_add($response->inflate, $chunk)) { @@ -379,7 +379,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene } } elseif ($chunk instanceof ErrorChunk) { unset($responses[$j]); - $isTimeout = true; + $enlapsedTimeout = $timeoutMax; } elseif ($chunk instanceof FirstChunk) { if ($response->logger) { $info = $response->getInfo(); @@ -447,10 +447,11 @@ public static function stream(iterable $responses, float $timeout = null): \Gene continue; } - switch (self::select($multi, $timeoutMin)) { - case -1: usleep(min(500, 1E6 * $timeoutMin)); break; - case 0: $isTimeout = microtime(true) - $lastActivity > $timeoutMax; break; + if (-1 === self::select($multi, min($timeoutMin, $timeoutMax - $enlapsedTimeout))) { + usleep(min(500, 1E6 * $timeoutMin)); } + + $enlapsedTimeout = microtime(true) - $lastActivity; } } } diff --git a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php index f83edf91b6f39..9c18ba1cb2752 100644 --- a/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php @@ -112,6 +112,15 @@ public function testHttp2PushVulcainWithUnusedResponse() $this->assertSame($expected, $logger->logs); } + public function testTimeoutIsNotAFatalError() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Too transient on Windows'); + } + + parent::testTimeoutIsNotAFatalError(); + } + private function getVulcainClient(): CurlHttpClient { if (\PHP_VERSION_ID >= 70300 && \PHP_VERSION_ID < 70304) { diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php index 7cfe26e9dfe82..94b35470e338f 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php @@ -72,9 +72,9 @@ public function testToStream404() $this->assertSame($response, stream_get_meta_data($stream)['wrapper_data']->getResponse()); $this->assertSame(404, $response->getStatusCode()); - $this->expectException(ClientException::class); $response = $client->request('GET', 'http://localhost:8057/404'); - $stream = $response->toStream(); + $this->expectException(ClientException::class); + $response->toStream(); } public function testNonBlockingStream() @@ -82,6 +82,7 @@ public function testNonBlockingStream() $client = $this->getHttpClient(__FUNCTION__); $response = $client->request('GET', 'http://localhost:8057/timeout-body'); $stream = $response->toStream(); + usleep(10000); $this->assertTrue(stream_set_blocking($stream, false)); $this->assertSame('<1>', fread($stream, 8192)); @@ -99,6 +100,7 @@ public function testTimeoutIsNotAFatalError() $response = $client->request('GET', 'http://localhost:8057/timeout-body', [ 'timeout' => 0.25, ]); + $this->assertSame(200, $response->getStatusCode()); try { $response->getContent(); diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index b8125e6716cfd..f81322e0bb0b3 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -69,6 +69,10 @@ protected function getHttpClient(string $testCase): HttpClientInterface $this->markTestSkipped("MockHttpClient doesn't unzip"); break; + case 'testTimeoutWithActiveConcurrentStream': + $this->markTestSkipped('Real transport required'); + break; + case 'testDestruct': $this->markTestSkipped("MockHttpClient doesn't timeout on destruct"); break; diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index 8ef46a9a90eeb..c1ad3ffec5014 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -786,6 +786,30 @@ public function testUncheckedTimeoutThrows() } } + public function testTimeoutWithActiveConcurrentStream() + { + $p1 = TestHttpServer::start(8067); + $p2 = TestHttpServer::start(8077); + + $client = $this->getHttpClient(__FUNCTION__); + $streamingResponse = $client->request('GET', 'http://localhost:8067/max-duration'); + $blockingResponse = $client->request('GET', 'http://localhost:8077/timeout-body', [ + 'timeout' => 0.25, + ]); + + $this->assertSame(200, $streamingResponse->getStatusCode()); + $this->assertSame(200, $blockingResponse->getStatusCode()); + + $this->expectException(TransportExceptionInterface::class); + + try { + $blockingResponse->getContent(); + } finally { + $p1->stop(); + $p2->stop(); + } + } + public function testDestruct() { $client = $this->getHttpClient(__FUNCTION__); diff --git a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php index cfc100d80ce6c..06a11444e35e4 100644 --- a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php +++ b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php @@ -19,23 +19,28 @@ */ class TestHttpServer { - private static $process; + private static $process = []; - public static function start() + public static function start(int $port = 8057) { - if (self::$process) { - self::$process->stop(); + if (isset(self::$process[$port])) { + self::$process[$port]->stop(); + } else { + register_shutdown_function(static function () use ($port) { + self::$process[$port]->stop(); + }); } $finder = new PhpExecutableFinder(); - $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', '127.0.0.1:8057'])); + $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', '127.0.0.1:'.$port])); $process->setWorkingDirectory(__DIR__.'/Fixtures/web'); $process->start(); + self::$process[$port] = $process; do { usleep(50000); - } while (!@fopen('http://127.0.0.1:8057/', 'r')); + } while (!@fopen('http://127.0.0.1:'.$port, 'r')); - self::$process = $process; + return $process; } } From 86613797d13fabda30eab7ce5171b7b1de5a9b2f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 5 Jun 2020 23:42:51 +0200 Subject: [PATCH 16/46] [Mime] Remove unused var --- src/Symfony/Component/Mime/Crypto/SMimeSigner.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Symfony/Component/Mime/Crypto/SMimeSigner.php b/src/Symfony/Component/Mime/Crypto/SMimeSigner.php index 243aaf10da060..1b555375ce908 100644 --- a/src/Symfony/Component/Mime/Crypto/SMimeSigner.php +++ b/src/Symfony/Component/Mime/Crypto/SMimeSigner.php @@ -24,11 +24,6 @@ final class SMimeSigner extends SMime private $signOptions; private $extraCerts; - /** - * @var string|null - */ - private $privateKeyPassphrase; - /** * @param string $certificate The path of the file containing the signing certificate (in PEM format) * @param string $privateKey The path of the file containing the private key (in PEM format) @@ -52,7 +47,6 @@ public function __construct(string $certificate, string $privateKey, string $pri $this->signOptions = $signOptions ?? PKCS7_DETACHED; $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; - $this->privateKeyPassphrase = $privateKeyPassphrase; } public function sign(Message $message): Message From 6ee6b2e1b804e86ab20735ea7f7e01a5038c47cc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 8 Jun 2020 17:48:27 +0200 Subject: [PATCH 17/46] [travis] add nightly to allowed failures --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index fd9aa095c9c30..3d5253f077b03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,9 @@ matrix: - php: nightly services: [memcached] fast_finish: true + allow_failures: + - php: nightly + services: [memcached] cache: directories: From 53491b97626ce462c606ad5c9be5eb884fa86223 Mon Sep 17 00:00:00 2001 From: Thomas Landauer Date: Sun, 7 Jun 2020 21:29:41 +0200 Subject: [PATCH 18/46] Update welcome.html.php --- src/Symfony/Component/HttpKernel/Resources/welcome.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Resources/welcome.html.php b/src/Symfony/Component/HttpKernel/Resources/welcome.html.php index e1c0ff11926be..b8337dc737e4e 100644 --- a/src/Symfony/Component/HttpKernel/Resources/welcome.html.php +++ b/src/Symfony/Component/HttpKernel/Resources/welcome.html.php @@ -65,7 +65,7 @@
- You're seeing this page because you haven't configured any homepage URL. + You're seeing this page because you haven't configured any homepage URL and debug mode is enabled.
From 38ad0063a035e5b6600a2b0a4ec3e1fe4d5f9e60 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 9 Jun 2020 09:39:38 +0200 Subject: [PATCH 19/46] [FrameworkBundle] Fix XSD definition --- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 403119842e28e..0a7a56f675a65 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 @@ -578,7 +578,7 @@ - + From c5833fa78497b5562319b0c842bf6405369a3785 Mon Sep 17 00:00:00 2001 From: Ahmed TAILOULOUTE Date: Mon, 8 Jun 2020 21:05:34 +0200 Subject: [PATCH 20/46] [Mailer] Fixed generator bug when creating multiple transports using Transport::fromDsn --- .../Component/Mailer/Tests/TransportTest.php | 16 ++++++++++++++++ src/Symfony/Component/Mailer/Transport.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Tests/TransportTest.php b/src/Symfony/Component/Mailer/Tests/TransportTest.php index 95eb5b6ebf03a..dfd8d1926e61a 100644 --- a/src/Symfony/Component/Mailer/Tests/TransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/TransportTest.php @@ -60,6 +60,22 @@ public function fromStringProvider(): iterable ]; } + /** + * @dataProvider fromDsnProvider + */ + public function testFromDsn(string $dsn, TransportInterface $transport): void + { + $this->assertEquals($transport, Transport::fromDsn($dsn)); + } + + public function fromDsnProvider(): iterable + { + yield 'multiple transports' => [ + 'failover(smtp://a smtp://b)', + new FailoverTransport([new Transport\Smtp\EsmtpTransport('a'), new Transport\Smtp\EsmtpTransport('b')]), + ]; + } + /** * @dataProvider fromWrongStringProvider */ diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index a8f159dc7c491..c0cd0c5fb9dad 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -51,7 +51,7 @@ class Transport public static function fromDsn(string $dsn, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface { - $factory = new self(self::getDefaultFactories($dispatcher, $client, $logger)); + $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger))); return $factory->fromString($dsn); } From 0b9519975dae206a48858ea204c35736765224fd Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 9 Jun 2020 10:25:18 +0200 Subject: [PATCH 21/46] [WebProfilerBundle] Set NullLogger for functional tests --- .../Tests/Functional/WebProfilerBundleKernel.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php index 5470ca7dc6858..a79504a8fe090 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php @@ -2,6 +2,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\Functional; +use Psr\Log\NullLogger; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\TwigBundle\TwigBundle; @@ -73,6 +74,11 @@ public function getLogDir() return sys_get_temp_dir().'/log-'.spl_object_hash($this); } + protected function build(ContainerBuilder $container) + { + $container->register('logger', NullLogger::class); + } + public function homepageController() { return new Response('Homepage Controller.'); From de687876936250c0c0c2fef709db1963b8f669b8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 9 Jun 2020 11:16:12 +0200 Subject: [PATCH 22/46] [Mime] use fromString when creating a new Adress --- src/Symfony/Component/Mime/Address.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mime/Address.php b/src/Symfony/Component/Mime/Address.php index b0dcbd0880f66..53f682c9c2bb7 100644 --- a/src/Symfony/Component/Mime/Address.php +++ b/src/Symfony/Component/Mime/Address.php @@ -89,7 +89,7 @@ public static function create($address): self return $address; } if (\is_string($address)) { - return new self($address); + return self::fromString($address); } throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address))); From 316efef8b8478020828932a3f5980db6b4b92711 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 9 Jun 2020 13:11:23 +0200 Subject: [PATCH 23/46] fix forward compatibility with Doctrine DBAL 3 --- .../Cache/Tests/Traits/PdoPruneableTrait.php | 6 ++++-- src/Symfony/Component/Cache/Traits/PdoTrait.php | 14 ++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php index c5ba9c66d6942..ac25578b0b01a 100644 --- a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php +++ b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Cache\Tests\Traits; +use Doctrine\DBAL\Result; + trait PdoPruneableTrait { protected function isPruned($cache, $name) @@ -27,8 +29,8 @@ protected function isPruned($cache, $name) /** @var \Doctrine\DBAL\Statement|\PDOStatement $select */ $select = $getPdoConn->invoke($cache)->prepare('SELECT 1 FROM cache_items WHERE item_id LIKE :id'); $select->bindValue(':id', sprintf('%%%s', $name)); - $select->execute(); + $result = $select->execute(); - return 1 !== (int) (method_exists($select, 'fetchOne') ? $select->fetchOne() : $select->fetch(\PDO::FETCH_COLUMN)); + return 1 !== (int) ($result instanceof Result ? $result->fetchOne() : $select->fetch(\PDO::FETCH_COLUMN)); } } diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index 6a9f3c46aea45..b00cd930aa95c 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -175,15 +176,16 @@ protected function doFetch(array $ids) foreach ($ids as $id) { $stmt->bindValue(++$i, $id); } - $stmt->execute(); + $result = $stmt->execute(); - if (method_exists($stmt, 'iterateNumeric')) { - $stmt = $stmt->iterateNumeric(); + if ($result instanceof Result) { + $result = $result->iterateNumeric(); } else { $stmt->setFetchMode(\PDO::FETCH_NUM); + $result = $stmt; } - foreach ($stmt as $row) { + foreach ($result as $row) { if (null === $row[1]) { $expired[] = $row[0]; } else { @@ -213,9 +215,9 @@ protected function doHave($id) $stmt->bindValue(':id', $id); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->execute(); + $result = $stmt->execute(); - return (bool) $stmt->fetchColumn(); + return (bool) ($result instanceof Result ? $result->fetchOne() : $stmt->fetchColumn()); } /** From 5a0645974f499995ed772d04db3e7ca185412a18 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 8 Jun 2020 12:38:09 +0200 Subject: [PATCH 24/46] minor #37141 [Messenger] fix forward compatibility with Doctrine DBAL 2.11+ (xabbuh) This PR was merged into the 5.1 branch. Discussion ---------- [Messenger] fix forward compatibility with Doctrine DBAL 2.11+ | Q | A | ------------- | --- | Branch? | 5.1 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | | License | MIT | Doc PR | The methods will be deprecated in 2.11 (see doctrine/dbal#4019), but the forward compatibility layer is only present in 3.0 (see doctrine/dbal#4007). Commits ------- bca4f9970b fix forward compatibility with Doctrine DBAL 2.11+ --- .../Tests/Transport/Doctrine/ConnectionTest.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php index d34e45d2ce518..915fe32ad5b49 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php @@ -13,12 +13,12 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\ResultStatement; -use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Schema\SchemaConfig; use Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer; +use Doctrine\DBAL\Statement; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Transport\Doctrine\Connection; @@ -145,14 +145,10 @@ private function getQueryBuilderMock() private function getStatementMock($expectedResult): ResultStatement { - $mockedInterface = interface_exists(ForwardCompatibleResultStatement::class) - ? ForwardCompatibleResultStatement::class - : ResultStatement::class; - - $stmt = $this->createMock($mockedInterface); + $stmt = $this->createMock(Statement::class); $stmt->expects($this->once()) - ->method(method_exists($mockedInterface, 'fetchAssociative') ? 'fetchAssociative' : 'fetch') + ->method(method_exists(Statement::class, 'fetchAssociative') ? 'fetchAssociative' : 'fetch') ->willReturn($expectedResult); return $stmt; @@ -312,12 +308,9 @@ public function testFindAll() 'headers' => json_encode(['type' => DummyMessage::class]), ]; - $mockedInterface = interface_exists(ForwardCompatibleResultStatement::class) - ? ForwardCompatibleResultStatement::class - : ResultStatement::class; - $stmt = $this->createMock($mockedInterface); + $stmt = $this->createMock(Statement::class); $stmt->expects($this->once()) - ->method(method_exists($mockedInterface, 'fetchAllAssociative') ? 'fetchAllAssociative' : 'fetchAll') + ->method(method_exists(Statement::class, 'fetchAllAssociative') ? 'fetchAllAssociative' : 'fetchAll') ->willReturn([$message1, $message2]); $driverConnection From 7bbbd3dd0d74a8eb68d06df0542d893b46ff66c3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 13:46:03 +0200 Subject: [PATCH 25/46] [Lock] fix compat with doctrine/dbal v3 --- src/Symfony/Component/Lock/Store/PdoStore.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index 7af7f3870fad2..284c0ac2628cf 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\InvalidTtlException; @@ -168,10 +169,10 @@ public function putOffExpiration(Key $key, $ttl) $stmt->bindValue(':id', $this->getHashedKey($key)); $stmt->bindValue(':token1', $uniqueToken); $stmt->bindValue(':token2', $uniqueToken); - $stmt->execute(); + $result = $stmt->execute(); // If this method is called twice in the same second, the row wouldn't be updated. We have to call exists to know if we are the owner - if (!$stmt->rowCount() && !$this->exists($key)) { + if (!($result instanceof Result ? $result : $stmt)->rowCount() && !$this->exists($key)) { throw new LockConflictedException(); } @@ -201,9 +202,9 @@ public function exists(Key $key) $stmt->bindValue(':id', $this->getHashedKey($key)); $stmt->bindValue(':token', $this->getUniqueToken($key)); - $stmt->execute(); + $result = $stmt->execute(); - return (bool) (method_exists($stmt, 'fetchOne') ? $stmt->fetchOne() : $stmt->fetchColumn()); + return (bool) ($result instanceof Result ? $result->fetchOne() : $stmt->fetchColumn()); } /** From 0f7630892923c9a532177608ca835af89d6ce7ab Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 13:48:38 +0200 Subject: [PATCH 26/46] [Cache] fix compat with doctrine/dbal v3 --- src/Symfony/Component/Cache/Traits/PdoTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index b00cd930aa95c..b8bd2255ac054 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -337,9 +337,9 @@ protected function doSave(array $values, $lifetime) } foreach ($serialized as $id => $data) { - $stmt->execute(); + $result = $stmt->execute(); - if (null === $driver && !$stmt->rowCount()) { + if (null === $driver && !($result instanceof Result ? $result : $stmt)->rowCount()) { try { $insertStmt->execute(); } catch (DBALException $e) { From ef6fc092605770ad81fa60c7cff5cf1d62a17257 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 14:06:18 +0200 Subject: [PATCH 27/46] [Cache] fix parse error on PHP 5.5 --- src/Symfony/Component/Cache/Traits/PdoTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index b8bd2255ac054..fd6101d351bf7 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -339,7 +339,7 @@ protected function doSave(array $values, $lifetime) foreach ($serialized as $id => $data) { $result = $stmt->execute(); - if (null === $driver && !($result instanceof Result ? $result : $stmt)->rowCount()) { + if (null === $driver && !($result instanceof Result ? $result->rowCount() : $stmt->rowCount())) { try { $insertStmt->execute(); } catch (DBALException $e) { From 4a51827b6dc49af2955221e3cd8f5348477c85e2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 16:02:17 +0200 Subject: [PATCH 28/46] Correctly use doctrine/dbal v3+ --- src/Symfony/Component/Lock/Store/PdoStore.php | 2 +- .../Tests/Transport/Doctrine/ConnectionTest.php | 17 +++++++++-------- .../Doctrine/DoctrineIntegrationTest.php | 3 ++- .../Messenger/Transport/Doctrine/Connection.php | 9 +++++---- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index 284c0ac2628cf..a3273c0cbc75d 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -13,8 +13,8 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\InvalidTtlException; diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php index 082162b0a4271..8e01d8d288efc 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Tests\Transport\Doctrine; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Schema\AbstractSchemaManager; @@ -29,7 +30,7 @@ public function testGetAMessageWillChangeItsStatus() $queryBuilder = $this->getQueryBuilderMock(); $driverConnection = $this->getDBALConnectionMock(); $schemaSynchronizer = $this->getSchemaSynchronizerMock(); - $stmt = $this->getStatementMock([ + $stmt = $this->getResultMock([ 'id' => 1, 'body' => '{"message":"Hi"}', 'headers' => json_encode(['type' => DummyMessage::class]), @@ -63,7 +64,7 @@ public function testGetWithNoPendingMessageWillReturnNull() $queryBuilder = $this->getQueryBuilderMock(); $driverConnection = $this->getDBALConnectionMock(); $schemaSynchronizer = $this->getSchemaSynchronizerMock(); - $stmt = $this->getStatementMock(false); + $stmt = $this->getResultMock(false); $queryBuilder ->method('getParameters') @@ -142,12 +143,12 @@ private function getQueryBuilderMock() return $queryBuilder; } - private function getStatementMock($expectedResult) + private function getResultMock($expectedResult) { - $stmt = $this->createMock(Statement::class); + $stmt = $this->createMock(interface_exists(Result::class) ? Result::class : Statement::class); $stmt->expects($this->once()) - ->method(method_exists(Statement::class, 'fetchAssociative') ? 'fetchAssociative' : 'fetch') + ->method(interface_exists(Result::class) ? 'fetchAssociative' : 'fetch') ->willReturn($expectedResult); return $stmt; @@ -262,7 +263,7 @@ public function testFind() $driverConnection = $this->getDBALConnectionMock(); $schemaSynchronizer = $this->getSchemaSynchronizerMock(); $id = 1; - $stmt = $this->getStatementMock([ + $stmt = $this->getResultMock([ 'id' => $id, 'body' => '{"message":"Hi"}', 'headers' => json_encode(['type' => DummyMessage::class]), @@ -307,9 +308,9 @@ public function testFindAll() 'headers' => json_encode(['type' => DummyMessage::class]), ]; - $stmt = $this->createMock(Statement::class); + $stmt = $this->createMock(interface_exists(Result::class) ? Result::class : Statement::class); $stmt->expects($this->once()) - ->method(method_exists(Statement::class, 'fetchAllAssociative') ? 'fetchAllAssociative' : 'fetchAll') + ->method(interface_exists(Result::class) ? 'fetchAllAssociative' : 'fetchAll') ->willReturn([$message1, $message2]); $driverConnection diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php index 45ca64b77106a..37a38b95d485e 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Messenger\Tests\Transport\Doctrine; +use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Version; use PHPUnit\Framework\TestCase; @@ -71,7 +72,7 @@ public function testSendWithDelay() ->setParameter(':body', '{"message": "Hi i am delayed"}') ->execute(); - $available_at = new \DateTime(method_exists($stmt, 'fetchOne') ? $stmt->fetchOne() : $stmt->fetchColumn()); + $available_at = new \DateTime($stmt instanceof Result ? $stmt->fetchOne() : $stmt->fetchColumn()); $now = new \DateTime(); $now->modify('+60 seconds'); diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php index 59a54df74955f..19141bd8d94c3 100644 --- a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\Connection as DBALConnection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Schema\Schema; @@ -163,7 +164,7 @@ public function get(): ?array $query->getParameters(), $query->getParameterTypes() ); - $doctrineEnvelope = method_exists($stmt, 'fetchAssociative') ? $stmt->fetchAssociative() : $stmt->fetch(); + $doctrineEnvelope = $stmt instanceof Result ? $stmt->fetchAssociative() : $stmt->fetch(); if (false === $doctrineEnvelope) { $this->driverConnection->commit(); @@ -251,7 +252,7 @@ public function getMessageCount(): int $stmt = $this->executeQuery($queryBuilder->getSQL(), $queryBuilder->getParameters(), $queryBuilder->getParameterTypes()); - return method_exists($stmt, 'fetchOne') ? $stmt->fetchOne() : $stmt->fetchColumn(); + return $stmt instanceof Result ? $stmt->fetchOne() : $stmt->fetchColumn(); } public function findAll(int $limit = null): array @@ -262,7 +263,7 @@ public function findAll(int $limit = null): array } $stmt = $this->executeQuery($queryBuilder->getSQL(), $queryBuilder->getParameters(), $queryBuilder->getParameterTypes()); - $data = method_exists($stmt, 'fetchAllAssociative') ? $stmt->fetchAllAssociative() : $stmt->fetchAll(); + $data = $stmt instanceof Result ? $stmt->fetchAllAssociative() : $stmt->fetchAll(); return array_map(function ($doctrineEnvelope) { return $this->decodeEnvelopeHeaders($doctrineEnvelope); @@ -275,7 +276,7 @@ public function find($id): ?array ->where('m.id = ?'); $stmt = $this->executeQuery($queryBuilder->getSQL(), [$id]); - $data = method_exists($stmt, 'fetchAssociative') ? $stmt->fetchAssociative() : $stmt->fetch(); + $data = $stmt instanceof Result ? $stmt->fetchAssociative() : $stmt->fetch(); return false === $data ? null : $this->decodeEnvelopeHeaders($data); } From 909931d9a44b3afba23e5e9f808f4655a04056e4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 16:06:03 +0200 Subject: [PATCH 29/46] Correctly use doctrine/dbal v3+ --- .../Doctrine/Security/RememberMe/DoctrineTokenProvider.php | 3 ++- .../Component/Cache/Tests/Traits/PdoPruneableTrait.php | 2 +- src/Symfony/Component/Cache/Traits/PdoTrait.php | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index 4bbc9f3fcdfb4..c6e4ab3a308ba 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Doctrine\Security\RememberMe; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; @@ -63,7 +64,7 @@ public function loadTokenBySeries($series) $paramValues = ['series' => $series]; $paramTypes = ['series' => \PDO::PARAM_STR]; $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes); - $row = method_exists($stmt, 'fetchAssociative') ? $stmt->fetchAssociative() : $stmt->fetch(\PDO::FETCH_ASSOC); + $row = $stmt instanceof Result ? $stmt->fetchAssociative() : $stmt->fetch(\PDO::FETCH_ASSOC); if ($row) { return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new \DateTime($row['last_used'])); diff --git a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php index ac25578b0b01a..113a2c28eb8ee 100644 --- a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php +++ b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Cache\Tests\Traits; -use Doctrine\DBAL\Result; +use Doctrine\DBAL\Driver\Result; trait PdoPruneableTrait { diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index fd6101d351bf7..1aa87cd3f1a11 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Cache\Traits; +use Doctrine\DBAL\Abstraction\Result; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\Result as DriverResult; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; -use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -217,7 +218,7 @@ protected function doHave($id) $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $result = $stmt->execute(); - return (bool) ($result instanceof Result ? $result->fetchOne() : $stmt->fetchColumn()); + return (bool) ($result instanceof DriverResult ? $result->fetchOne() : $stmt->fetchColumn()); } /** @@ -339,7 +340,7 @@ protected function doSave(array $values, $lifetime) foreach ($serialized as $id => $data) { $result = $stmt->execute(); - if (null === $driver && !($result instanceof Result ? $result->rowCount() : $stmt->rowCount())) { + if (null === $driver && !($result instanceof DriverResult ? $result->rowCount() : $stmt->rowCount())) { try { $insertStmt->execute(); } catch (DBALException $e) { From 749380a399a792f140ca3b8cf1490c5fcc559b72 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 9 Jun 2020 16:23:13 +0200 Subject: [PATCH 30/46] [Messenger] fix typo --- .../Messenger/Tests/Transport/Doctrine/ConnectionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php index 8e01d8d288efc..b4348d4958a48 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Messenger\Tests\Transport\Doctrine; +use Doctrine\DBAL\Abstraction\Result; use Doctrine\DBAL\DBALException; -use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Schema\AbstractSchemaManager; From f062e08f4d77ba1980a568bbb5df6a35378b858f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 4 Jun 2020 15:06:18 +0200 Subject: [PATCH 31/46] rework form validator tests --- .../FormValidatorFunctionalTest.php | 315 ++++++++++++++++++ .../Constraints/FormValidatorTest.php | 146 -------- .../Validator/ValidatorExtensionTest.php | 158 --------- 3 files changed, 315 insertions(+), 304 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php new file mode 100644 index 0000000000000..1cf1199f71732 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php @@ -0,0 +1,315 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryBuilder; +use Symfony\Component\Form\Test\ForwardCompatTestTrait; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; +use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; +use Symfony\Component\Validator\Validation; + +class FormValidatorFunctionalTest extends TestCase +{ + use ForwardCompatTestTrait; + + private $validator; + private $formFactory; + + private function doSetUp() + { + $this->validator = Validation::createValidatorBuilder() + ->setMetadataFactory(new LazyLoadingMetadataFactory(new StaticMethodLoader())) + ->getValidator(); + $this->formFactory = (new FormFactoryBuilder()) + ->addExtension(new ValidatorExtension($this->validator)) + ->getFormFactory(); + } + + public function testDataConstraintsInvalidateFormEvenIfFieldIsNotSubmitted() + { + $form = $this->formFactory->create(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->formFactory->create(FooType::class); + $form->submit(['bar' => 'foobar'], false); + + $this->assertTrue($form->isSubmitted()); + $this->assertTrue($form->isValid()); + } + + public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted() + { + $form = $this->formFactory->create(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()); + } + + public function testNonCompositeConstraintValidatedOnce() + { + $form = $this->formFactory->create(TextType::class, null, [ + 'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])], + 'validation_groups' => ['foo', 'bar'], + ]); + $form->submit(''); + + $violations = $this->validator->validate($form); + + $this->assertCount(1, $violations); + $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); + $this->assertSame('data', $violations[0]->getPropertyPath()); + } + + public function testCompositeConstraintValidatedInEachGroup() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'constraints' => [ + new Collection([ + 'field1' => new NotBlank([ + 'groups' => ['field1'], + ]), + 'field2' => new NotBlank([ + 'groups' => ['field2'], + ]), + ]), + ], + 'validation_groups' => ['field1', 'field2'], + ]); + $form->add('field1'); + $form->add('field2'); + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(2, $violations); + $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); + $this->assertSame('data[field1]', $violations[0]->getPropertyPath()); + $this->assertSame('This value should not be blank.', $violations[1]->getMessage()); + $this->assertSame('data[field2]', $violations[1]->getPropertyPath()); + } + + public function testCompositeConstraintValidatedInSequence() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'constraints' => [ + new Collection([ + 'field1' => new NotBlank([ + 'groups' => ['field1'], + ]), + 'field2' => new NotBlank([ + 'groups' => ['field2'], + ]), + ]), + ], + 'validation_groups' => new GroupSequence(['field1', 'field2']), + ]); + $form->add('field1'); + $form->add('field2'); + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(1, $violations); + $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); + $this->assertSame('data[field1]', $violations[0]->getPropertyPath()); + } + + public function testFieldsValidateInSequence() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => new GroupSequence(['group1', 'group2']), + ]) + ->add('foo', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + ]) + ->add('bar', TextType::class, [ + 'constraints' => [new NotBlank(['groups' => ['group2']])], + ]) + ; + + $form->submit(['foo' => 'invalid', 'bar' => null]); + + $errors = $form->getErrors(true); + + $this->assertCount(1, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + } + + public function testFieldsValidateInSequenceWithNestedGroupsArray() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']), + ]) + ->add('foo', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + ]) + ->add('bar', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])], + ]) + ->add('baz', TextType::class, [ + 'constraints' => [new NotBlank(['groups' => ['group3']])], + ]) + ; + + $form->submit(['foo' => 'invalid', 'bar' => 'invalid', 'baz' => null]); + + $errors = $form->getErrors(true); + + $this->assertCount(2, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + $this->assertInstanceOf(Length::class, $errors[1]->getCause()->getConstraint()); + } + + public function testConstraintsInDifferentGroupsOnSingleField() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => new GroupSequence(['group1', 'group2']), + ]) + ->add('foo', TextType::class, [ + 'constraints' => [ + new NotBlank([ + 'groups' => ['group1'], + ]), + new Length([ + 'groups' => ['group2'], + 'max' => 3, + ]), + ], + ]); + $form->submit([ + 'foo' => 'test@example.com', + ]); + + $errors = $form->getErrors(true); + + $this->assertFalse($form->isValid()); + $this->assertCount(1, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + } + + public function testCascadeValidationToChildFormsUsingPropertyPaths() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => ['group1', 'group2'], + ]) + ->add('field1', null, [ + 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'property_path' => '[foo]', + ]) + ->add('field2', null, [ + 'constraints' => [new NotBlank(['groups' => 'group2'])], + 'property_path' => '[bar]', + ]) + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(2, $violations); + $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); + $this->assertSame('children[field1].data', $violations[0]->getPropertyPath()); + $this->assertSame('This value should not be blank.', $violations[1]->getMessage()); + $this->assertSame('children[field2].data', $violations[1]->getPropertyPath()); + } + + public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSequence() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => new GroupSequence(['group1', 'group2']), + ]) + ->add('field1', null, [ + 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'property_path' => '[foo]', + ]) + ->add('field2', null, [ + 'constraints' => [new NotBlank(['groups' => 'group2'])], + 'property_path' => '[bar]', + ]) + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(1, $violations); + $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); + $this->assertSame('children[field1].data', $violations[0]->getPropertyPath()); + } +} + +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/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 927dd64f52071..f789fbe1e408d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -25,7 +25,6 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\Translation\IdentityTranslator; -use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; @@ -704,151 +703,6 @@ public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint() $this->assertSame($constraint, $context->getViolations()->get(0)->getConstraint()); } - public function testNonCompositeConstraintValidatedOnce() - { - $form = $this - ->getBuilder('form', null, [ - 'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])], - 'validation_groups' => ['foo', 'bar'], - ]) - ->setCompound(false) - ->getForm(); - $form->submit(''); - - $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); - - $this->assertCount(1, $context->getViolations()); - $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); - $this->assertSame('data', $context->getViolations()[0]->getPropertyPath()); - } - - public function testCompositeConstraintValidatedInEachGroup() - { - $form = $this->getBuilder('form', null, [ - 'constraints' => [ - new Collection([ - 'field1' => new NotBlank([ - 'groups' => ['field1'], - ]), - 'field2' => new NotBlank([ - 'groups' => ['field2'], - ]), - ]), - ], - 'validation_groups' => ['field1', 'field2'], - ]) - ->setData([]) - ->setCompound(true) - ->setDataMapper(new PropertyPathMapper()) - ->getForm(); - $form->add($this->getForm('field1')); - $form->add($this->getForm('field2')); - $form->submit([ - 'field1' => '', - 'field2' => '', - ]); - - $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); - - $this->assertCount(2, $context->getViolations()); - $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); - $this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath()); - $this->assertSame('This value should not be blank.', $context->getViolations()[1]->getMessage()); - $this->assertSame('data[field2]', $context->getViolations()[1]->getPropertyPath()); - } - - public function testCompositeConstraintValidatedInSequence() - { - $form = $this->getCompoundForm([], [ - 'constraints' => [ - new Collection([ - 'field1' => new NotBlank([ - 'groups' => ['field1'], - ]), - 'field2' => new NotBlank([ - 'groups' => ['field2'], - ]), - ]), - ], - 'validation_groups' => new GroupSequence(['field1', 'field2']), - ]) - ->add($this->getForm('field1')) - ->add($this->getForm('field2')) - ; - - $form->submit([ - 'field1' => '', - 'field2' => '', - ]); - - $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); - - $this->assertCount(1, $context->getViolations()); - $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); - $this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath()); - } - - public function testCascadeValidationToChildFormsUsingPropertyPaths() - { - $form = $this->getCompoundForm([], [ - 'validation_groups' => ['group1', 'group2'], - ]) - ->add('field1', null, [ - 'constraints' => [new NotBlank(['groups' => 'group1'])], - 'property_path' => '[foo]', - ]) - ->add('field2', null, [ - 'constraints' => [new NotBlank(['groups' => 'group2'])], - 'property_path' => '[bar]', - ]) - ; - - $form->submit([ - 'field1' => '', - 'field2' => '', - ]); - - $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); - - $this->assertCount(2, $context->getViolations()); - $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); - $this->assertSame('children[field1].data', $context->getViolations()[0]->getPropertyPath()); - $this->assertSame('This value should not be blank.', $context->getViolations()[1]->getMessage()); - $this->assertSame('children[field2].data', $context->getViolations()[1]->getPropertyPath()); - } - - public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSequence() - { - $form = $this->getCompoundForm([], [ - 'validation_groups' => new GroupSequence(['group1', 'group2']), - ]) - ->add('field1', null, [ - 'constraints' => [new NotBlank(['groups' => 'group1'])], - 'property_path' => '[foo]', - ]) - ; - - $form->submit([ - 'field1' => '', - ]); - - $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); - - $this->assertCount(1, $context->getViolations()); - $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); - $this->assertSame('children[field1].data', $context->getViolations()[0]->getPropertyPath()); - } - protected function createValidator() { return new FormValidator(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php index 9793bd78e69e7..4a12acf4126b4 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -12,23 +12,12 @@ namespace Symfony\Component\Form\Tests\Extension\Validator; use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\Core\Type\TextType; 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\GroupSequence; -use Symfony\Component\Validator\Constraints\Length; -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; @@ -57,151 +46,4 @@ public function test2Dot5ValidationApi() $this->assertSame(TraversalStrategy::NONE, $metadata->traversalStrategy); $this->assertCount(0, $metadata->getPropertyMetadata('children')); } - - 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()); - } - - public function testFieldsValidateInSequence() - { - $form = $this->createForm(FormType::class, null, [ - 'validation_groups' => new GroupSequence(['group1', 'group2']), - ]) - ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], - ]) - ->add('bar', TextType::class, [ - 'constraints' => [new NotBlank(['groups' => ['group2']])], - ]) - ; - - $form->submit(['foo' => 'invalid', 'bar' => null]); - - $errors = $form->getErrors(true); - - $this->assertCount(1, $errors); - $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); - } - - public function testFieldsValidateInSequenceWithNestedGroupsArray() - { - $form = $this->createForm(FormType::class, null, [ - 'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']), - ]) - ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], - ]) - ->add('bar', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])], - ]) - ->add('baz', TextType::class, [ - 'constraints' => [new NotBlank(['groups' => ['group3']])], - ]) - ; - - $form->submit(['foo' => 'invalid', 'bar' => 'invalid', 'baz' => null]); - - $errors = $form->getErrors(true); - - $this->assertCount(2, $errors); - $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); - $this->assertInstanceOf(Length::class, $errors[1]->getCause()->getConstraint()); - } - - public function testConstraintsInDifferentGroupsOnSingleField() - { - $form = $this->createForm(FormType::class, null, [ - 'validation_groups' => new GroupSequence(['group1', 'group2']), - ]) - ->add('foo', TextType::class, [ - 'constraints' => [ - new NotBlank([ - 'groups' => ['group1'], - ]), - new Length([ - 'groups' => ['group2'], - 'max' => 3, - ]), - ], - ]); - $form->submit([ - 'foo' => 'test@example.com', - ]); - - $errors = $form->getErrors(true); - - $this->assertFalse($form->isValid()); - $this->assertCount(1, $errors); - $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); - } - - private function createForm($type, $data = null, array $options = []) - { - $validator = Validation::createValidatorBuilder() - ->setMetadataFactory(new LazyLoadingMetadataFactory(new StaticMethodLoader())) - ->getValidator(); - $formFactoryBuilder = new FormFactoryBuilder(); - $formFactoryBuilder->addExtension(new ValidatorExtension($validator)); - $formFactory = $formFactoryBuilder->getFormFactory(); - - return $formFactory->create($type, $data, $options); - } -} - -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); - } } From ee752f90ed036cd535db19ab563b9af71df535c8 Mon Sep 17 00:00:00 2001 From: Paulo Ribeiro Date: Mon, 8 Jun 2020 20:42:00 -0300 Subject: [PATCH 32/46] [Mailer] added the reply-to addresses to the API SES transport request. The transport was not sending the reply-to addresses to the SES API. --- .../Mailer/Bridge/Amazon/Transport/SesApiTransport.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php index 7295fdf79a5a9..0bd5627ac9bd1 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php @@ -113,6 +113,9 @@ private function getPayload(Email $email, Envelope $envelope): array if ($email->getHtmlBody()) { $payload['Message.Body.Html.Data'] = $email->getHtmlBody(); } + if ($email->getReplyTo()) { + $payload['ReplyToAddresses.member'] = $this->stringifyAddresses($email->getReplyTo()); + } return $payload; } From 52161f35c7694a9e87efed99cff669868aad2748 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 10 Jun 2020 07:55:43 +0200 Subject: [PATCH 33/46] [Mailer] Remove an internal annot --- src/Symfony/Component/Mailer/Messenger/SendEmailMessage.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Symfony/Component/Mailer/Messenger/SendEmailMessage.php b/src/Symfony/Component/Mailer/Messenger/SendEmailMessage.php index 0472c36b6209a..b06ac839c64f7 100644 --- a/src/Symfony/Component/Mailer/Messenger/SendEmailMessage.php +++ b/src/Symfony/Component/Mailer/Messenger/SendEmailMessage.php @@ -22,9 +22,6 @@ class SendEmailMessage private $message; private $envelope; - /** - * @internal - */ public function __construct(RawMessage $message, Envelope $envelope = null) { $this->message = $message; From cb8f12996c6889ebf8d8e5ed4718fca90f7fb21c Mon Sep 17 00:00:00 2001 From: Arkadius Stefanski Date: Tue, 9 Jun 2020 20:51:18 +0200 Subject: [PATCH 34/46] [Ldap] fix refreshUser() ignoring extra_fields --- .../Component/Ldap/Security/LdapUserProvider.php | 2 +- .../Ldap/Tests/Security/LdapUserProviderTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php index fa37e6d7baa3a..cf7e9b39f2bec 100644 --- a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php +++ b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php @@ -108,7 +108,7 @@ public function refreshUser(UserInterface $user) throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); } - return new LdapUser($user->getEntry(), $user->getUsername(), $user->getPassword(), $user->getRoles()); + return new LdapUser($user->getEntry(), $user->getUsername(), $user->getPassword(), $user->getRoles(), $user->getExtraFields()); } /** diff --git a/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php b/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php index 8d0a7a3517584..a2e888077cde8 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php @@ -330,4 +330,14 @@ public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute() $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword', ['email']); $this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo')); } + + public function testRefreshUserShouldReturnUserWithSameProperties() + { + $ldap = $this->createMock(LdapInterface::class); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword', ['email']); + + $user = new LdapUser(new Entry('foo'), 'foo', 'bar', ['ROLE_DUMMY'], ['email' => 'foo@symfony.com']); + + $this->assertEquals($user, $provider->refreshUser($user)); + } } From ff05be06ec112d406bc4428e94cdc3de5b59f8a9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 10 Jun 2020 17:33:47 +0200 Subject: [PATCH 35/46] [HttpClient] fix offset computation for data chunks --- src/Symfony/Component/HttpClient/Response/ResponseTrait.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php index 80894ffb01030..8d4fe59ae6872 100644 --- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php @@ -359,8 +359,9 @@ public static function stream(iterable $responses, float $timeout = null): \Gene continue; } - $response->offset += \strlen($chunk); + $chunkLen = \strlen($chunk); $chunk = new DataChunk($response->offset, $chunk); + $response->offset += $chunkLen; } elseif (null === $chunk) { $e = $multi->handlesActivity[$j][0]; unset($responses[$j], $multi->handlesActivity[$j]); From da0e2c36ef7aa7ee0ec45b5ca64d009db68d7c47 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 10 Jun 2020 18:10:45 +0200 Subject: [PATCH 36/46] [DependencyInjection][CheckTypeDeclarationsPass] Always resolve parameters --- .../Compiler/CheckTypeDeclarationsPass.php | 3 +- .../CheckTypeDeclarationsPassTest.php | 30 ++++++++++--------- .../BarMethodCall.php | 4 +++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index bad2624529138..c15932b06cb45 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -198,8 +198,7 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar } } elseif (\is_string($value)) { if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { - // Only array parameters are not inlined when dumped. - $value = []; + $value = $this->container->getParameter(substr($value, 1, -1)); } elseif ($envPlaceholderUniquePrefix && false !== strpos($value, 'env_')) { // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it. // We don't need to change the value because it is already a string. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index 9524c7a4f61bd..18e06b3d29480 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -612,20 +612,6 @@ public function testProcessThrowsOnIterableTypeWhenScalarPassed() $this->assertInstanceOf(\stdClass::class, $container->get('bar')->foo); } - public function testProcessResolveArrayParameters() - { - $container = new ContainerBuilder(); - $container->setParameter('ccc', ['foobar']); - - $container - ->register('foobar', BarMethodCall::class) - ->addMethodCall('setArray', ['%ccc%']); - - (new CheckTypeDeclarationsPass(true))->process($container); - - $this->addToAssertionCount(1); - } - public function testProcessResolveExpressions() { $container = new ContainerBuilder(); @@ -791,4 +777,20 @@ public function testExpressionLanguageWithSyntheticService() $this->addToAssertionCount(1); } + + public function testProcessResolveParameters() + { + $container = new ContainerBuilder(); + $container->setParameter('array_param', ['foobar']); + $container->setParameter('string_param', 'ccc'); + + $container + ->register('foobar', BarMethodCall::class) + ->addMethodCall('setArray', ['%array_param%']) + ->addMethodCall('setString', ['%string_param%']); + + (new CheckTypeDeclarationsPass(true))->process($container); + + $this->addToAssertionCount(1); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/BarMethodCall.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/BarMethodCall.php index 69f1a693a4c5b..65437a63ec743 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/BarMethodCall.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/BarMethodCall.php @@ -44,4 +44,8 @@ public function setCallable(callable $callable): void public function setClosure(\Closure $closure): void { } + + public function setString(string $string) + { + } } From d179d71f456ded55e75e627db7ef46170f275888 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 11 Jun 2020 14:32:28 +0200 Subject: [PATCH 37/46] Remove non-existing arg and param from serializer service config --- .../Bundle/FrameworkBundle/Resources/config/serializer.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml index 0dbc388ddffcb..c3eea28b8c2b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml @@ -6,7 +6,6 @@ %kernel.cache_dir%/serialization.php - @@ -97,7 +96,6 @@ - null From 176e769e5f7422a510c95aac9c2d26aff2692331 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Wed, 10 Jun 2020 08:28:31 +0000 Subject: [PATCH 38/46] [HttpKernel] Fix regression where Store does not return response body correctly --- .../Component/HttpKernel/HttpCache/Store.php | 41 ++++++++++++------- .../HttpKernel/Tests/HttpCache/StoreTest.php | 33 +++++++++++++++ 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index fd04a7b23d1d3..72793f582df85 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -152,8 +152,8 @@ public function lookup(Request $request) } $headers = $match[1]; - if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) { - return $this->restoreResponse($headers, $body); + if (file_exists($path = $this->getPath($headers['x-content-digest'][0]))) { + return $this->restoreResponse($headers, $path); } // TODO the metaStore referenced an entity that doesn't exist in @@ -177,15 +177,28 @@ public function write(Request $request, Response $response) $key = $this->getCacheKey($request); $storedEnv = $this->persistRequest($request); - $digest = $this->generateContentDigest($response); - $response->headers->set('X-Content-Digest', $digest); + if ($response->headers->has('X-Body-File')) { + // Assume the response came from disk, but at least perform some safeguard checks + if (!$response->headers->has('X-Content-Digest')) { + throw new \RuntimeException('A restored response must have the X-Content-Digest header.'); + } - if (!$this->save($digest, $response->getContent(), false)) { - throw new \RuntimeException('Unable to store the entity.'); - } + $digest = $response->headers->get('X-Content-Digest'); + if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) { + throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.'); + } + // Everything seems ok, omit writing content to disk + } else { + $digest = $this->generateContentDigest($response); + $response->headers->set('X-Content-Digest', $digest); - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); + if (!$this->save($digest, $response->getContent(), false)) { + throw new \RuntimeException('Unable to store the entity.'); + } + + if (!$response->headers->has('Transfer-Encoding')) { + $response->headers->set('Content-Length', \strlen($response->getContent())); + } } // read existing cache entries, remove non-varying, and add this one to the list @@ -477,19 +490,19 @@ private function persistResponse(Response $response) * Restores a Response from the HTTP headers and body. * * @param array $headers An array of HTTP headers for the Response - * @param string $body The Response body + * @param string $path Path to the Response body * * @return Response */ - private function restoreResponse($headers, $body = null) + private function restoreResponse($headers, $path = null) { $status = $headers['X-Status'][0]; unset($headers['X-Status']); - if (null !== $body) { - $headers['X-Body-File'] = [$body]; + if (null !== $path) { + $headers['X-Body-File'] = [$path]; } - return new Response($body, $status, $headers); + return new Response($path, $status, $headers); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 07c41542697e3..6754be45a13aa 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -118,6 +118,39 @@ public function testWritesResponseEvenIfXContentDigestIsPresent() $this->assertNotNull($response); } + public function testWritingARestoredResponseDoesNotCorruptCache() + { + /* + * This covers the regression reported in https://github.com/symfony/symfony/issues/37174. + * + * A restored response does *not* load the body, but only keep the file path in a special X-Body-File + * header. For reasons (?), the file path was also used as the restored response body. + * It would be up to others (HttpCache...?) to hohor this header and actually load the response content + * from there. + * + * When a restored response was stored again, the Store itself would ignore the header. In the first + * step, this would compute a new Content Digest based on the file path in the restored response body; + * this is covered by "Checkpoint 1" below. But, since the X-Body-File header was left untouched (Checkpoint 2), downstream + * code (HttpCache...) would not immediately notice. + * + * Only upon performing the lookup for a second time, we'd get a Response where the (wrong) Content Digest + * is also reflected in the X-Body-File header, this time also producing wrong content when the downstream + * evaluates it. + */ + $this->store->write($this->request, $this->response); + $digest = $this->response->headers->get('X-Content-Digest'); + $path = $this->getStorePath($digest); + + $response = $this->store->lookup($this->request); + $this->store->write($this->request, $response); + $this->assertEquals($digest, $response->headers->get('X-Content-Digest')); // Checkpoint 1 + $this->assertEquals($path, $response->headers->get('X-Body-File')); // Checkpoint 2 + + $response = $this->store->lookup($this->request); + $this->assertEquals($digest, $response->headers->get('X-Content-Digest')); + $this->assertEquals($path, $response->headers->get('X-Body-File')); + } + public function testFindsAStoredEntryWithLookup() { $this->storeSimpleEntry(); From 816b6ea6f195cf808932c6def5d70a674165021b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 11 Jun 2020 15:00:25 +0200 Subject: [PATCH 39/46] Fix typo --- src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 6754be45a13aa..eee8970b968c6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -125,7 +125,7 @@ public function testWritingARestoredResponseDoesNotCorruptCache() * * A restored response does *not* load the body, but only keep the file path in a special X-Body-File * header. For reasons (?), the file path was also used as the restored response body. - * It would be up to others (HttpCache...?) to hohor this header and actually load the response content + * It would be up to others (HttpCache...?) to honor this header and actually load the response content * from there. * * When a restored response was stored again, the Store itself would ignore the header. In the first From 2d781ddce67d6c04e564946ded1d484e54c65d9c Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 11 Jun 2020 23:52:31 +0200 Subject: [PATCH 40/46] fix test checking non-existing arg --- .../Tests/DependencyInjection/FrameworkExtensionTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 9a8fc0776f0af..3e6591a75b8e7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -1204,7 +1204,6 @@ public function testSerializerEnabled() $this->assertCount(2, $argument); $this->assertEquals('Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', $argument[0]->getClass()); - $this->assertNull($container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1)); $this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.name_converter.metadata_aware')->getArgument(1)); $this->assertEquals(new Reference('property_info', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $container->getDefinition('serializer.normalizer.object')->getArgument(3)); $this->assertArrayHasKey('circular_reference_handler', $container->getDefinition('serializer.normalizer.object')->getArgument(6)); From d75ec21cdbf38136a1368f664183e70bb28a6fbe Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Fri, 12 Jun 2020 02:09:24 +0200 Subject: [PATCH 41/46] remove unused param from validator service config --- .../Bundle/FrameworkBundle/Resources/config/validator.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index f2d0e9e2a603b..886132ff4b1c8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -5,7 +5,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> - %kernel.cache_dir%/validation.php From 38135de549c78c09cac00c0ee5a6494a8a8805f8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 4 Jun 2020 21:54:20 +0200 Subject: [PATCH 42/46] switch the context when validating nested forms --- .../Validator/Constraints/FormValidator.php | 2 + .../FormValidatorFunctionalTest.php | 46 +++++++++++++++++++ src/Symfony/Component/Form/composer.json | 3 +- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 6811dceb9832a..4447b2e54aa88 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -90,6 +90,7 @@ public function validate($form, Constraint $formConstraint) // in different steps without breaking early enough $this->resolvedGroups[$field] = (array) $group; $fieldFormConstraint = new Form(); + $this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath()); $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint); } } @@ -129,6 +130,7 @@ public function validate($form, Constraint $formConstraint) if ($field->isSubmitted()) { $this->resolvedGroups[$field] = $groups; $fieldFormConstraint = new Form(); + $this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath()); $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php index 1cf1199f71732..b51b34bb32ab0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php @@ -21,6 +21,7 @@ use Symfony\Component\Form\Test\ForwardCompatTestTrait; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; @@ -283,6 +284,51 @@ public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSe $this->assertSame('This value should not be blank.', $violations[0]->getMessage()); $this->assertSame('children[field1].data', $violations[0]->getPropertyPath()); } + + public function testContextIsPopulatedWithFormBeingValidated() + { + $form = $this->formFactory->create(FormType::class) + ->add('field1', null, [ + 'constraints' => [new Expression([ + 'expression' => '!this.getParent().get("field2").getData()', + ])], + ]) + ->add('field2') + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(0, $violations); + } + + public function testContextIsPopulatedWithFormBeingValidatedUsingGroupSequence() + { + $form = $this->formFactory->create(FormType::class, null, [ + 'validation_groups' => new GroupSequence(['group1']), + ]) + ->add('field1', null, [ + 'constraints' => [new Expression([ + 'expression' => '!this.getParent().get("field2").getData()', + 'groups' => ['group1'], + ])], + ]) + ->add('field2') + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $violations = $this->validator->validate($form); + + $this->assertCount(0, $violations); + } } class Foo diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 161994a672609..c69ac107bd8c7 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -26,9 +26,10 @@ }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^3.2.5|~4.0", + "symfony/validator": "^3.4.3|^4.0.3", "symfony/dependency-injection": "~3.3|~4.0", "symfony/config": "~2.7|~3.0|~4.0", + "symfony/expression-language": "~3.4|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/http-kernel": "^3.3.5|~4.0", "symfony/security-csrf": "^2.8.31|^3.3.13|~4.0", From dac3c8fae8029d7bbf9c7645cfa16a483ac53790 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 11 Jun 2020 19:27:38 +0200 Subject: [PATCH 43/46] [DependencyInjection][CheckTypeDeclarationsPass] Handle unresolved parameters pointing to environment variables --- .../Compiler/CheckTypeDeclarationsPass.php | 4 +++- .../Compiler/CheckTypeDeclarationsPassTest.php | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index c15932b06cb45..cf255640c2258 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -199,7 +199,9 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar } elseif (\is_string($value)) { if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { $value = $this->container->getParameter(substr($value, 1, -1)); - } elseif ($envPlaceholderUniquePrefix && false !== strpos($value, 'env_')) { + } + + if ($envPlaceholderUniquePrefix && \is_string($value) && false !== strpos($value, 'env_')) { // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it. // We don't need to change the value because it is already a string. if ('' === preg_replace('/'.$envPlaceholderUniquePrefix.'_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index 18e06b3d29480..0842f2687968a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -780,17 +780,27 @@ public function testExpressionLanguageWithSyntheticService() public function testProcessResolveParameters() { - $container = new ContainerBuilder(); + putenv('ARRAY={"foo":"bar"}'); + + $container = new ContainerBuilder(new EnvPlaceholderParameterBag([ + 'env_array_param' => '%env(json:ARRAY)%', + ])); $container->setParameter('array_param', ['foobar']); $container->setParameter('string_param', 'ccc'); - $container - ->register('foobar', BarMethodCall::class) + $definition = $container->register('foobar', BarMethodCall::class); + $definition ->addMethodCall('setArray', ['%array_param%']) ->addMethodCall('setString', ['%string_param%']); + (new ResolveParameterPlaceHoldersPass())->process($container); + + $definition->addMethodCall('setArray', ['%env_array_param%']); + (new CheckTypeDeclarationsPass(true))->process($container); $this->addToAssertionCount(1); + + putenv('ARRAY='); } } From 6304b6b11a32fc950b87ec536e3ee758c442660b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 12 Jun 2020 10:25:05 +0200 Subject: [PATCH 44/46] fix merge --- src/Symfony/Component/Form/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index ca855983927ab..283fff0c10812 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -29,6 +29,7 @@ "doctrine/collections": "~1.0", "symfony/validator": "^3.4.31|^4.3.4|^5.0", "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/expression-language": "^3.4|^4.0|^5.0", "symfony/config": "^3.4|^4.0|^5.0", "symfony/console": "^4.3|^5.0", "symfony/http-foundation": "^3.4|^4.0|^5.0", From 6199cf12b105d66193d4340df74f5081cfc70d7d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 12 Jun 2020 13:15:31 +0200 Subject: [PATCH 45/46] updated CHANGELOG for 4.4.10 --- CHANGELOG-4.4.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md index 20f38b3422f1f..2f51e38874c8f 100644 --- a/CHANGELOG-4.4.md +++ b/CHANGELOG-4.4.md @@ -7,6 +7,28 @@ in 4.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/v4.4.0...v4.4.1 +* 4.4.10 (2020-06-12) + + * bug #37227 [DependencyInjection][CheckTypeDeclarationsPass] Handle unresolved parameters pointing to environment variables (fancyweb) + * bug #37103 [Form] switch the context when validating nested forms (xabbuh) + * bug #37182 [HttpKernel] Fix regression where Store does not return response body correctly (mpdude) + * bug #37193 [DependencyInjection][CheckTypeDeclarationsPass] Always resolve parameters (fancyweb) + * bug #37191 [HttpClient] fix offset computation for data chunks (nicolas-grekas) + * bug #37177 [Ldap] fix refreshUser() ignoring extra_fields (arkste) + * bug #37181 [Mailer] Remove an internal annot (fabpot) + * bug #36913 [FrameworkBundle] fix type annotation on ControllerTrait::addFlash() (ThomasLandauer) + * bug #37162 [Mailer] added the reply-to addresses to the API SES transport request. (ribeiropaulor) + * bug #37167 [Mime] use fromString when creating a new Address (fabpot) + * bug #37169 [Cache] fix forward compatibility with Doctrine DBAL 3 (xabbuh) + * bug #37159 [Mailer] Fixed generator bug when creating multiple transports using Transport::fromDsn (atailouloute) + * bug #37048 [HttpClient] fix monitoring timeouts when other streams are active (nicolas-grekas) + * bug #37085 [Form] properly cascade validation to child forms (xabbuh) + * bug #37095 [PhpUnitBridge] Fix undefined index when output of "composer show" cannot be parsed (nicolas-grekas) + * bug #37092 [PhpUnitBridge] fix undefined var on version 3.4 (nicolas-grekas) + * bug #37065 [HttpClient] Throw JsonException instead of TransportException on empty response in Response::toArray() (jeroennoten) + * bug #37077 [WebProfilerBundle] Move ajax clear event listener initialization on loadToolbar (Bruno BOUTAREL) + * bug #37049 [Serializer] take into account the context when preserving empty array objects (xabbuh) + * 4.4.9 (2020-05-31) * bug #37008 [Security] Fixed AbstractToken::hasUserChanged() (wouterj) From e71a9ff2281a003753dbfc7f58d89b4f9a4a4bc7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 12 Jun 2020 13:15:37 +0200 Subject: [PATCH 46/46] updated VERSION for 4.4.10 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f0a2ee8d29734..25e8202cdb997 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '4.4.10-DEV'; + const VERSION = '4.4.10'; const VERSION_ID = 40410; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; const RELEASE_VERSION = 10; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023';