diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml
index 9c126e2ef2422..c5c9bfecf4d09 100644
--- a/.github/workflows/psalm.yml
+++ b/.github/workflows/psalm.yml
@@ -52,5 +52,4 @@ jobs:
- name: Psalm
run: |
- ./vendor/bin/psalm.phar --no-progress
- ./vendor/bin/psalm.phar --output-format=github --no-progress
+ ./vendor/bin/psalm.phar --no-progress || ./vendor/bin/psalm.phar --output-format=github --no-progress
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 430d67c4c8cda..1eefe6f5583c6 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -15,18 +15,18 @@ jobs:
runs-on: Ubuntu-20.04
env:
- extensions: amqp,apcu,igbinary,intl,mbstring,memcached,mongodb,redis
+ extensions: amqp,apcu,igbinary,intl,mbstring,memcached,mongodb,redis-5.3.4
strategy:
matrix:
include:
- php: '7.2'
- - php: '8.0'
+ - php: '8.1'
- php: '7.4'
mode: high-deps
- php: '8.0'
mode: low-deps
- - php: '8.1'
+ - php: '8.2'
mode: experimental
fail-fast: false
@@ -36,11 +36,10 @@ jobs:
with:
fetch-depth: 2
- - name: Configure for PHP 8.1
- if: "${{ matrix.php == '8.1' }}"
+ - name: Configure for PHP >= 8.2
+ if: "${{ matrix.php >= '8.2' }}"
run: |
- echo "extensions=mbstring" >> $GITHUB_ENV
- composer config platform.php 8.0.99
+ composer config platform.php 8.1.99
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -136,7 +135,7 @@ jobs:
echo "::endgroup::"
- name: Patch return types
- if: "${{ matrix.php == '8.0' && ! matrix.mode }}"
+ if: "${{ matrix.php == '8.1' && ! matrix.mode }}"
run: |
sed -i 's/"\*\*\/Tests\/"//' composer.json
composer install -q --optimize-autoloader
diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md
index 2067112f91c93..cd2318c54c47e 100644
--- a/CHANGELOG-4.4.md
+++ b/CHANGELOG-4.4.md
@@ -7,6 +7,27 @@ 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.31 (2021-09-28)
+
+ * bug #43158 [Cache] Fix invalidating tags on Redis <5 (wouterj)
+ * bug #43179 [Ldap] Fix `resource` type checks & docblocks on PHP 8.1 (chalasr)
+ * bug #43137 [FrameworkBundle] Avoid secrets:decrypt-to-local command to fail (noniagriconomie)
+ * bug #43171 [VarDumper] fix dumping typed references from properties (nicolas-grekas)
+ * bug #43124 [Messenger] [Redis] Allow authentication with user and password (GaryPEGEOT)
+ * bug #39350 [FrameworkBundle] Remove translation data_collector BEFORE adding it to profiler (l-vo)
+ * bug #43115 [DependencyInjection] Fix iterator in ServiceConfigurator (jderusse)
+ * bug #43031 [Form] Do not trim unassigned unicode characters (simonberger)
+ * bug #43058 [WebProfilerBundle] Fix displaying certain configs (HypeMC)
+ * bug #43022 [PhpUnitBridge] Track unsilenced deprecations only for userland (nicolas-grekas)
+ * bug #42976 [Mime] Allow array as input for RawMessage (derrabus)
+ * bug #42098 [PropertyInfo] Support for intersection types (derrabus)
+ * bug #42904 [Cache] Make sure PdoAdapter::prune() always returns a bool (derrabus)
+ * bug #42896 [HttpClient] Fix handling timeouts when responses are destructed (nicolas-grekas)
+ * bug #42835 [Cache] Fix implicit float to int cast (derrabus)
+ * bug #42831 [Mime] Update mime types (fabpot)
+ * bug #42830 [HttpKernel] Fix empty timeline in profiler (nicodmf)
+ * bug #42819 Fix tests failing with DBAL 3 (derrabus)
+
* 4.4.30 (2021-08-30)
* bug #42753 Cast ini_get to an integer to match expected type (natewiebe13)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index f804602f54457..507ca7e28d68b 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -7,16 +7,16 @@ The Symfony Connect username in parenthesis allows to get more information
- Fabien Potencier (fabpot)
- Nicolas Grekas (nicolas-grekas)
- Christian Flothmann (xabbuh)
- - Bernhard Schussek (bschussek)
- Alexander M. Turek (derrabus)
+ - Bernhard Schussek (bschussek)
- Tobias Schultze (tobion)
- Robin Chalas (chalas_r)
- Christophe Coevoet (stof)
- Wouter De Jong (wouterj)
- Jérémy DERUSSÉ (jderusse)
- Maxime Steinhausser (ogizanagi)
- - Kévin Dunglas (dunglas)
- Grégoire Pineau (lyrixx)
+ - Kévin Dunglas (dunglas)
- Jordi Boggiano (seldaek)
- Victor Berchet (victor)
- Javier Eguiluz (javier.eguiluz)
@@ -66,8 +66,8 @@ The Symfony Connect username in parenthesis allows to get more information
- stealth35 (stealth35)
- Alexander Mols (asm89)
- Titouan Galopin (tgalopin)
- - Vasilij Dusko | CREATION
- Laurent VOULLEMIER (lvo)
+ - Vasilij Dusko | CREATION
- Bulat Shakirzyanov (avalanche123)
- David Maicher (dmaicher)
- gadelat (gadelat)
@@ -81,17 +81,17 @@ The Symfony Connect username in parenthesis allows to get more information
- Konstantin Kudryashov (everzet)
- Vladimir Reznichenko (kalessil)
- Bilal Amarni (bamarni)
+ - Jérôme Tamarelle (gromnan)
- Florin Patan (florinpatan)
- Jáchym Toušek (enumag)
- - Jérôme Tamarelle (gromnan)
- Alex Pott
- Michel Weimerskirch (mweimerskirch)
- Andrej Hudec (pulzarraider)
- Christian Raue
- Issei Murasawa (issei_m)
+ - Antoine M (amakdessi)
- Eric Clemmons (ericclemmons)
- Charles Sarrazin (csarrazi)
- - Antoine M (amakdessi)
- Vasilij Dusko
- Douglas Greenshields (shieldo)
- Graham Campbell (graham)
@@ -107,18 +107,18 @@ The Symfony Connect username in parenthesis allows to get more information
- Brandon Turner
- Luis Cordova (cordoval)
- Daniel Holmes (dholmes)
+ - Alexander Schranz (alexander-schranz)
- Sebastiaan Stok (sstok)
- Toni Uebernickel (havvg)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- John Wards (johnwards)
- - Alexander Schranz (alexander-schranz)
- Baptiste Clavié (talus)
- Antoine Hérault (herzult)
- Paráda József (paradajozsef)
+ - Vincent Langlet (deviling)
- Arnaud Le Blanc (arnaud-lb)
- Przemysław Bogusz (przemyslaw-bogusz)
- - Vincent Langlet (deviling)
- Maxime STEINHAUSSER
- Tomas Norkūnas (norkunas)
- Michal Piotrowski (eventhorizon)
@@ -126,13 +126,13 @@ The Symfony Connect username in parenthesis allows to get more information
- Massimiliano Arione (garak)
- Mathias Arlaud (mtarld)
- Tim Nagel (merk)
+ - HypeMC (hypemc)
- Chris Wilkinson (thewilkybarkid)
- Peter Kokot (maastermedia)
- Lars Strojny (lstrojny)
- Brice BERNARD (brikou)
- Ahmed TAILOULOUTE (ahmedtai)
- Gregor Harlan (gharlan)
- - HypeMC (hypemc)
- marc.weistroff
- lenar
- Alexander Schwenn (xelaris)
@@ -148,6 +148,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Théo FIDRY (theofidry)
- Florian Voutzinos (florianv)
- Teoh Han Hui (teohhanhui)
+ - Alexandre Daubois (alexandre-daubois)
- Colin Frei
- Javier Spagnoletti (phansys)
- Joshua Thijssen
@@ -156,26 +157,26 @@ The Symfony Connect username in parenthesis allows to get more information
- excelwebzone
- Gordon Franke (gimler)
- Saif Eddin Gmati (azjezz)
- - Alexandre Daubois (alexandre-daubois)
+ - Richard van Laak (rvanlaak)
- Jesse Rushlow (geeshoe)
- Fabien Pennequin (fabienpennequin)
+ - Mathieu Santostefano (welcomattic)
- Olivier Dolbeau (odolbeau)
- Smaine Milianni (ismail1432)
- - Richard van Laak (rvanlaak)
- Eric GELOEN (gelo)
+ - Gary PEGEOT (gary-p)
- Matthieu Napoli (mnapoli)
+ - Maxime Helias (maxhelias)
- Jannik Zschiesche (apfelbox)
- - Mathieu Santostefano (welcomattic)
- Robert Schönthal (digitalkaoz)
- Florian Lonqueu-Brochard (florianlb)
- Tigran Azatyan (tigranazatyan)
- YaFou
- - Gary PEGEOT (gary-p)
- Gabriel Caruso (carusogabriel)
+ - Ruud Kamphuis (ruudk)
- Stefano Sala (stefano.sala)
- Andréia Bohner (andreia)
- Evgeniy (ewgraf)
- - Maxime Helias (maxhelias)
- Vincent AUBERT (vincent)
- Juti Noppornpitak (shiroyuki)
- Anthony MARTIN (xurudragon)
@@ -184,11 +185,12 @@ The Symfony Connect username in parenthesis allows to get more information
- Hidenori Goto (hidenorigoto)
- Jan Rosier (rosier)
- Alessandro Chitolina (alekitto)
- - Ruud Kamphuis (ruudk)
+ - Ion Bazan (ionbazan)
- Albert Casademont (acasademont)
- Arnaud Kleinpeter (nanocom)
- Guilherme Blanco (guilhermeblanco)
- SpacePossum
+ - Alexander Menshchikov (zmey_kk)
- Pablo Godel (pgodel)
- Andreas Braun
- Jérémie Augustin (jaugustin)
@@ -201,7 +203,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Jeroen Spee (jeroens)
- Fabien Bourigault (fbourigault)
- Joe Bennett (kralos)
- - Alexander Menshchikov (zmey_kk)
- Mikael Pajunen
- Andreas Schempp (aschempp)
- Romaric Drigon (romaricdrigon)
@@ -241,6 +242,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Dmitrii Poddubnyi (karser)
- Michael Babker (mbabker)
- Tien Vo (tienvx)
+ - Simon Berger
- Timothée Barray (tyx)
- James Halsall (jaitsu)
- Florent Mata (fmata)
@@ -270,7 +272,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Sebastien Morel (plopix)
- Baptiste Leduc (korbeil)
- mcfedr (mcfedr)
- - Simon Berger
- Ruben Gonzalez (rubenrua)
- Benjamin Dulau (dbenjamin)
- Baptiste Lafontaine (magnetik)
@@ -282,7 +283,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Guillaume Pédelagrabe
- Noel Guilbert (noel)
- Anthony GRASSIOT (antograssiot)
- - Ion Bazan (ionbazan)
- Stadly
- Stepan Anchugov (kix)
- François Pluchino (francoispluchino)
@@ -351,6 +351,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Sébastien Lavoie (lavoiesl)
- Dariusz
- Farhad Safarov (safarov)
+ - BoShurik
- Thomas Lallement (raziel057)
- Francois Zaninotto
- Claude Khedhiri (ck-developer)
@@ -429,6 +430,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Wouter Van Hecke
- Iker Ibarguren (ikerib)
- Bob van de Vijver (bobvandevijver)
+ - Soner Sayakci
- Peter Kruithof (pkruithof)
- Michael Holm (hollo)
- Sylvain Fabre (sylfabre)
@@ -499,7 +501,6 @@ The Symfony Connect username in parenthesis allows to get more information
- ivan
- Greg Anderson
- Tri Pham (phamuyentri)
- - BoShurik
- Gennady Telegin (gtelegin)
- Krystian Marcisz (simivar)
- Toni Rudolf (toooni)
@@ -524,8 +525,8 @@ The Symfony Connect username in parenthesis allows to get more information
- Dmytro Borysovskyi (dmytr0)
- Tomasz Kowalczyk (thunderer)
- Artur Eshenbrener
- - Soner Sayakci
- Thomas Perez (scullwm)
+ - Yoann RENARD (yrenard)
- Felix Labrecque
- Yaroslav Kiliba
- Terje Bråten
@@ -619,6 +620,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Alexandru Furculita (afurculita)
- Valentin Jonovs (valentins-jonovs)
- Bastien DURAND (deamon)
+ - Antonio Jose Cerezo (ajcerezo)
- Jeanmonod David (jeanmonod)
- Christin Gruber (christingruber)
- Andrey Sevastianov
@@ -670,7 +672,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Andrew M-Y (andr)
- Krasimir Bosilkov (kbosilkov)
- Marcin Michalski (marcinmichalski)
- - Yoann RENARD (yrenard)
- Vitaliy Tverdokhlib (vitaliytv)
- Ariel Ferrandini (aferrandini)
- Niklas Keller
@@ -694,6 +695,7 @@ The Symfony Connect username in parenthesis allows to get more information
- franek (franek)
- Raulnet
- Christian Wahler
+ - Dries Vints
- Giso Stallenberg (gisostallenberg)
- Gintautas Miselis
- Rob Bast
@@ -714,6 +716,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Patrick Reimers (preimers)
- insekticid
- Alexander Obuhovich (aik099)
+ - Jérémy M (th3mouk)
- Vitaliy Ryaboy (vitaliy)
- boombatower
- Fabrice Bernhard (fabriceb)
@@ -753,6 +756,7 @@ The Symfony Connect username in parenthesis allows to get more information
- ondrowan
- Barry vd. Heuvel (barryvdh)
- Jon Dufresne
+ - Fabien S (bafs)
- Evan S Kaufman (evanskaufman)
- Alex Bacart
- mcben
@@ -773,6 +777,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Andrew Udvare (audvare)
- alexpods
- Dennis Langen (nijusan)
+ - Hubert Lenoir (hubert_lenoir)
- Adam Szaraniec (mimol)
- Dariusz Ruminski
- Erik Trapman (eriktrapman)
@@ -847,6 +852,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Thiago Cordeiro (thiagocordeiro)
- Jan Behrens
- Dragos Protung (dragosprotung)
+ - Romain Monteil (ker0x)
- Mantas Var (mvar)
- Terje Bråten
- Yann LUCAS (drixs6o9)
@@ -872,7 +878,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Jean-Christophe Cuvelier [Artack]
- julien57
- Julien Montel (julienmgel)
- - Antonio Jose Cerezo (ajcerezo)
- Mátyás Somfai (smatyas)
- Alexandre Tranchant (alexandre_t)
- Anthony Moutte
@@ -1114,11 +1119,13 @@ The Symfony Connect username in parenthesis allows to get more information
- Aurélien Fontaine
- Pascal Helfenstein
- Baldur Rensch (brensch)
+ - Carl Casbolt (carlcasbolt)
- Vladyslav Petrovych
- Hugo Sales
- Alex Xandra Albert Sim
- Carson Full
- Sergey Yastrebov
+ - kylekatarnls (kylekatarnls)
- Trent Steel (trsteel88)
- Yuen-Chi Lian
- Tarjei Huse (tarjei)
@@ -1175,6 +1182,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Christian Soronellas (theunic)
- kick-the-bucket
- fedor.f
+ - Bilge
- Yosmany Garcia (yosmanyga)
- Jeremiasz Major
- Wouter de Wild
@@ -1186,7 +1194,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Krzysiek Łabuś
- Juraj Surman
- Camille Dejoye
- - Fabien S (bafs)
- 1ma (jautenim)
- Douglas Hammond (wizhippo)
- Xavier Lacot (xavier)
@@ -1210,7 +1217,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Dmitry Pigin (dotty)
- Vincent Composieux (eko)
- Jayson Xu (superjavason)
- - Hubert Lenoir (hubert_lenoir)
- fago
- popnikos
- Tito Costa
@@ -1235,14 +1241,15 @@ The Symfony Connect username in parenthesis allows to get more information
- Reen Lokum
- Martin Parsiegla (spea)
- Bernhard Rusch
+ - bhavin (bhavin4u)
- Ivan
- Quentin Schuler
+ - Nico Haase
- Pierre Vanliefland (pvanliefland)
- Roy Klutman (royklutman)
- Sofiane HADDAG (sofhad)
- frost-nzcr4
- Taylor Otwell
- - Dries Vints
- Sami Mussbach
- Kien Nguyen
- Foxprodev
@@ -1279,6 +1286,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Cyrille Bourgois (cyrilleb)
- Gerard van Helden (drm)
- Johnny Peck (johnnypeck)
+ - Jordi Sala Morales (jsala)
- Marcos Rezende (rezehnde)
- Roman Anasal
- Ivan Menshykov
@@ -1324,7 +1332,6 @@ The Symfony Connect username in parenthesis allows to get more information
- abdul malik ikhsan (samsonasik)
- Henry Snoek (snoek09)
- Dmitry (staratel)
- - Jérémy M (th3mouk)
- Tito Miguel Costa (titomiguelcosta)
- Simone Di Maulo (toretto460)
- Christian Morgan
@@ -1355,6 +1362,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Arno Geurts
- Adán Lobato (adanlobato)
- Ian Jenkins (jenkoian)
+ - Kai Eichinger (kai_eichinger)
- Hugo Alliaume (kocal)
- Marcos Gómez Vilches (markitosgv)
- Matthew Davis (mdavis1982)
@@ -1404,6 +1412,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Vincent MOULENE (vints24)
- Koen Kuipers
- datibbaw
+ - Nicolas de Marqué (nicola)
- Antoine Leblanc
- Andre Johnson
- Marco Pfeiffer
@@ -1412,7 +1421,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Daniel Alejandro Castro Arellano (lexcast)
- Aleksandar Dimitrov (netbull)
- Gary Houbre (thegarious)
- - Romain Monteil (ker0x)
- sensio
- Thomas Jarrand
- Antoine Bluchet (soyuka)
@@ -1421,6 +1429,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Paul Oms
- Reece Fowell (reecefowell)
- stefan.r
+ - Htun Htun Htet (ryanhhh91)
- Guillaume Gammelin
- Valérian Galliat
- d-ph
@@ -1490,6 +1499,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Ken Stanley
- ivan
- Zachary Tong (polyfractal)
+ - Oleg Krasavin (okwinza)
- Mario Blažek (marioblazek)
- Jure (zamzung)
- Michael Nelson
@@ -1562,6 +1572,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Antanas Arvasevicius
- Pierre Dudoret
- Thomas
+ - Georgi Georgiev
- Maximilian Berghoff (electricmaxxx)
- nacho
- Piotr Antosik (antek88)
@@ -1621,6 +1632,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Maximilian Ruta (deltachaos)
- Mickaël Isaert (misaert)
- Jakub Sacha
+ - Julius Kiekbusch
- Olaf Klischat
- orlovv
- Claude Dioudonnat
@@ -1644,6 +1656,7 @@ The Symfony Connect username in parenthesis allows to get more information
- James Hudson
- Stephen Clouse
- e-ivanov
+ - Nathanaël Martel (nathanaelmartel)
- Einenlum
- Jochen Bayer (jocl)
- Patrick Carlo-Hickman
@@ -1669,6 +1682,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Neil Katin
- David Otton
- Will Donohoe
+ - gnito-org
- peter
- Jérémy Jourdin (jjk801)
- BRAMILLE Sébastien (oktapodia)
@@ -1697,7 +1711,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Juan Miguel Besada Vidal (soutlink)
- dlorek
- Stuart Fyfe
- - Carl Casbolt (carlcasbolt)
- David de Boer (ddeboer)
- Eno Mullaraj (emullaraj)
- Nathan PAGE (nathix)
@@ -1752,6 +1765,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Clement Herreman (clemherreman)
- Dan Ionut Dumitriu (danionut90)
- Vladislav Rastrusny (fractalizer)
+ - Vlad Gapanovich (gapik)
- Alexander Kurilo (kamazee)
- Nyro (nyro)
- Marco
@@ -1801,6 +1815,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Artem Stepin (astepin)
- Christian Flach (cmfcmf)
- Cédric Girard (enk_)
+ - Fabian Kropfhamer (fabiank)
- Lars Ambrosius Wallenborn (larsborn)
- Oriol Mangas Abellan (oriolman)
- Sebastian Göttschkes (sgoettschkes)
@@ -1912,7 +1927,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Martin Pärtel
- Daniel Rotter (danrot)
- Frédéric Bouchery (fbouchery)
- - kylekatarnls (kylekatarnls)
- Patrick Daley (padrig)
- Foxprodev
- Max Summe
@@ -1923,6 +1937,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Tadcka
- Beth Binkovitz
- Gonzalo Míguez
+ - Fabian Haase
- Romain Geissler
- Adrien Moiruad
- Tomaz Ahlin
@@ -1994,6 +2009,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Ergie Gonzaga
- Matthew J Mucklo
- AnrDaemon
+ - Anthony Massard (decap94)
- Emre Akinci (emre)
- Chris Maiden (matason)
- fdgdfg (psampaz)
@@ -2119,6 +2135,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Sergey Fokin (tyraelqp)
- Evrard Boulou
- pborreli
+ - Bernat Llibre
- Boris Betzholz
- Eric Caron
- 2manypeople
@@ -2234,10 +2251,12 @@ The Symfony Connect username in parenthesis allows to get more information
- Felix Marezki
- Normunds
- Luiz “Felds” Liscia
+ - Yuri Karaban
- Johan
- Thomas Rothe
- Martin
- nietonfir
+ - Andriy
- alefranz
- David Barratt
- Andrea Giannantonio
@@ -2278,7 +2297,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Alessio Baglio (ioalessio)
- Johannes Müller (johmue)
- Jordi Llonch (jordillonch)
- - Jordi Sala Morales (jsala)
- Mouad ZIANI (mouadziani)
- Nicholas Ruunu (nicholasruunu)
- Jeroen van den Nieuwenhuisen (nieuwenhuisen)
@@ -2473,8 +2491,10 @@ The Symfony Connect username in parenthesis allows to get more information
- Maerlyn
- Even André Fiskvik
- Agata
+ - dakur
- Александр Ли
- Arjan Keeman
+ - Vlad Dumitrache
- Erik van Wingerden
- Valouleloup
- robmro27
@@ -2602,6 +2622,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Paulius Jarmalavičius (pjarmalavicius)
- Ramon Henrique Ornelas (ramonornela)
- Ricardo de Vries (ricknox)
+ - Ruslan Zavacky (ruslanzavacky)
- Stefano Cappellini (stefano_cappellini)
- Thomas Dutrion (theocrite)
- Till Klampaeckel (till)
@@ -2639,7 +2660,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Jordan Hoff
- znerol
- Christian Eikermann
- - Kai Eichinger
- Antonio Angelino
- Jens Schulze
- Matt Fields
@@ -2702,10 +2722,12 @@ The Symfony Connect username in parenthesis allows to get more information
- Adrian Philipp
- James Michael DuPont
- Kasperki
+ - dima-gr
- Tammy D
- Rodolfo Ruiz
- Enrico
- Ryan Rud
+ - Christopher Georg
- Ondrej Slinták
- vlechemin
- Brian Corrigan
@@ -2798,6 +2820,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Дмитрий Пацура
- Signor Pedro
- Matthias Larisch
+ - Maxime P
- ilyes kooli
- Ilia Lazarev
- Michaël VEROUX
@@ -2806,7 +2829,6 @@ The Symfony Connect username in parenthesis allows to get more information
- arduanov
- sualko
- Molkobain
- - Bilge
- Yendric
- ADmad
- Nicolas Roudaire
@@ -2978,7 +3000,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Maxime COLIN (maximecolin)
- Muharrem Demirci (mdemirci)
- Evgeny Z (meze)
- - Nicolas de Marqué (nicola)
- Pierre Geyer (ptheg)
- Thomas BERTRAND (sevrahk)
- Matej Žilák (teo_sk)
diff --git a/composer.json b/composer.json
index da8e66b784de0..1e73439a2dd1e 100644
--- a/composer.json
+++ b/composer.json
@@ -123,7 +123,7 @@
"doctrine/cache": "^1.6|^2.0",
"doctrine/collections": "~1.0",
"doctrine/data-fixtures": "^1.1",
- "doctrine/dbal": "^2.6|^3.0",
+ "doctrine/dbal": "^2.7|^3.0",
"doctrine/orm": "^2.6.3",
"guzzlehttp/promises": "^1.4",
"masterminds/html5": "^2.6",
@@ -143,6 +143,7 @@
"twig/markdown-extra": "^2.12|^3"
},
"conflict": {
+ "doctrine/dbal": "<2.7",
"egulias/email-validator": "~3.0.0",
"masterminds/html5": "<2.6",
"monolog/monolog": ">=2",
diff --git a/psalm.xml b/psalm.xml
index 3f12f1331c272..015c0ed18b21b 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -17,4 +17,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php
index 4b63652ae8058..8f8256f6cb99b 100644
--- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php
+++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php
@@ -13,6 +13,7 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Result as DriverResult;
+use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
@@ -63,7 +64,7 @@ public function loadTokenBySeries($series)
$sql = 'SELECT class, username, value, lastUsed AS last_used'
.' FROM rememberme_token WHERE series=:series';
$paramValues = ['series' => $series];
- $paramTypes = ['series' => \PDO::PARAM_STR];
+ $paramTypes = ['series' => ParameterType::STRING];
$stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes);
$row = $stmt instanceof Result || $stmt instanceof DriverResult ? $stmt->fetchAssociative() : $stmt->fetch(\PDO::FETCH_ASSOC);
@@ -81,7 +82,7 @@ public function deleteTokenBySeries($series)
{
$sql = 'DELETE FROM rememberme_token WHERE series=:series';
$paramValues = ['series' => $series];
- $paramTypes = ['series' => \PDO::PARAM_STR];
+ $paramTypes = ['series' => ParameterType::STRING];
if (method_exists($this->conn, 'executeStatement')) {
$this->conn->executeStatement($sql, $paramValues, $paramTypes);
} else {
@@ -102,9 +103,9 @@ public function updateToken($series, $tokenValue, \DateTime $lastUsed)
'series' => $series,
];
$paramTypes = [
- 'value' => \PDO::PARAM_STR,
+ 'value' => ParameterType::STRING,
'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE,
- 'series' => \PDO::PARAM_STR,
+ 'series' => ParameterType::STRING,
];
if (method_exists($this->conn, 'executeStatement')) {
$updated = $this->conn->executeStatement($sql, $paramValues, $paramTypes);
@@ -132,10 +133,10 @@ public function createNewToken(PersistentTokenInterface $token)
'lastUsed' => $token->getLastUsed(),
];
$paramTypes = [
- 'class' => \PDO::PARAM_STR,
- 'username' => \PDO::PARAM_STR,
- 'series' => \PDO::PARAM_STR,
- 'value' => \PDO::PARAM_STR,
+ 'class' => ParameterType::STRING,
+ 'username' => ParameterType::STRING,
+ 'series' => ParameterType::STRING,
+ 'value' => ParameterType::STRING,
'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE,
];
if (method_exists($this->conn, 'executeStatement')) {
diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php
index 9c31d6d7e76b4..35fc48ff1536f 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php
@@ -11,9 +11,9 @@
namespace Symfony\Bridge\Doctrine\Tests\DataCollector;
+use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Logging\DebugStack;
-use Doctrine\DBAL\Platforms\MySqlPlatform;
-use Doctrine\DBAL\Version;
+use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\Persistence\ManagerRegistry;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector;
@@ -22,6 +22,9 @@
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Dumper\CliDumper;
+// Doctrine DBAL 2 compatibility
+class_exists(\Doctrine\DBAL\Platforms\MySqlPlatform::class);
+
class DoctrineDataCollectorTest extends TestCase
{
public function testCollectConnections()
@@ -93,6 +96,8 @@ public function testCollectQueries($param, $types, $expected, $explainable, bool
$dumper->setColors(false);
$collectedParam->dump($dumper);
$this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true));
+ } elseif (\is_string($expected)) {
+ $this->assertStringMatchesFormat($expected, $collectedParam);
} else {
$this->assertEquals($expected, $collectedParam);
}
@@ -150,7 +155,7 @@ public function testReset()
/**
* @dataProvider paramProvider
*/
- public function testSerialization($param, $types, $expected, $explainable, bool $runnable = true)
+ public function testSerialization($param, array $types, $expected, $explainable, bool $runnable = true)
{
$queries = [
['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1],
@@ -167,6 +172,8 @@ public function testSerialization($param, $types, $expected, $explainable, bool
$dumper->setColors(false);
$collectedParam->dump($dumper);
$this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true));
+ } elseif (\is_string($expected)) {
+ $this->assertStringMatchesFormat($expected, $collectedParam);
} else {
$this->assertEquals($expected, $collectedParam);
}
@@ -175,9 +182,9 @@ public function testSerialization($param, $types, $expected, $explainable, bool
$this->assertSame($runnable, $collectedQueries['default'][0]['runnable']);
}
- public function paramProvider()
+ public function paramProvider(): array
{
- $tests = [
+ return [
['some value', [], 'some value', true],
[1, [], 1, true],
[true, [], true, true],
@@ -207,30 +214,25 @@ public function paramProvider()
,
false,
],
- ];
-
- if (version_compare(Version::VERSION, '2.6', '>=')) {
- $tests[] = ['this is not a date', ['date'], "⚠ Could not convert PHP value 'this is not a date' of type 'string' to type 'date'. Expected one of the following types: null, DateTime", false, false];
- $tests[] = [
+ ['this is not a date', ['date'], "⚠ Could not convert PHP value 'this is not a date'%S to type %Sdate%S. Expected one of the following types: null, DateTime", false, false],
+ [
new \stdClass(),
['date'],
<<getMockBuilder(\Doctrine\DBAL\Connection::class)
+ $connection = $this->getMockBuilder(Connection::class)
->disableOriginalConstructor()
->getMock();
$connection->expects($this->any())
diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php
index f99a48527c442..be63ef923dfbc 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php
@@ -103,9 +103,12 @@ public function testInvalidEntityManagerThrowsException()
public function testMiddlewareNoPingInNonWorkerContext()
{
- $this->connection->expects($this->never())
- ->method('ping')
- ->willReturn(false);
+ // This method has been removed in DBAL 3.0
+ if (method_exists(Connection::class, 'ping')) {
+ $this->connection->expects($this->never())
+ ->method('ping')
+ ->willReturn(false);
+ }
$this->connection->expects($this->never())
->method('close')
diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json
index 0da77033b3334..79961033bc0a6 100644
--- a/src/Symfony/Bridge/Doctrine/composer.json
+++ b/src/Symfony/Bridge/Doctrine/composer.json
@@ -43,10 +43,12 @@
"doctrine/annotations": "^1.10.4",
"doctrine/collections": "~1.0",
"doctrine/data-fixtures": "^1.1",
- "doctrine/dbal": "^2.6|^3.0",
+ "doctrine/dbal": "^2.7|^3.0",
"doctrine/orm": "^2.6.3"
},
"conflict": {
+ "doctrine/dbal": "<2.7",
+ "doctrine/orm": "<2.6.3",
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
"symfony/dependency-injection": "<3.4",
"symfony/form": "<4.4",
diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
index 518a76425377e..bff2db7d87257 100644
--- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
+++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
@@ -146,7 +146,7 @@ public function handleError($type, $msg, $file, $line, $context = [])
$msg = $deprecation->getMessage();
- if (error_reporting() & $type) {
+ if (\E_DEPRECATED !== $type && (error_reporting() & $type)) {
$group = 'unsilenced';
} elseif ($deprecation->isLegacy()) {
$group = 'legacy';
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
index 1d3a96e982c25..6d8820443a2c1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
@@ -77,9 +77,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
foreach ($secrets as $k => $v) {
if (null === $v) {
- $io->error($this->vault->getLastMessage());
-
- return 1;
+ $io->error($this->vault->getLastMessage() ?? sprintf('Secret "%s" has been skipped as there was an error reading it.', $k));
+ continue;
}
$this->localVault->seal($k, $v);
diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 0dc2860229bdf..524b8ded2d48e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -119,6 +119,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
$container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new RoutingResolverPass());
+ $container->addCompilerPass(new DataCollectorTranslatorPass());
$container->addCompilerPass(new ProfilerPass());
// must be registered before removing private services as some might be listeners/subscribers
// but as late as possible to get resolved parameters
@@ -139,7 +140,6 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new FragmentRendererPass());
$this->addCompilerPassIfExists($container, SerializerPass::class);
$this->addCompilerPassIfExists($container, PropertyInfoPass::class);
- $container->addCompilerPass(new DataCollectorTranslatorPass());
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
$container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32);
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
index 7792ea6730a0f..6dfd27bcbc67a 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
@@ -116,14 +116,14 @@
Symfony version
- {% if 'n/a' != collector.env %}
+ {% if 'n/a' is not same as(collector.env) %}
{{ collector.env }}Environment
{% endif %}
- {% if 'n/a' != collector.debug %}
+ {% if 'n/a' is not same as(collector.debug) %}
{{ collector.debug ? 'enabled' : 'disabled' }}Debug
diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
index 71338c3c12e0a..edbdc3ea92a11 100644
--- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
@@ -121,7 +121,7 @@ public static function createSystemCache($namespace, $defaultLifetime, $version,
return $opcache;
}
- $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version);
+ $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version);
if (null !== $logger) {
$apcu->setLogger($logger);
}
diff --git a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php
index c721f35d73d4e..b8b4b6f7b3134 100644
--- a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php
@@ -15,6 +15,7 @@
use Predis\Connection\Aggregate\PredisCluster;
use Predis\Connection\Aggregate\ReplicationInterface;
use Predis\Response\Status;
+use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\Exception\LogicException;
use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
@@ -159,6 +160,12 @@ protected function doDeleteYieldTags(array $ids): iterable
});
foreach ($results as $id => $result) {
+ if ($result instanceof \RedisException) {
+ CacheItem::log($this->logger, 'Failed to delete key "{key}": '.$result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]);
+
+ continue;
+ }
+
try {
yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
} catch (\Exception $e) {
@@ -197,6 +204,8 @@ protected function doInvalidate(array $tagIds): bool
// gargage collect that set from the client side.
$lua = <<<'EOLUA'
+ redis.replicate_commands()
+
local cursor = '0'
local id = KEYS[1]
repeat
@@ -234,6 +243,8 @@ protected function doInvalidate(array $tagIds): bool
});
$lua = <<<'EOLUA'
+ redis.replicate_commands()
+
local id = KEYS[1]
local cursor = table.remove(ARGV)
redis.call('SREM', '{'..id..'}'..id, unpack(ARGV))
@@ -241,7 +252,17 @@ protected function doInvalidate(array $tagIds): bool
return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000)
EOLUA;
- foreach ($results as $id => [$cursor, $ids]) {
+ $success = true;
+ foreach ($results as $id => $values) {
+ if ($values instanceof \RedisException) {
+ CacheItem::log($this->logger, 'Failed to invalidate key "{key}": '.$values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]);
+ $success = false;
+
+ continue;
+ }
+
+ [$cursor, $ids] = $values;
+
while ($ids || '0' !== $cursor) {
$this->doDelete($ids);
@@ -264,7 +285,7 @@ protected function doInvalidate(array $tagIds): bool
}
}
- return true;
+ return $success;
}
private function getRedisEvictionPolicy(): string
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
index 27354cf911f3c..3ff73aeab965f 100644
--- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
+++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
@@ -217,7 +217,7 @@ public function testPrune()
$doSet('qux', 'qux-val', new \DateInterval('PT20S'));
sleep(30);
- $cache->prune();
+ $this->assertTrue($cache->prune());
$this->assertTrue($this->isPruned($cache, 'foo'));
$this->assertTrue($this->isPruned($cache, 'bar'));
$this->assertTrue($this->isPruned($cache, 'baz'));
@@ -228,27 +228,27 @@ public function testPrune()
$doSet('baz', 'baz-val', new \DateInterval('PT40S'));
$doSet('qux', 'qux-val', new \DateInterval('PT80S'));
- $cache->prune();
+ $this->assertTrue($cache->prune());
$this->assertFalse($this->isPruned($cache, 'foo'));
$this->assertFalse($this->isPruned($cache, 'bar'));
$this->assertFalse($this->isPruned($cache, 'baz'));
$this->assertFalse($this->isPruned($cache, 'qux'));
sleep(30);
- $cache->prune();
+ $this->assertTrue($cache->prune());
$this->assertFalse($this->isPruned($cache, 'foo'));
$this->assertTrue($this->isPruned($cache, 'bar'));
$this->assertFalse($this->isPruned($cache, 'baz'));
$this->assertFalse($this->isPruned($cache, 'qux'));
sleep(30);
- $cache->prune();
+ $this->assertTrue($cache->prune());
$this->assertFalse($this->isPruned($cache, 'foo'));
$this->assertTrue($this->isPruned($cache, 'baz'));
$this->assertFalse($this->isPruned($cache, 'qux'));
sleep(30);
- $cache->prune();
+ $this->assertTrue($cache->prune());
$this->assertFalse($this->isPruned($cache, 'foo'));
$this->assertTrue($this->isPruned($cache, 'qux'));
}
diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php
index a2129c459b6f7..2f733a78e1307 100644
--- a/src/Symfony/Component/Cache/Traits/PdoTrait.php
+++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php
@@ -17,7 +17,9 @@
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\TableNotFoundException;
+use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Statement;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
@@ -166,19 +168,29 @@ public function prune()
$deleteSql .= " AND $this->idCol LIKE :namespace";
}
+ $connection = $this->getConnection();
+ $useDbalConstants = $connection instanceof Connection;
+
try {
- $delete = $this->getConnection()->prepare($deleteSql);
+ $delete = $connection->prepare($deleteSql);
} catch (TableNotFoundException $e) {
return true;
} catch (\PDOException $e) {
return true;
}
- $delete->bindValue(':time', time(), \PDO::PARAM_INT);
+ $delete->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
if ('' !== $this->namespace) {
- $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR);
+ $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), $useDbalConstants ? ParameterType::STRING : \PDO::PARAM_STR);
}
try {
+ // Doctrine DBAL ^2.13 || >= 3.1
+ if ($delete instanceof Statement && method_exists($delete, 'executeStatement')) {
+ $delete->executeStatement();
+
+ return true;
+ }
+
return $delete->execute();
} catch (TableNotFoundException $e) {
return true;
@@ -192,13 +204,16 @@ public function prune()
*/
protected function doFetch(array $ids)
{
+ $connection = $this->getConnection();
+ $useDbalConstants = $connection instanceof Connection;
+
$now = time();
$expired = [];
$sql = str_pad('', (\count($ids) << 1) - 1, '?,');
$sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)";
- $stmt = $this->getConnection()->prepare($sql);
- $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
+ $stmt = $connection->prepare($sql);
+ $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
foreach ($ids as $id) {
$stmt->bindValue(++$i, $id);
}
@@ -222,8 +237,8 @@ protected function doFetch(array $ids)
if ($expired) {
$sql = str_pad('', (\count($expired) << 1) - 1, '?,');
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)";
- $stmt = $this->getConnection()->prepare($sql);
- $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
+ $stmt = $connection->prepare($sql);
+ $stmt->bindValue($i = 1, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
foreach ($expired as $id) {
$stmt->bindValue(++$i, $id);
}
@@ -236,11 +251,14 @@ protected function doFetch(array $ids)
*/
protected function doHave($id)
{
+ $connection = $this->getConnection();
+ $useDbalConstants = $connection instanceof Connection;
+
$sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)";
- $stmt = $this->getConnection()->prepare($sql);
+ $stmt = $connection->prepare($sql);
$stmt->bindValue(':id', $id);
- $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
+ $stmt->bindValue(':time', time(), $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
$result = $stmt->execute();
return (bool) (\is_object($result) ? $result->fetchOne() : $stmt->fetchColumn());
@@ -303,6 +321,8 @@ protected function doSave(array $values, int $lifetime)
}
$conn = $this->getConnection();
+ $useDbalConstants = $conn instanceof Connection;
+
$driver = $this->driver;
$insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
@@ -354,25 +374,25 @@ protected function doSave(array $values, int $lifetime)
if ('sqlsrv' === $driver || 'oci' === $driver) {
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $id);
- $stmt->bindParam(3, $data, \PDO::PARAM_LOB);
- $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT);
- $stmt->bindValue(5, $now, \PDO::PARAM_INT);
- $stmt->bindParam(6, $data, \PDO::PARAM_LOB);
- $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT);
- $stmt->bindValue(8, $now, \PDO::PARAM_INT);
+ $stmt->bindParam(3, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB);
+ $stmt->bindValue(4, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
+ $stmt->bindValue(5, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
+ $stmt->bindParam(6, $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB);
+ $stmt->bindValue(7, $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
+ $stmt->bindValue(8, $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
} else {
$stmt->bindParam(':id', $id);
- $stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
- $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
- $stmt->bindValue(':time', $now, \PDO::PARAM_INT);
+ $stmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB);
+ $stmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
+ $stmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
}
if (null === $driver) {
$insertStmt = $conn->prepare($insertSql);
$insertStmt->bindParam(':id', $id);
- $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
- $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
- $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT);
+ $insertStmt->bindParam(':data', $data, $useDbalConstants ? ParameterType::LARGE_OBJECT : \PDO::PARAM_LOB);
+ $insertStmt->bindValue(':lifetime', $lifetime, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
+ $insertStmt->bindValue(':time', $now, $useDbalConstants ? ParameterType::INTEGER : \PDO::PARAM_INT);
}
foreach ($values as $id => $data) {
diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json
index d71f2169e03c2..72bd68fbe31dd 100644
--- a/src/Symfony/Component/Cache/composer.json
+++ b/src/Symfony/Component/Cache/composer.json
@@ -33,7 +33,7 @@
"require-dev": {
"cache/integration-tests": "dev-master",
"doctrine/cache": "^1.6|^2.0",
- "doctrine/dbal": "^2.6|^3.0",
+ "doctrine/dbal": "^2.7|^3.0",
"predis/predis": "^1.1",
"psr/simple-cache": "^1.0",
"symfony/config": "^4.2|^5.0",
@@ -43,7 +43,7 @@
"symfony/var-dumper": "^4.4|^5.0"
},
"conflict": {
- "doctrine/dbal": "<2.6",
+ "doctrine/dbal": "<2.7",
"symfony/dependency-injection": "<3.4",
"symfony/http-kernel": "<4.4|>=5.0",
"symfony/var-dumper": "<4.4"
diff --git a/src/Symfony/Component/Debug/README.md b/src/Symfony/Component/Debug/README.md
index 0627e69c35f31..31a824069f8a6 100644
--- a/src/Symfony/Component/Debug/README.md
+++ b/src/Symfony/Component/Debug/README.md
@@ -12,7 +12,7 @@ Getting Started
---------------
```
-$ composer install symfony/debug
+$ composer require symfony/debug
```
```php
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php
index 2257edaef6daf..38e2dd06d9638 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php
@@ -32,8 +32,8 @@ public function __destruct()
{
// default tags should be added last
foreach ($this->defaultTags as $name => $attributes) {
- foreach ($attributes as $attributes) {
- $this->definition->addTag($name, $attributes);
+ foreach ($attributes as $attribute) {
+ $this->definition->addTag($name, $attribute);
}
}
$this->defaultTags = [];
diff --git a/src/Symfony/Component/Form/Resources/translations/validators.my.xlf b/src/Symfony/Component/Form/Resources/translations/validators.my.xlf
new file mode 100644
index 0000000000000..b0180c551172f
--- /dev/null
+++ b/src/Symfony/Component/Form/Resources/translations/validators.my.xlf
@@ -0,0 +1,139 @@
+
+
+
+
+
+ This form should not contain extra fields.
+ ဤ ဖောင်သည် field အပိုများ မပါ၀င်သင့်ပါ။
+
+
+ The uploaded file was too large. Please try to upload a smaller file.
+ Upload တင်သောဖိုင်သည်အလွန်ကြီးလွန်းသည်။ ကျေးဇူးပြု၍ သေးငယ်သည့်ဖိုင်ကိုတင်ရန်ကြိုးစားပါ။
+
+
+ The CSRF token is invalid. Please try to resubmit the form.
+ သင့်လျှော်သော် CSRF တိုကင် မဟုတ်ပါ။ ကျေးဇူးပြု၍ဖောင်ကိုပြန်တင်ပါ။
+
+
+ This value is not a valid HTML5 color.
+ ဤတန်ဖိုးသည် သင့်လျှော်သော် HTML5 အရောင်မဟုတ်ပါ။
+
+
+ Please enter a valid birthdate.
+ ကျေးဇူးပြု၍ မှန်ကန်သောမွေးနေ့ကိုထည့်ပါ။
+
+
+ The selected choice is invalid.
+ သင့် ရွေးချယ်မှုသည်မမှန်ကန်ပါ။
+
+
+ The collection is invalid.
+ ဤ collection သည်သင့်လျှော်သော် collection မဟုတ်ပါ။
+
+
+ Please select a valid color.
+ ကျေးဇူးပြု၍ မှန်ကန်သောအရောင်ကိုရွေးပါ။
+
+
+ Please select a valid country.
+ ကျေးဇူးပြု၍ မှန်ကန်သောနိုင်ငံကိုရွေးပါ။
+
+
+ Please select a valid currency.
+ ကျေးဇူးပြု၍ မှန်ကန်သောငွေကြေးကိုရွေးပါ။
+
+
+ Please choose a valid date interval.
+ ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲကိုရွေးပါ။
+
+
+ Please enter a valid date and time.
+ ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲနှင့်အချိန် ကိုထည့်ပါ။
+
+
+ Please enter a valid date.
+ ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲကိုထည့်ပါ။
+
+
+ Please select a valid file.
+ ကျေးဇူးပြု၍ မှန်ကန်သောနေ ဖိုင်ကိုရွေးချယ်ပါ။
+
+
+ The hidden field is invalid.
+ မသင့် လျှော်သော် hidden field ဖြစ်နေသည်။
+
+
+ Please enter an integer.
+ ကျေးဇူးပြု၍ Integer တန်ဖိုးသာထည့်ပါ။
+
+
+ Please select a valid language.
+ ကျေးဇူးပြု၍ မှန်ကန်သော ဘာသာစကားကိုရွေးချယ်ပါ။
+
+
+ Please select a valid locale.
+ ကျေးဇူးပြု၍ မှန်ကန်သော locale ကိုရွေးချယ်ပါ။
+
+
+ Please enter a valid money amount.
+ ကျေးဇူးပြု၍ မှန်ကန်သော ပိုက်ဆံပမာဏ ကိုထည့်ပါ။
+
+
+ Please enter a number.
+ ကျေးဇူးပြု၍ မှန်ကန်သော နံပါတ် ကိုရွေးချယ်ပါ။
+
+
+ The password is invalid.
+ မှန်ကန်သောစကား၀ှက်မဟုတ်ပါ။
+
+
+ Please enter a percentage value.
+ ကျေးဇူးပြု၍ ရာခိုင်နှုန်းတန်ဖိုးထည့်ပါ။
+
+
+ The values do not match.
+ တန်ဖိုးများကိုက်ညီမှုမရှိပါ။
+
+
+ Please enter a valid time.
+ ကျေးဇူးပြု၍ မှန်ကန်သောအချိန်ကိုထည့်ပါ။
+
+
+ Please select a valid timezone.
+ ကျေးဇူးပြု၍ မှန်ကန်သောအချိန်ဇုန်ကိုရွေးပါ။
+
+
+ Please enter a valid URL.
+ ကျေးဇူးပြု၍ သင့်လျှော်သော် URL ကိုရွေးပါ။
+
+
+ Please enter a valid search term.
+ ကျေးဇူးပြု၍ သင့် လျှော်သော်ရှာဖွေမှု term များထည့်ပါ။
+
+
+ Please provide a valid phone number.
+ ကျေးဇူးပြု၍ သင့် လျှော်သော်ရှာဖွေမှု ဖုန်းနံပါတ်ထည့်ပါ။
+
+
+ The checkbox has an invalid value.
+ Checkbox တန်ဖိုးသည် မှန်ကန်မှုမရှိပါ။
+
+
+ Please enter a valid email address.
+ ကျေးဇူးပြု၍ မှန်ကန်သော် email လိပ်စာထည့်ပါ။
+
+
+ Please select a valid option.
+ ကျေးဇူးပြု၍ မှန်ကန်သော် ရွေးချယ်မှု ကိုရွေးပါ။
+
+
+ Please select a valid range.
+ ကျေးဇူးပြု၍ မှန်ကန်သော အပိုင်းအခြား ကိုရွေးပါ။
+
+
+ Please enter a valid week.
+ ကျေးဇူးပြု၍ မှန်ကန်သောရက်သတ္တပတ်ကိုထည့်ပါ။
+
+
+
+
diff --git a/src/Symfony/Component/Form/Tests/Util/StringUtilTest.php b/src/Symfony/Component/Form/Tests/Util/StringUtilTest.php
index 1d162250d1568..3058a2e25d84d 100644
--- a/src/Symfony/Component/Form/Tests/Util/StringUtilTest.php
+++ b/src/Symfony/Component/Form/Tests/Util/StringUtilTest.php
@@ -16,11 +16,20 @@
class StringUtilTest extends TestCase
{
- public function testTrim()
+ public function trimProvider()
{
- $data = ' Foo! ';
+ return [
+ [' Foo! ', 'Foo!'],
+ ["\u{1F92E}", "\u{1F92E}"], // unassigned character in PCRE versions of assertEquals('Foo!', StringUtil::trim($data));
+ /**
+ * @dataProvider trimProvider
+ */
+ public function testTrim($data, $expectedData)
+ {
+ $this->assertSame($expectedData, StringUtil::trim($data));
}
/**
diff --git a/src/Symfony/Component/Form/Util/StringUtil.php b/src/Symfony/Component/Form/Util/StringUtil.php
index fe372cf196d24..623693d5635e2 100644
--- a/src/Symfony/Component/Form/Util/StringUtil.php
+++ b/src/Symfony/Component/Form/Util/StringUtil.php
@@ -33,7 +33,7 @@ private function __construct()
*/
public static function trim($string)
{
- if (null !== $result = @preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $string)) {
+ if (null !== $result = @preg_replace('/^[\pZ\p{Cc}\p{Cf}]+|[\pZ\p{Cc}\p{Cf}]+$/u', '', $string)) {
return $result;
}
diff --git a/src/Symfony/Component/HttpClient/Internal/ClientState.php b/src/Symfony/Component/HttpClient/Internal/ClientState.php
index c316e7b078920..52fe3c8c054c7 100644
--- a/src/Symfony/Component/HttpClient/Internal/ClientState.php
+++ b/src/Symfony/Component/HttpClient/Internal/ClientState.php
@@ -22,4 +22,5 @@ class ClientState
{
public $handlesActivity = [];
public $openHandles = [];
+ public $lastTimeout;
}
diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
index 69caabf4b85d0..0f041d4d02d21 100644
--- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
+++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
@@ -233,15 +233,15 @@ abstract protected static function perform(ClientState $multi, array &$responses
*/
abstract protected static function select(ClientState $multi, float $timeout): int;
- private static function initialize(self $response): void
+ private static function initialize(self $response, float $timeout = null): void
{
if (null !== $response->info['error']) {
throw new TransportException($response->info['error']);
}
try {
- if (($response->initializer)($response)) {
- foreach (self::stream([$response]) as $chunk) {
+ if (($response->initializer)($response, $timeout)) {
+ foreach (self::stream([$response], $timeout) as $chunk) {
if ($chunk->isFirst()) {
break;
}
@@ -304,7 +304,7 @@ private function doDestruct()
$this->shouldBuffer = true;
if ($this->initializer && null === $this->info['error']) {
- self::initialize($this);
+ self::initialize($this, -0.0);
$this->checkStatusCode();
}
}
@@ -325,6 +325,12 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
$lastActivity = microtime(true);
$elapsedTimeout = 0;
+ if ($fromLastTimeout = 0.0 === $timeout && '-0' === (string) $timeout) {
+ $timeout = null;
+ } elseif ($fromLastTimeout = 0 > $timeout) {
+ $timeout = -$timeout;
+ }
+
while (true) {
$hasActivity = false;
$timeoutMax = 0;
@@ -340,13 +346,18 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
$timeoutMin = min($timeoutMin, $response->timeout, 1);
$chunk = false;
+ if ($fromLastTimeout && null !== $multi->lastTimeout) {
+ $elapsedTimeout = microtime(true) - $multi->lastTimeout;
+ }
+
if (isset($multi->handlesActivity[$j])) {
- // no-op
+ $multi->lastTimeout = null;
} elseif (!isset($multi->openHandles[$j])) {
unset($responses[$j]);
continue;
} elseif ($elapsedTimeout >= $timeoutMax) {
$multi->handlesActivity[$j] = [new ErrorChunk($response->offset, sprintf('Idle timeout reached for "%s".', $response->getInfo('url')))];
+ $multi->lastTimeout ?? $multi->lastTimeout = $lastActivity;
} else {
continue;
}
diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php
index a3782df49e5ed..85466d33b5438 100644
--- a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php
+++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php
@@ -19,6 +19,15 @@
abstract class HttpClientTestCase extends BaseHttpClientTestCase
{
+ public function testTimeoutOnDestruct()
+ {
+ if (!method_exists(parent::class, 'testTimeoutOnDestruct')) {
+ $this->markTestSkipped('BaseHttpClientTestCase doesn\'t have testTimeoutOnDestruct().');
+ }
+
+ parent::testTimeoutOnDestruct();
+ }
+
public function testAcceptHeader()
{
$client = $this->getHttpClient(__FUNCTION__);
diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
index 27cc87f0ccfbd..75bf16d3e6c86 100644
--- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
+++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
@@ -115,6 +115,10 @@ protected function getHttpClient(string $testCase): HttpClientInterface
$this->markTestSkipped('Real transport required');
break;
+ case 'testTimeoutOnDestruct':
+ $this->markTestSkipped('Real transport required');
+ break;
+
case 'testDestruct':
$this->markTestSkipped("MockHttpClient doesn't timeout on destruct");
break;
diff --git a/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php
index bcfab64bdcace..2f76cc91c609f 100644
--- a/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php
+++ b/src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php
@@ -25,4 +25,9 @@ public function testInformationalResponseStream()
{
$this->markTestSkipped('NativeHttpClient doesn\'t support informational status codes.');
}
+
+ public function testTimeoutOnDestruct()
+ {
+ $this->markTestSkipped('NativeHttpClient doesn\'t support opening concurrent requests.');
+ }
}
diff --git a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php
index 7c0cdaa90d7d1..b83c44a48dea5 100644
--- a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php
+++ b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php
@@ -47,7 +47,7 @@ public function collect(Request $request, Response $response/*, \Throwable $exce
}
$this->data = [
- 'token' => $response->headers->get('X-Debug-Token'),
+ 'token' => $request->attributes->get('_stopwatch_token'),
'start_time' => $startTime * 1000,
'events' => [],
'stopwatch_installed' => class_exists(Stopwatch::class, false),
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 6c816aaf63d63..4578541b2a889 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -76,11 +76,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
private static $freshCache = [];
- public const VERSION = '4.4.30';
- public const VERSION_ID = 40430;
+ public const VERSION = '4.4.31';
+ public const VERSION_ID = 40431;
public const MAJOR_VERSION = 4;
public const MINOR_VERSION = 4;
- public const RELEASE_VERSION = 30;
+ public const RELEASE_VERSION = 31;
public const EXTRA_VERSION = '';
public const END_OF_MAINTENANCE = '11/2022';
diff --git a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php
index 0c6f1543acfdd..26b323f81051a 100644
--- a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php
@@ -32,9 +32,11 @@ public function testClearPool()
$pool = $this->createMock(CacheItemPoolInterface::class);
$pool
->expects($this->once())
- ->method('clear');
+ ->method('clear')
+ ->willReturn(true)
+ ;
- (new Psr6CacheClearer(['pool' => $pool]))->clearPool('pool');
+ $this->assertTrue((new Psr6CacheClearer(['pool' => $pool]))->clearPool('pool'));
}
public function testClearPoolThrowsExceptionOnUnreferencedPool()
diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
index c00e1849fc500..5a0964f6c21ca 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
@@ -236,7 +236,8 @@ public function testNoExceptionOnNonExistentTypeHintOptionalArg()
$pass->process($container);
$locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
- $this->assertSame(['foo::barAction', 'foo::fooAction'], array_keys($locator));
+
+ $this->assertEqualsCanonicalizing(['foo::barAction', 'foo::fooAction'], array_keys($locator));
}
public function testArgumentWithNoTypeHintIsOk()
diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
index b5e55bdea9e97..b9dd84d592fa6 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
@@ -57,7 +57,7 @@ public function testProcess()
'Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass: Removing method "setTestCase" of service "c2" from controller candidates: the method is called at instantiation, thus cannot be an action.',
];
- $this->assertSame($expectedLog, $container->getCompiler()->getLog());
+ $this->assertEqualsCanonicalizing($expectedLog, $container->getCompiler()->getLog());
}
public function testInvoke()
diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php
index e6436bb0f6807..d55d7efd824ae 100644
--- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php
+++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php
@@ -56,6 +56,9 @@ public function testConstructorDefaultTimeZone()
);
}
+ /**
+ * @group legacy
+ */
public function testConstructorWithoutDateType()
{
$formatter = $this->getDateFormatter('en', null, IntlDateFormatter::SHORT, 'UTC', IntlDateFormatter::GREGORIAN);
@@ -63,6 +66,9 @@ public function testConstructorWithoutDateType()
$this->assertSame('EEEE, MMMM d, y \'at\' h:mm a', $formatter->getPattern());
}
+ /**
+ * @group legacy
+ */
public function testConstructorWithoutTimeType()
{
$formatter = $this->getDateFormatter('en', IntlDateFormatter::SHORT, null, 'UTC', IntlDateFormatter::GREGORIAN);
diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
index 2e400d29c9283..49e465d3f791c 100644
--- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
+++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Ldap\Adapter\ExtLdap;
+use LDAP\Connection as LDAPConnection;
use Symfony\Component\Ldap\Adapter\AbstractConnection;
use Symfony\Component\Ldap\Exception\AlreadyExistsException;
use Symfony\Component\Ldap\Exception\ConnectionException;
@@ -32,7 +33,7 @@ class Connection extends AbstractConnection
/** @var bool */
private $bound = false;
- /** @var resource */
+ /** @var resource|LDAPConnection */
private $connection;
/**
@@ -89,9 +90,7 @@ public function bind($dn = null, $password = null)
}
/**
- * Returns a link resource.
- *
- * @return resource
+ * @return resource|LDAPConnection
*
* @internal
*/
@@ -165,7 +164,7 @@ private function connect()
private function disconnect()
{
- if ($this->connection && \is_resource($this->connection)) {
+ if ($this->connection) {
ldap_unbind($this->connection);
}
diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php
index 4abcff763aaac..3fcf9bee16018 100644
--- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php
+++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Ldap\Adapter\ExtLdap;
+use LDAP\Connection as LDAPConnection;
+use LDAP\Result;
use Symfony\Component\Ldap\Adapter\AbstractQuery;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\Ldap\Exception\NotBoundException;
@@ -27,7 +29,7 @@ class Query extends AbstractQuery
/** @var Connection */
protected $connection;
- /** @var resource[] */
+ /** @var resource[]|Result[] */
private $results;
/** @var array */
@@ -156,7 +158,7 @@ public function execute()
* Returns an LDAP search resource. If this query resulted in multiple searches, only the first
* page will be returned.
*
- * @return resource
+ * @return resource|Result
*
* @internal
*/
@@ -172,7 +174,7 @@ public function getResource($idx = 0)
/**
* Returns all LDAP search resources.
*
- * @return resource[]
+ * @return resource[]|Result[]
*
* @internal
*/
@@ -215,7 +217,7 @@ private function resetPagination()
/**
* Sets LDAP pagination controls.
*
- * @param resource $con
+ * @param resource|LDAPConnection $con
*/
private function controlPagedResult($con, int $pageSize, bool $critical, string $cookie): bool
{
@@ -239,8 +241,8 @@ private function controlPagedResult($con, int $pageSize, bool $critical, string
/**
* Retrieve LDAP pagination cookie.
*
- * @param resource $con
- * @param resource $result
+ * @param resource|LDAPConnection $con
+ * @param resource|Result $result
*/
private function controlPagedResultResponse($con, $result, string $cookie = ''): string
{
@@ -257,9 +259,9 @@ private function controlPagedResultResponse($con, $result, string $cookie = ''):
/**
* Calls actual LDAP search function with the prepared options and parameters.
*
- * @param resource $con
+ * @param resource|LDAPConnection $con
*
- * @return resource
+ * @return resource|Result
*/
private function callSearchFunction($con, string $func, int $sizeLimit)
{
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php
index d8b1447257ba1..5bc7dddcd2934 100644
--- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php
@@ -140,7 +140,11 @@ private function getDBALConnectionMock()
$schemaConfig->method('getMaxIdentifierLength')->willReturn(63);
$schemaConfig->method('getDefaultTableOptions')->willReturn([]);
$schemaManager->method('createSchemaConfig')->willReturn($schemaConfig);
- $driverConnection->method('getSchemaManager')->willReturn($schemaManager);
+ if (method_exists(DBALConnection::class, 'createSchemaManager')) {
+ $driverConnection->method('createSchemaManager')->willReturn($schemaManager);
+ } else {
+ $driverConnection->method('getSchemaManager')->willReturn($schemaManager);
+ }
return $driverConnection;
}
@@ -428,7 +432,11 @@ public function testSetupIndices(string $platformClass, array $expectedIndices)
$expectedTable->addIndex($indexColumns);
}
$schemaManager->method('createSchema')->willReturn($schema);
- $driverConnection->method('getSchemaManager')->willReturn($schemaManager);
+ if (method_exists(DBALConnection::class, 'createSchemaManager')) {
+ $driverConnection->method('createSchemaManager')->willReturn($schemaManager);
+ } else {
+ $driverConnection->method('getSchemaManager')->willReturn($schemaManager);
+ }
$platformMock = $this->createMock($platformClass);
$platformMock
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php
index d0b531387033e..2bc70871baf5c 100644
--- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/DoctrineIntegrationTest.php
@@ -14,6 +14,7 @@
use Doctrine\DBAL\Driver\Result as DriverResult;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Result;
+use Doctrine\DBAL\Schema\AbstractSchemaManager;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Transport\Doctrine\Connection;
@@ -175,7 +176,7 @@ public function testItRetrieveTheMessageThatIsOlderThanRedeliverTimeout()
public function testTheTransportIsSetupOnGet()
{
- $this->assertFalse($this->driverConnection->getSchemaManager()->tablesExist('messenger_messages'));
+ $this->assertFalse($this->createSchemaManager()->tablesExist('messenger_messages'));
$this->assertNull($this->connection->get());
$this->connection->send('the body', ['my' => 'header']);
@@ -187,4 +188,11 @@ private function formatDateTime(\DateTime $dateTime)
{
return $dateTime->format($this->driverConnection->getDatabasePlatform()->getDateTimeFormatString());
}
+
+ private function createSchemaManager(): AbstractSchemaManager
+ {
+ return method_exists($this->driverConnection, 'createSchemaManager')
+ ? $this->driverConnection->createSchemaManager()
+ : $this->driverConnection->getSchemaManager();
+ }
}
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php
index 3aa59d69eaeee..bf7ad591e454d 100644
--- a/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Transport/RedisExt/ConnectionTest.php
@@ -113,15 +113,26 @@ public function testKeepGettingPendingMessages()
$this->assertNotNull($connection->get());
}
- public function testAuth()
+ /**
+ * @param string|array $expected
+ *
+ * @dataProvider provideAuthDsn
+ */
+ public function testAuth($expected, string $dsn)
{
$redis = $this->createMock(\Redis::class);
$redis->expects($this->exactly(1))->method('auth')
- ->with('password')
+ ->with($expected)
->willReturn(true);
- Connection::fromDsn('redis://password@localhost/queue', [], $redis);
+ Connection::fromDsn($dsn, [], $redis);
+ }
+
+ public function provideAuthDsn(): \Generator
+ {
+ yield 'Password only' => ['password', 'redis://password@localhost/queue'];
+ yield 'User and password' => [['user', 'password'], 'redis://user:password@localhost/queue'];
}
public function testNoAuthWithEmptyPassword()
diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
index e936ca09e871f..063724b976219 100644
--- a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
+++ b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
@@ -20,6 +20,7 @@
use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Result;
+use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer;
@@ -377,7 +378,7 @@ private function executeStatement(string $sql, array $parameters = [], array $ty
private function getSchema(): Schema
{
- $schema = new Schema([], [], $this->driverConnection->getSchemaManager()->createSchemaConfig());
+ $schema = new Schema([], [], $this->createSchemaManager()->createSchemaConfig());
$table = $schema->createTable($this->configuration['table_name']);
$table->addColumn('id', self::$useDeprecatedConstants ? Type::BIGINT : Types::BIGINT)
->setAutoincrement(true)
@@ -421,7 +422,7 @@ private function updateSchema(): void
}
$comparator = new Comparator();
- $schemaDiff = $comparator->compare($this->driverConnection->getSchemaManager()->createSchema(), $this->getSchema());
+ $schemaDiff = $comparator->compare($this->createSchemaManager()->createSchema(), $this->getSchema());
foreach ($schemaDiff->toSaveSql($this->driverConnection->getDatabasePlatform()) as $sql) {
if (method_exists($this->driverConnection, 'executeStatement')) {
@@ -431,4 +432,11 @@ private function updateSchema(): void
}
}
}
+
+ private function createSchemaManager(): AbstractSchemaManager
+ {
+ return method_exists($this->driverConnection, 'createSchemaManager')
+ ? $this->driverConnection->createSchemaManager()
+ : $this->driverConnection->getSchemaManager();
+ }
}
diff --git a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php
index e7c549ecf49f8..88b1a7e5a5f28 100644
--- a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php
+++ b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php
@@ -97,7 +97,8 @@ public static function fromDsn(string $dsn, array $redisOptions = [], \Redis $re
$connectionCredentials = [
'host' => $parsedUrl['host'] ?? '127.0.0.1',
'port' => $parsedUrl['port'] ?? 6379,
- 'auth' => $parsedUrl['pass'] ?? $parsedUrl['user'] ?? null,
+ // See: https://github.com/phpredis/phpredis/#auth
+ 'auth' => isset($parsedUrl['pass']) && isset($parsedUrl['user']) ? [$parsedUrl['user'], $parsedUrl['pass']] : $parsedUrl['pass'] ?? $parsedUrl['user'] ?? null,
];
if (isset($parsedUrl['query'])) {
diff --git a/src/Symfony/Component/Mime/RawMessage.php b/src/Symfony/Component/Mime/RawMessage.php
index 66788d8ad526d..d2a311daebecf 100644
--- a/src/Symfony/Component/Mime/RawMessage.php
+++ b/src/Symfony/Component/Mime/RawMessage.php
@@ -33,8 +33,11 @@ public function toString(): string
if (\is_string($this->message)) {
return $this->message;
}
+ if ($this->message instanceof \Traversable) {
+ $this->message = iterator_to_array($this->message, false);
+ }
- return $this->message = implode('', iterator_to_array($this->message, false));
+ return $this->message = implode('', $this->message);
}
public function toIterable(): iterable
diff --git a/src/Symfony/Component/Mime/Tests/RawMessageTest.php b/src/Symfony/Component/Mime/Tests/RawMessageTest.php
index 26e7605baba2d..41503451bb1da 100644
--- a/src/Symfony/Component/Mime/Tests/RawMessageTest.php
+++ b/src/Symfony/Component/Mime/Tests/RawMessageTest.php
@@ -16,16 +16,12 @@
class RawMessageTest extends TestCase
{
- public function testToString()
+ /**
+ * @dataProvider provideMessages
+ */
+ public function testToString($messageParameter)
{
- $message = new RawMessage('string');
- $this->assertEquals('string', $message->toString());
- $this->assertEquals('string', implode('', iterator_to_array($message->toIterable())));
- // calling methods more than once work
- $this->assertEquals('string', $message->toString());
- $this->assertEquals('string', implode('', iterator_to_array($message->toIterable())));
-
- $message = new RawMessage(new \ArrayObject(['some', ' ', 'string']));
+ $message = new RawMessage($messageParameter);
$this->assertEquals('some string', $message->toString());
$this->assertEquals('some string', implode('', iterator_to_array($message->toIterable())));
// calling methods more than once work
@@ -33,6 +29,15 @@ public function testToString()
$this->assertEquals('some string', implode('', iterator_to_array($message->toIterable())));
}
+ public function provideMessages(): array
+ {
+ return [
+ 'string' => ['some string'],
+ 'traversable' => [new \ArrayObject(['some', ' ', 'string'])],
+ 'array' => [['some', ' ', 'string']],
+ ];
+ }
+
public function testSerialization()
{
$message = new RawMessage('string');
diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
index 0af4b9bf1bb36..be22f95855b9e 100644
--- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
+++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
@@ -333,8 +333,8 @@ private function extractFromReflectionType(\ReflectionType $reflectionType, \Ref
$types = [];
$nullable = $reflectionType->allowsNull();
- foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
- $phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type;
+ foreach (($reflectionType instanceof \ReflectionUnionType || $reflectionType instanceof \ReflectionIntersectionType) ? $reflectionType->getTypes() : [$reflectionType] as $type) {
+ $phpTypeOrClass = $type->getName();
if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass || 'never' === $phpTypeOrClass) {
continue;
}
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
index 95e1ca5cda118..2f2449cd1112d 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
@@ -256,11 +256,20 @@ public function php80TypesProvider()
}
/**
+ * @dataProvider php81TypesProvider
* @requires PHP 8.1
*/
- public function testExtractPhp81Type()
+ public function testExtractPhp81Type($property, array $type = null)
{
- $this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy', 'nothing', []));
+ $this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy', $property, []));
+ }
+
+ public function php81TypesProvider()
+ {
+ return [
+ ['nothing', null],
+ ['collection', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Traversable'), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Countable')]],
+ ];
}
/**
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php
index b4e896a434524..1300c3e695f1f 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php
@@ -8,4 +8,8 @@ public function getNothing(): never
{
throw new \Exception('Oops');
}
+
+ public function getCollection(): \Traversable&\Countable
+ {
+ }
}
diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf
index 5a8d0c7d84880..212ca70c922e3 100644
--- a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf
+++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf
@@ -70,6 +70,14 @@
Invalid or expired login link.Enllaç d'inici de sessió no vàlid o caducat.
+
+ Too many failed login attempts, please try again in %minutes% minute.
+ Massa intents d'inici de sessió fallits, torneu-ho a provar en %minutes% minut.
+
+
+ Too many failed login attempts, please try again in %minutes% minutes.
+ Massa intents d'inici de sessió fallits, torneu-ho a provar en %minutes% minuts.
+