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. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.my.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.my.xlf new file mode 100644 index 0000000000000..df593f0e0b82b --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.my.xlf @@ -0,0 +1,83 @@ + + + + + + An authentication exception occurred. + အသုံးပြုခွင့် ခြွင်းချက်တစ်ခုဖြစ်သွားသည်။ + + + Authentication credentials could not be found. + အသုံးပြုခွင့် အထောက်အထားများ ရှာမတွေ့ပါ။ + + + Authentication request could not be processed due to a system problem. + System ပြဿနာအခက်အခဲရှိ နေပါသဖြင့် အသုံးပြုခွင့်တောင်းဆိုချက်ကို ဆောင်ရွက်၍မရ နိုင်ပါ။ + + + Invalid credentials. + သင့်လျှော်သော် အထောက်အထားမဟုတ်ပါ။ + + + Cookie has already been used by someone else. + Cookie ကို တစ်စုံတစ်ယောက်မှ အသုံးပြုပြီးဖြစ်သည်။ + + + Not privileged to request the resource. + အရင်းအမြစ်ကိုတောင်းဆိုရန်အခွင့်ထူးမရပါ။ + + + Invalid CSRF token. + သင့်လျှော်သော် CSRF token မဟုတ်ပါ။ + + + No authentication provider found to support the authentication token. + အထောက်အထားစိစစ်ခြင်းသင်္ကေတကိုပံ့ပိုးရန် မည်သည့်အထောက်အထားစိစစ်ရေး ၀န်ဆောင်မှုမှမတွေ့ပါ။ + + + No session available, it either timed out or cookies are not enabled. + Session မအားလပ်ပါ။ Session အချိန်ကုန်သွားခြင်း (သို့မဟုတ်) cookies များကိုဖွင့်ထားခြင်းမရှိပါ။ + + + No token could be found. + Toke ရှာမတွေ့ပါ။ + + + Username could not be found. + အသုံးပြုသူအမည် ရှာဖွေတွေ့ရှိချင်းမရှိပါ။ + + + Account has expired. + အကောင့် သက်တမ်းကုန်လွန်သွားပါပြီ။ + + + Credentials have expired. + အထောက်အထားသက်တန်း ကုန်လွန်သွားပါပြီ။ + + + Account is disabled. + အကောင့်ပိတ်ထားပါသည်။ + + + Account is locked. + အကောင့် လောခ်ကျသွားပါပြီ။ + + + Too many failed login attempts, please try again later. + Login ၀င်ရန်ကြိုးစားမှုများလွန်းပါသည်၊ ကျေးဇူးပြု၍ နောက်မှထပ်ကြိုးစားပါ။ + + + Invalid or expired login link. + မသင့်လျှော်သော် (သို့မဟုတ်) သက်တန်းကုန်သော login link ဖြစ်ပါသည်။ + + + Too many failed login attempts, please try again in %minutes% minute. + Too many failed login attempts, please try again in %minutes% minute. + + + Too many failed login attempts, please try again in %minutes% minutes. + Login ၀င်ရန်ကြိုးစားမှုများလွန်းပါသည်၊ ကျေးဇူးပြု၍ နောက် %minutes% မှထပ်မံကြိုးစားပါ။ + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf index 3caa51ab01306..8e06befafdf33 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf @@ -70,6 +70,14 @@ Invalid or expired login link. Neplatný alebo expirovaný odkaz na prihlásenie. + + Too many failed login attempts, please try again in %minutes% minute. + Príliš veľa neúspešných pokusov o prihlásenie. Skúste to znova o %minutes% minútu. + + + Too many failed login attempts, please try again in %minutes% minutes. + Príliš veľa neúspešných pokusov o prihlásenie. Skúste to znova o %minutes% minút. + diff --git a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php index b1643fb4d0a4b..e93724f8ec7f5 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php @@ -109,13 +109,13 @@ public function supportsNormalization($data, $format = null) */ public function denormalize($data, $type, $format = null, array $context = []) { - if (!preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) { + if (null === $data || !preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) { throw new NotNormalizableValueException('The provided "data:" URI is not valid.'); } try { switch ($type) { - case 'Symfony\Component\HttpFoundation\File\File': + case File::class: return new File($data, false); case 'SplFileObject': diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php index 24c5672bea43f..02bd050bd395b 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php @@ -139,6 +139,7 @@ public function invalidUriProvider() ['data:text/html;charset,%3Ch1%3EHello!%3C%2Fh1%3E'], ['data:base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC'], [''], + [null], ['http://wikipedia.org'], ['base64'], ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC'], diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf index f53eb0e61ad82..4a73556e504d7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf @@ -386,6 +386,10 @@ This value is not a valid International Securities Identification Number (ISIN). Aquest valor no és un número d'identificació de valors internacionals (ISIN) vàlid. + + This value should be a valid expression. + Aquest valor hauria de ser una expressió vàlida. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf new file mode 100644 index 0000000000000..7f45aaed64f36 --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf @@ -0,0 +1,395 @@ + + + + + + This value should be false. + ဤတန်ဖိုးသည် false ဖြစ်ရမည်။ + + + This value should be true. + ဤတန်ဖိုးသည် true ဖြစ်ရမည်။ + + + This value should be of type {{ type }}. + ဤတန်ဖိုးသည် {{ type }} အမျိုးအစားဖြစ်ရမည်။ + + + This value should be blank. + ဤတန်ဖိုးသည် ကွပ်လပ်မဖြစ်သင့်ပါ။ + + + The value you selected is not a valid choice. + သင်ရွေးချယ်သောတန်ဖိုးသည် သင့်လျှော်သော် တန်ဖိုးမဟုတ်ပါ။ + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + သင်သည် အနည်းဆုံးရွေးချယ်မှု {{ limit }} ခုရွေးချယ်ရမည်။ + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + သင်သည်အများဆုံး {{ limit }} ခုသာရွေးချယ်ခွင့်ရှိသည်။ + + + One or more of the given values is invalid. + ပေးထားသောတန်ဖိုးတစ်ခု (သို့မဟုတ်) တစ်ခုထက်ပို၍မမှန်ကန်ပါ။ + + + This field was not expected. + ဤကွက်လပ်ကိုမမျှော်လင့်ထားပါ။ + + + This field is missing. + ဤကွက်လပ်ကိုမမျှော်လင့်ထားပါ။ + + + This value is not a valid date. + ဤတန်ဖိုးသည်မှန်ကန်သော်ရက်စွဲမဟုတ်ပါ။ + + + This value is not a valid datetime. + ဤတန်ဖိုးသည် မှန်ကန်သော် ရက်စွဲ/အချိန် မဟုတ်ပါ။ + + + This value is not a valid email address. + ဤတန်ဖိုးသည် မှန်ကန်သော် အီးမေးလိပ်စာ မဟုတ်ပါ။ + + + The file could not be found. + ဖိုင်ရှာမတွေ့ပါ။ + + + The file is not readable. + ဤဖိုင်ကို ဖတ်၍မရပါ။ + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + ဖိုင်အရွယ်အစား အလွန်ကြီးနေသည် ({{ size }} {{ suffix }}). ခွင့်ပြုထားသော အများဆုံး ဖိုင်ဆိုဒ်သည် {{ limit }} {{ suffix }} ဖြစ်သည်။ + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + ဖိုင်၏ mime အမျိုးအစားမမှန်ကန်ပါ ({{ type }})။ ခွင့်ပြုထားသော mime အမျိုးအစားများမှာ {{ types }}. + + + This value should be {{ limit }} or less. + ဤတန်ဖိုးသည် {{ limit }} (သို့မဟုတ်) {{ limit }} ထက်နည်းသင့်သည်။ + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + ဤတန်ဖိုးသည် အလွန်ရှည်လွန်းသည်။ ၎င်းတွင်အက္ခရာ {{ limit }} (သို့မဟုတ်) ၎င်းထက်နည်းသင့်သည်။ | ဤတန်ဖိုးသည် အလွန်ရှည်လွန်းသည်။ ၎င်းတွင်အက္ခရာ {{limit}} ခုနှင့်အထက်ရှိသင့်သည်။ + + + This value should be {{ limit }} or more. + ဤတန်ဖိုးသည် {{limit}} (သို့မဟုတ်) ထို့ထက်ပိုသင့်သည်။ + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + ဤတန်ဖိုးသည် အလွန်တိုလွန်းသည်။ ၎င်းတွင်အက္ခရာ {{limit}} (သို့မဟုတ်) ထို့ထက်ပိုရှိသင့်သည်။ | ဤတန်ဖိုးသည်တိုလွန်းသည်။ ၎င်းတွင်အက္ခရာ {{limit}} လုံးနှင့်အထက်ရှိသင့်သည်။ + + + This value should not be blank. + ဤတန်ဖိုးသည်ကွက်လပ်မဖြစ်သင့်ပါ။ + + + This value should not be null. + ဤတန်ဖိုးသည် null မဖြစ်သင့်ပါ။ + + + This value should be null. + ဤတန်ဖိုးသည် null ဖြစ်သင့်သည်။ + + + This value is not valid. + ဤတန်ဖိုးသည်မှန်ကန်သောတန်ဖိုးမဟုတ်ပါ။ + + + This value is not a valid time. + ဤတန်ဖိုးသည်မှန်ကန်သော အချိန်တန်ဖိုးမဟုတ်ပါ။ + + + This value is not a valid URL. + ဤတန်ဖိုးသည်မှန်ကန်သော URL တန်ဖိုးမဟုတ်ပါ။ + + + The two values should be equal. + တန်ဖိုးနှစ်ခုသည် တူညီသင့်သည်။ + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + ဤဖိုင်သည် အလွန်ကြီးသည်။ ခွင့်ပြုထားသည့်အများဆုံးဖိုင်အရွယ်အစားသည် {{ limit }} {{ suffix }} ဖြစ်သည်။ + + + The file is too large. + ဤဖိုင်သည် အလွန်ကြီးသည်။ + + + The file could not be uploaded. + ဤဖိုင်ကိုတင်၍မရပါ။ + + + This value should be a valid number. + ဤတန်ဖိုးသည်မှန်ကန်သောနံပါတ်ဖြစ်သင့်သည်။ + + + This file is not a valid image. + ဤဖိုင်သည်မှန်ကန်သော ဓါတ်ပုံမဟုတ်ပါ။ + + + This is not a valid IP address. + ၎င်းသည်တရားဝင် IP လိပ်စာမဟုတ်ပါ။ + + + This value is not a valid language. + ဤတန်ဖိုးသည် မှန်ကန်သောဘာသာစကားမဟုတ်ပါ။ + + + This value is not a valid locale. + ဤတန်ဖိုးသည်မှန်ကန်သောဘာသာပြန်မဟုတ်ပါ။ + + + This value is not a valid country. + ဤတန်ဖိုးသည်မှန်ကန်သောနိုင်ငံမဟုတ်ပါ။ + + + This value is already used. + ဤတန်ဖိုးသည် အသုံးပြုပြီးသားဖြစ်သည်။ + + + The size of the image could not be detected. + ဓါတ်ပုံအရွယ်အစားကိုရှာမတွေ့ပါ။ + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + ပုံ၏အလျားသည် ကြီးလွန်းသည် ({{ width }}px)။ ခွင့်ပြုထားသည့်အများဆုံးအလျားသည် {{max_width}}px ဖြစ်သည်။ + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + ပုံ၏အလျားသည် သေးလွန်းသည် ({{ width }}px)။ ခွင့်ပြုထားသည့်အနည်းဆုံးအလျားသည် {{max_width}}px ဖြစ်သည်။ + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + ပုံ၏အနံသည် ကြီးလွန်းသည် ({{ height }}px)။ ခွင့်ပြုထားသည့်အများဆုံးအနံသည် {{max_height}}px ဖြစ်သည်။ + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + ပုံ၏အနံသည် သေးလွန်းသည် ({{ height }}px)။ ခွင့်ပြုထားသည့်အနည်းဆုံးအနံသည် {{min_height}}px ဖြစ်သည်။ + + + This value should be the user's current password. + ဤတန်ဖိုးသည်အသုံးပြုသူ၏ လက်ရှိစကားဝှက်ဖြစ်သင့်သည်။ + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + ဤတန်ဖိုးသည်စာလုံး {{limit}} အတိအကျရှိသင့်သည်။ + + + The file was only partially uploaded. + ဤဖိုင်သည်တစ်စိတ်တစ်ပိုင်းသာ upload တင်ခဲ့သည်။ + + + No file was uploaded. + မည်သည့် ဖိုင်မျှ upload မလုပ်ခဲ့ပါ။ + + + No temporary folder was configured in php.ini. + php.ini တွင်ယာယီဖိုင်တွဲကိုပြင်ဆင်ထားခြင်းမရှိပါ၊ + + + Cannot write temporary file to disk. + ယာရီဖိုင်ကို disk မရေးနိုင်ပါ။ + + + A PHP extension caused the upload to fail. + PHP extension တစ်ခုကြောင့် upload တင်၍မရနိုင်ပါ။ + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + ဤ collection တွင် {{limit}} element (သို့မဟုတ်) ထို့ထက်မပိုသင့်ပါ။ + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + ဤ collection တွင် {{limit}} element (သို့မဟုတ်) ၎င်းထက်နည်းသင့်သည်။ + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + ဤစုစည်းမှုတွင် {{limit}} element အတိအကျပါသင့်သည်။ + + + Invalid card number. + ကဒ်နံပါတ်မမှန်ပါ။ + + + Unsupported card type or invalid card number. + ကဒ်အမျိုးအစားမမှန်ပါ (သို့မဟုတ်) ကဒ်နံပါတ်မမှန်ပါ။ + + + This is not a valid International Bank Account Number (IBAN). + ဤတန်ဖိုးသည် တရား၀င်နိုင်ငံတကာဘဏ်အကောင့်နံပါတ် (International Bank Account Number, IBAN) မဟုတ်ပါ။ + + + This value is not a valid ISBN-10. + ဤတန်ဖိုးသည် မှန်ကန်သော ISBN-10 တန်ဖိုးမဟုတ်ပါ၊ + + + This value is not a valid ISBN-13. + ဤတန်ဖိုးသည် မှန်ကန်သော ISBN-13 တန်ဖိုးမဟုတ်ပါ၊ + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + ဤတန်ဖိုးသည် သင့်လျှော်သော် ISBN-10 (သို့မဟုတ်) ISBN-13 တန်ဖိုးမဟုတ်ပါ၊ + + + This value is not a valid ISSN. + ဤတန်ဖိုးသည် သင့်လျှော်သော် ISSN တန်ဖိုးမဟုတ်ပါ။ + + + This value is not a valid currency. + ဤတန်ဖိုးသည် သင့်လျှော်သော် ငွေကြေးတန်ဖိုးမဟုတ်ပါ။ + + + This value should be equal to {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} နှင့်ညီသင့်သည်။ + + + This value should be greater than {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} ထက်ကြီးသင့်သည်။ + + + This value should be greater than or equal to {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} ထက်ကြီးသင့်သည် (သို့မဟုတ်) ဤတန်ဖိုးသည် {{ compared_value }} ညီသင့်သည်။ + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value_type }} {{ compared_value }} နှင့်ထပ်တူညီမျှသင့်သည်။ + + + This value should be less than {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} ထက်မနဲသောတဲ့ တန်ဖိုးဖြစ်သင့်သည်။ + + + This value should be less than or equal to {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} ထက် မနည်းသောတန်ဖိုး (သို့မဟုတ်) ညီမျှသောတန်ဖိုးဖြစ်သင့်သည်။ + + + This value should not be equal to {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value }} နှင့်မညီသင့်ပါ။ + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + ဤတန်ဖိုးသည် {{ compared_value_type }} {{ compared_value }} နှင့်ထပ်တူမညီမျှသင့်သည်။ + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + ဤဓာတ်ပုံအချိုးအစားသည်အလွန်ကြီးလွန်းသည်။ ({{ ratio }})။ ခွင့်ပြုထားသောဓာတ်ပုံအချိုးအသားသည် {{ max_ratio }} ဖြစ်သည်။ + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + ဤဓာတ်ပုံအချိုးအစားသည်အလွန်သေးလွန်းသည်။ ({{ ratio }})။ ခွင့်ပြုထားသောဓာတ်ပုံအချိုးအသားသည် {{ min_ratio }} ဖြစ်သည်။ + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + ဤဓာတ်ပုံသည် စတုရန်းဖြစ်နေသည် ({{ width }}x{{ height }}px)။ စတုရန်းဓာတ်ပုံများကို ခွင့်မပြုပါ။ + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + ဤဓာတ်ပုံသည် အလျှားလိုက်ဖြစ်နေသည် ({{ width }}x{{ height }}px). အလျှားလိုက်ဓာတ်ပုံများခွင့်မပြုပါ။ + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + ဤဓာတ်ပုံသည် ဒေါင်လိုက်ဖြစ်နေသည် ({{ width }}x{{ height }}px). ဒေါင်လိုက်ဓာတ်ပုံများခွင့်မပြုပါ။ + + + An empty file is not allowed. + ဖိုင်အလွတ်ကိုတင်ခွင့်မပြုပါ။ + + + The host could not be resolved. + host ဖြေရှင်း၍မနိုင်ပါ။ + + + This value does not match the expected {{ charset }} charset. + ဤတန်ဖိုးသည် မျှော်မှန်းထားသော {{ charset }} စားလုံးနှင့် ကိုက်ညီမှုမရှိပါ။ + + + This is not a valid Business Identifier Code (BIC). + ၎င်းသည်မှန်ကန်သော Business Identifier Code (BIC) မဟုတ်ပါ။ + + + Error + အမှား + + + This is not a valid UUID. + ဤတန်ဖိုးသည် သင့်လျှော်သော် UUID မဟုတ်ပါ။ + + + This value should be a multiple of {{ compared_value }}. + ဤတန်ဖိုးသည် {{compared_value}} ၏ စတူတန်ဖိုးဖြစ်သင့်သည်။ + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + ဤ Business Identifier Code (BIC) သည် IBAN {{ iban }} နှင့်ဆက်စပ်မှုမရှိပါ။ + + + This value should be valid JSON. + ဤတန်ဖိုးသည် သင့်လျှော်သော် JSON တန်ဖိုးဖြစ်သင့်သည်။ + + + This collection should contain only unique elements. + ဤ collection ကိုယ်ပိုင် elements များ ပါသင့်သည်။ + + + This value should be positive. + ဤတန်ဖိုးသည် အပေါင်းဖြစ်သင့်သည်။ + + + This value should be either positive or zero. + ဤတန်ဖိုးသည် အပေါင်း (သို့မဟုတ်) သုည ဖြစ်သင့်သည်။ + + + This value should be negative. + ဤတန်ဖိုးသည် အနုတ် ဖြစ်သင့်သည်။ + + + This value should be either negative or zero. + ဤတန်ဖိုးသည် အနုတ် (သို့မဟုတ်) သုည ဖြစ်သင့်သည်။ + + + This value is not a valid timezone. + ဤတန်ဖိုးသည် မှန်ကန်သော အချိန်ဇုန်မဟုတ်ပါ။ + + + This password has been leaked in a data breach, it must not be used. Please use another password. + ဤစကားဝှက် သည် ဒေတာပေါက်ကြားမှုတစ်ခုဖြစ်ခဲ့သည်။ ဤစကား၀ှက်ကိုအသုံးမပြုရပါ။ ကျေးဇူးပြု၍ အခြားစကားဝှက်ကိုသုံးပါ။ + + + This value should be between {{ min }} and {{ max }}. + ဤတန်ဖိုးသည် {{ min }} နှင့် {{ max }} ကြားရှိသင့်သည်။ + + + This value is not a valid hostname. + ဤတန်ဖိုးသည် သင့်လျှော်သော် hostname မဟုတ်ပါ။ + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + ဤ collection တွင်ပါပါ၀င်သော elements အရေအတွက်သည် {{ compared_value }} ၏ စတူဖြစ်သင့်သည်။ + + + This value should satisfy at least one of the following constraints: + ဤတန်ဖိုးသည် အောက်ပါကန့်သတ်ချက်များအနက်မှအနည်းဆုံးတစ်ခု ဖြည့်ဆည်းပေးသင့်သည်။ + + + Each element of this collection should satisfy its own set of constraints. + ဤ collection ၏ element တစ်ခုစီသည်၎င်း၏ကိုယ်ပိုင်ကန့်သတ်ချက်များကိုဖြည့်ဆည်းသင့်သည်။ + + + This value is not a valid International Securities Identification Number (ISIN). + ဤတန်ဖိုးသည် သင့်လျှော်သော် အပြည်ပြည်ဆိုင်ရာငွေချေးသက်သေခံနံပါတ် ,International Securities Identification Number (ISIN) မဟုတ်ပါ။ + + + This value should be a valid expression. + ဤတန်ဖိုးသည်မှန်ကန်သောစကားရပ်ဖြစ်သင့်သည်။ + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf index 2f7660ea08e17..64a5c80fb6d24 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf @@ -386,6 +386,10 @@ This value is not a valid International Securities Identification Number (ISIN). Această valoare nu este un număr internațional de identificare (ISIN) valabil. + + This value should be a valid expression. + Această valoare ar trebui să fie o expresie validă. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index a0c55ea6db146..ad61814197df9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini. - V php.ini nie je nastavená cesta k adresáru pre dočasné súbory. + V php.ini nie je nastavená cesta k addressáru pre dočasné súbory. Cannot write temporary file to disk. @@ -386,6 +386,10 @@ This value is not a valid International Securities Identification Number (ISIN). Táto hodnota nie je platné medzinárodné označenie cenného papiera (ISIN). + + This value should be a valid expression. + Táto hodnota by mala byť platným výrazom. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf index 31453ff15736d..847bf3c26888b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf @@ -386,6 +386,10 @@ This value is not a valid International Securities Identification Number (ISIN). ค่า​รหัสหลักทรัพย์สากล (ISIN) ไม่ถูกต้อง + + This value should be a valid expression. + ค่านี้ควรเป็นนิพจน์ที่ถูกต้อง + diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 6a9002137b7c9..cd6e7dcab4804 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -82,29 +82,39 @@ protected function doClone($var) // $v is the original value or a stub object in case of hard references if (\PHP_VERSION_ID >= 70400) { - $zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k); + $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null; } else { $refs[$k] = $cookie; - $zvalIsRef = $vals[$k] === $cookie; + $zvalRef = $vals[$k] === $cookie; } - if ($zvalIsRef) { + if ($zvalRef) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure - if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { - $vals[$k] = $refs[$k] = $v; + if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { + if (\PHP_VERSION_ID >= 70400) { + $v = $vals[$k]; + } else { + $refs[$k] = $vals[$k] = $v; + } if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; } ++$v->refCount; continue; } - $refs[$k] = $vals[$k] = new Stub(); - $refs[$k]->value = $v; - $h = spl_object_id($refs[$k]); - $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; + $vals[$k] = new Stub(); + $vals[$k]->value = $v; $vals[$k]->handle = ++$refsCounter; + + if (\PHP_VERSION_ID >= 70400) { + $hardRefs[$zvalRef] = $vals[$k]; + } else { + $refs[$k] = $vals[$k]; + $h = spl_object_id($refs[$k]); + $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; + } } // Create $stub when the original value $v can not be used directly // If $v is a nested structure, put that structure in array $a @@ -163,12 +173,17 @@ protected function doClone($var) unset($v[$gid]); $a = []; foreach ($v as $gk => &$gv) { - if ($v === $gv) { + if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) { unset($v); $v = new Stub(); $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0]; $v->handle = -1; - $gv = &$hardRefs[spl_object_id($v)]; + if (\PHP_VERSION_ID >= 70400) { + $gv = &$a[$gk]; + $hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv; + } else { + $gv = &$hardRefs[spl_object_id($v)]; + } $gv = $v; } @@ -270,10 +285,12 @@ protected function doClone($var) } } - if ($zvalIsRef) { - $refs[$k]->value = $stub; - } else { + if (!$zvalRef) { $vals[$k] = $stub; + } elseif (\PHP_VERSION_ID >= 70400) { + $hardRefs[$zvalRef]->value = $stub; + } else { + $refs[$k]->value = $stub; } } diff --git a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php index a9518444db9c2..fed2d669a7654 100644 --- a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php @@ -499,12 +499,55 @@ public function testPhp74() [p1] => 123 [p2] => Symfony\Component\VarDumper\Cloner\Stub Object ( - [type] => 4 - [class] => stdClass - [value] => + [type] => 1 + [class] => + [value] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => 4 + [class] => stdClass + [value] => + [cut] => 0 + [handle] => %i + [refCount] => 1 + [position] => 0 + [attr] => Array + ( + ) + + ) + [cut] => 0 - [handle] => %i - [refCount] => 0 + [handle] => 1 + [refCount] => 1 + [position] => 0 + [attr] => Array + ( + ) + + ) + + [p3] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => 1 + [class] => + [value] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => 4 + [class] => stdClass + [value] => + [cut] => 0 + [handle] => %i + [refCount] => 1 + [position] => 0 + [attr] => Array + ( + ) + + ) + + [cut] => 0 + [handle] => 1 + [refCount] => 1 [position] => 0 [attr] => Array ( diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php index 724fbeb7bdb6e..8bd4c496a1715 100644 --- a/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php @@ -6,9 +6,11 @@ class Php74 { public $p1 = 123; public \stdClass $p2; + public \stdClass $p3; public function __construct() { $this->p2 = new \stdClass(); + $this->p3 = &$this->p2; } } diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/FooSerializable.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/FooSerializable.php new file mode 100644 index 0000000000000..63d9fd230c790 --- /dev/null +++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/FooSerializable.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Tests\Fixtures; + +class FooSerializable implements \Serializable +{ + private $foo; + + public function __construct(string $foo) + { + $this->foo = $foo; + } + + public function getFoo(): string + { + return $this->foo; + } + + public function serialize(): string + { + return serialize([$this->getFoo()]); + } + + public function unserialize($str) + { + [$this->foo] = unserialize($str); + } +} diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/MySerializable.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/MySerializable.php new file mode 100644 index 0000000000000..8d649a22a944d --- /dev/null +++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/MySerializable.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Tests\Fixtures; + +class MySerializable implements \Serializable +{ + public function serialize(): string + { + return '123'; + } + + public function unserialize($data): void + { + // no-op + } +} diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/foo-serializable.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/foo-serializable.php index fd4e2671010b3..c6285fd1fbebe 100644 --- a/src/Symfony/Component/VarExporter/Tests/Fixtures/foo-serializable.php +++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/foo-serializable.php @@ -2,7 +2,7 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate( $o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [ - 'C:51:"Symfony\\Component\\VarExporter\\Tests\\FooSerializable":20:{a:1:{i:0;s:3:"bar";}}', + 'C:60:"Symfony\\Component\\VarExporter\\Tests\\Fixtures\\FooSerializable":20:{a:1:{i:0;s:3:"bar";}}', ]), null, [], diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/serializable.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/serializable.php index fcf32278b0685..9e7b52803d924 100644 --- a/src/Symfony/Component/VarExporter/Tests/Fixtures/serializable.php +++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/serializable.php @@ -2,7 +2,7 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate( $o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [ - 'C:50:"Symfony\\Component\\VarExporter\\Tests\\MySerializable":3:{123}', + 'C:59:"Symfony\\Component\\VarExporter\\Tests\\Fixtures\\MySerializable":3:{123}', ]), null, [], diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index cd10c7af37a8a..c10a87761ce8c 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -16,7 +16,9 @@ use Symfony\Component\VarExporter\Exception\ClassNotFoundException; use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; use Symfony\Component\VarExporter\Internal\Registry; +use Symfony\Component\VarExporter\Tests\Fixtures\FooSerializable; use Symfony\Component\VarExporter\Tests\Fixtures\FooUnitEnum; +use Symfony\Component\VarExporter\Tests\Fixtures\MySerializable; use Symfony\Component\VarExporter\VarExporter; class VarExporterTest extends TestCase @@ -137,9 +139,28 @@ public function provideExport() yield ['array-iterator', new \ArrayIterator([123], 1)]; yield ['array-object-custom', new MyArrayObject([234])]; - $value = new MySerializable(); + $errorHandler = set_error_handler(static function (int $errno, string $errstr) use (&$errorHandler) { + if (\E_DEPRECATED === $errno && str_contains($errstr, 'implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead')) { + // We're testing if the component handles deprecated Serializable implementations well. + // This kind of implementation triggers a deprecation warning since PHP 8.1 that we explicitly want to + // ignore here. We probably need to reevaluate this piece of code for PHP 9. + return true; + } + + return $errorHandler ? $errorHandler(...\func_get_args()) : false; + }); - yield ['serializable', [$value, $value]]; + try { + $mySerializable = new MySerializable(); + $fooSerializable = new FooSerializable('bar'); + } finally { + restore_error_handler(); + } + + yield ['serializable', [$mySerializable, $mySerializable]]; + yield ['foo-serializable', $fooSerializable]; + + unset($mySerializable, $fooSerializable, $errorHandler); $value = new MyWakeup(); $value->sub = new MyWakeup(); @@ -211,8 +232,6 @@ public function provideExport() yield ['abstract-parent', new ConcreteClass()]; - yield ['foo-serializable', new FooSerializable('bar')]; - yield ['private-constructor', PrivateConstructor::create('bar')]; yield ['php74-serializable', new Php74Serializable()]; @@ -223,19 +242,6 @@ public function provideExport() } } -class MySerializable implements \Serializable -{ - public function serialize(): string - { - return '123'; - } - - public function unserialize($data) - { - // no-op - } -} - class MyWakeup { public $sub; @@ -384,31 +390,6 @@ public function __construct() } } -class FooSerializable implements \Serializable -{ - private $foo; - - public function __construct(string $foo) - { - $this->foo = $foo; - } - - public function getFoo(): string - { - return $this->foo; - } - - public function serialize(): string - { - return serialize([$this->getFoo()]); - } - - public function unserialize($str) - { - [$this->foo] = unserialize($str); - } -} - class Php74Serializable implements \Serializable { public function __serialize(): array diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index f3e75c9337c2c..1062c7c024b4d 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -810,6 +810,38 @@ public function testTimeoutWithActiveConcurrentStream() } } + public function testTimeoutOnDestruct() + { + $p1 = TestHttpServer::start(8067); + $p2 = TestHttpServer::start(8077); + + $client = $this->getHttpClient(__FUNCTION__); + $start = microtime(true); + $responses = []; + + $responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]); + $responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]); + $responses[] = $client->request('GET', 'http://localhost:8067/timeout-header', ['timeout' => 0.25]); + $responses[] = $client->request('GET', 'http://localhost:8077/timeout-header', ['timeout' => 0.25]); + + try { + while ($response = array_shift($responses)) { + try { + unset($response); + $this->fail(TransportExceptionInterface::class.' expected'); + } catch (TransportExceptionInterface $e) { + } + } + + $duration = microtime(true) - $start; + + $this->assertLessThan(1.0, $duration); + } finally { + $p1->stop(); + $p2->stop(); + } + } + public function testDestruct() { $client = $this->getHttpClient(__FUNCTION__);