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'; pFad - Phonifier reborn

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

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy