Merge branch '4.3' into 4.4

This commit is contained in:
Tobias Schultze 2019-07-29 18:17:34 +02:00
commit f45350338c
22 changed files with 333 additions and 177 deletions

View File

@ -1,6 +1,6 @@
| Q | A
| ------------- | ---
| Branch? | 4.4 for features / 3.4, 4.2 or 4.3 for bug fixes <!-- see below -->
| Branch? | 4.4 for features / 3.4 or 4.3 for bug fixes <!-- see below -->
| Bug fix? | yes/no
| New feature? | yes/no <!-- please update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc -->

View File

@ -7,6 +7,64 @@ in 4.3 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.3.0...v4.3.1
* 4.3.3 (2019-07-28)
* bug #32726 [Messenger] Fix redis last error not cleared between calls (chalasr)
* bug #32760 [HttpKernel] clarify error handler restoring process (xabbuh)
* bug #32730 [Inflector] Fix pluralizing words ending with "son" (norkunas)
* bug #32715 [DI] fix perf issue with lazy autowire error messages (nicolas-grekas)
* bug #32503 Fix multiSelect ChoiceQuestion when answers have spaces (IceMaD)
* bug #32688 [Yaml] fix inline handling when dumping tagged values (xabbuh)
* bug #32710 [Security/Core] align defaults for sodium with PHP 7.4 (nicolas-grekas)
* bug #32644 [WebProfileBundle] Avoid getting right to left style (Arman-Hosseini)
* bug #32689 [HttpClient] rewind stream when using Psr18Client (nicolas-grekas)
* bug #32700 [Messenger] Flatten collection of stamps collected by the traceable middleware (ogizanagi)
* bug #32699 [HttpClient] fix canceling responses in a streaming loop (nicolas-grekas)
* bug #32679 [Intl] relax some date parser patterns (xabbuh)
* bug #31303 [VarDumper] Use \ReflectionReference for determining if a key is a reference (php >= 7.4) (dorumd, nicolas-grekas)
* bug #32485 [Validator] Added support for validation of giga values (kernig)
* bug #32567 [Messenger] pass transport name to factory (Tobion)
* bug #32568 [Messenger] Fix UnrecoverableExceptionInterface handling (LanaiGrunt)
* bug #32604 Properly handle optional tag attributes for !tagged_iterator (apfelbox)
* bug #32571 [HttpClient] fix debug output added to stderr at shutdown (nicolas-grekas)
* bug #32443 [PHPUnitBridge] Mute deprecations triggered from phpunit (greg0ire)
* bug #32572 Bump minimum version of symfony/phpunit-bridge (fancyweb)
* bug #32438 [Serializer] XmlEncoder: don't cast padded strings (ogizanagi)
* bug #32579 [Config] Do not use absolute path when computing the vendor freshness (lyrixx)
* bug #32563 Container*::getServiceIds() should return strings (mathroc)
* bug #32553 [Mailer] Allow register mailer configuration in xml format (Koc)
* bug #32442 Adding missing event_dispatcher wiring for messenger.middleware.send_message (weaverryan)
* bug #32466 [Config] Fix for signatures of typed properties (tvandervorm)
* bug #32501 [FrameworkBundle] Fix descriptor of routes described as callable array (ribeiropaulor)
* bug #32500 [Debug][DebugClassLoader] Include found files instead of requiring them (fancyweb)
* bug #32464 [WebProfilerBundle] Fix Twig 1.x compatibility (yceruto)
* bug #31620 [FrameworkBundle] Inform the user when save_path will be ignored (gnat42)
* bug #32096 Don't assume port 0 for X-Forwarded-Port (alexbowers, xabbuh)
* bug #31820 [SecurityBundle] Fix profiler dump for non-invokable security listeners (chalasr)
* bug #32392 [Messenger] Doctrine Transport: Support setting auto_setup from DSN (bendavies)
* bug #31267 [Translator] Load plurals from mo files properly (Stadly)
* bug #31266 [Translator] Load plurals from po files properly (Stadly)
* bug #32383 [Serializer] AbstractObjectNormalizer ignores the property types of discriminated classes (sandergo90)
* bug #32413 [Messenger] fix publishing headers set on AmqpStamp (Tobion)
* bug #32421 [EventDispatcher] Add tag kernel.rest on 'debug.event_dispatcher' service (lyrixx)
* bug #32398 [Messenger] Removes deprecated call to ReflectionType::__toString() on MessengerPass (brunowowk)
* bug #32379 [SecurityBundle] conditionally register services (xabbuh)
* bug #32380 [Messenger] fix broken key normalization (Tobion)
* bug #32363 [FrameworkBundle] reset cache pools between requests (nicolas-grekas)
* bug #32365 [DI] fix processing of regular parameter bags by MergeExtensionConfigurationPass (nicolas-grekas)
* bug #32187 [PHPUnit] Fixed composer error on Windows (misterx)
* bug #32299 [Lock] Stores must implement `putOffExpiration` (jderusse)
* bug #32302 [Mime] Remove @internal annotations for the serialize methods (francoispluchino)
* bug #32334 [Messenger] Fix authentication for redis transport (alexander-schranz)
* bug #32309 Fixing validation for messenger transports retry_strategy service key (weaverryan)
* bug #32331 [Workflow] only decorate when an event dispatcher was passed (xabbuh)
* bug #32236 [Cache] work aroung PHP memory leak (nicolas-grekas)
* bug #32206 Catch JsonException and rethrow in JsonEncode (phil-davis)
* bug #32211 [Mailer] Fix error message when connecting to a stream raises an error before connect() (fabpot)
* bug #32210 [Mailer] Fix timeout type hint (fabpot)
* bug #32199 [EventDispatcher] improve error messages in the event dispatcher (xabbuh)
* bug #32200 [Security/Core] work around sodium_compat issue (nicolas-grekas)
* 4.3.2 (2019-06-26)
* bug #31954 [PhpunitBridge] Read environment variable from superglobals (greg0ire)

View File

@ -16,9 +16,9 @@ Symfony is the result of the work of many people who made the code better
- Kévin Dunglas (dunglas)
- Maxime Steinhausser (ogizanagi)
- Ryan Weaver (weaverryan)
- Javier Eguiluz (javier.eguiluz)
- Jakub Zalas (jakubzalas)
- Johannes S (johannes)
- Javier Eguiluz (javier.eguiluz)
- Roland Franssen (ro0)
- Kris Wallsmith (kriswallsmith)
- Grégoire Pineau (lyrixx)
@ -28,52 +28,53 @@ Symfony is the result of the work of many people who made the code better
- Romain Neutron (romain)
- Pascal Borreli (pborreli)
- Wouter De Jong (wouterj)
- Yonel Ceruto (yonelceruto)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
- Yonel Ceruto (yonelceruto)
- Martin Hasoň (hason)
- Hamza Amrouche (simperfit)
- Jeremy Mikola (jmikola)
- Jean-François Simon (jfsimon)
- Jules Pietri (heah)
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- Eriksen Costa (eriksencosta)
- Hamza Amrouche (simperfit)
- Guilhem Niot (energetick)
- Alexander M. Turek (derrabus)
- Sarah Khalil (saro0h)
- Jonathan Wage (jwage)
- Tobias Nyholm (tobias)
- Lynn van der Berg (kjarli)
- Jérémy DERUSSÉ (jderusse)
- Lynn van der Berg (kjarli)
- Diego Saint Esteben (dosten)
- Alexandre Salomé (alexandresalome)
- William Durand (couac)
- ornicar
- Alexander M. Turek (derrabus)
- Dany Maillard (maidmaid)
- Francis Besset (francisbesset)
- stealth35 (stealth35)
- Alexander Mols (asm89)
- Matthias Pigulla (mpdude)
- Bulat Shakirzyanov (avalanche123)
- Konstantin Myakshin (koc)
- Pierre du Plessis (pierredup)
- Grégoire Paris (greg0ire)
- Saša Stamenković (umpirsky)
- Peter Rehm (rpet)
- Pierre du Plessis (pierredup)
- Kevin Bond (kbond)
- Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik
- Diego Saint Esteben (dii3g0)
- Grégoire Paris (greg0ire)
- Konstantin Kudryashov (everzet)
- Gábor Egyed (1ed)
- Thomas Calvet (fancyweb)
- Konstantin Kudryashov (everzet)
- Titouan Galopin (tgalopin)
- Konstantin Myakshin (koc)
- Valentin Udaltsov (vudaltsov)
- Bilal Amarni (bamarni)
- Mathieu Piot (mpiot)
- David Maicher (dmaicher)
- Florin Patan (florinpatan)
- Valentin Udaltsov (vudaltsov)
- Gabriel Ostrolucký (gadelat)
- Vladimir Reznichenko (kalessil)
- Jáchym Toušek (enumag)
@ -89,13 +90,13 @@ Symfony is the result of the work of many people who made the code better
- Dariusz Górecki (canni)
- Douglas Greenshields (shieldo)
- David Buchmann (dbu)
- Jan Schädlich (jschaedl)
- Dariusz Ruminski
- Lee McDermott
- Brandon Turner
- Luis Cordova (cordoval)
- Graham Campbell (graham)
- Daniel Holmes (dholmes)
- Thomas Calvet (fancyweb)
- Toni Uebernickel (havvg)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
@ -120,7 +121,7 @@ Symfony is the result of the work of many people who made the code better
- Peter Kokot (maastermedia)
- Jacob Dreesen (jdreesen)
- Florian Voutzinos (florianv)
- Jan Schädlich (jschaedl)
- Sebastiaan Stok (sstok)
- Colin Frei
- Javier Spagnoletti (phansys)
- Adrien Brault (adrienbrault)
@ -128,30 +129,29 @@ Symfony is the result of the work of many people who made the code better
- Daniel Wehner (dawehner)
- excelwebzone
- Gordon Franke (gimler)
- Sebastiaan Stok (sstok)
- Fabien Pennequin (fabienpennequin)
- Théo FIDRY (theofidry)
- Teoh Han Hui (teohhanhui)
- Oskar Stark (oskarstark)
- Eric GELOEN (gelo)
- Joel Wurtz (brouznouf)
- Lars Strojny (lstrojny)
- Tugdual Saunier (tucksaun)
- Alex Pott
- Jannik Zschiesche (apfelbox)
- Robert Schönthal (digitalkaoz)
- Florian Lonqueu-Brochard (florianlb)
- Oskar Stark (oskarstark)
- Gabriel Caruso (carusogabriel)
- Stefano Sala (stefano.sala)
- Evgeniy (ewgraf)
- Alex Pott
- Vincent AUBERT (vincent)
- Juti Noppornpitak (shiroyuki)
- Teoh Han Hui (teohhanhui)
- Anthony MARTIN (xurudragon)
- Tigran Azatyan (tigranazatyan)
- Sebastian Hörl (blogsh)
- Daniel Gomes (danielcsgomes)
- Gabriel Caruso
- Hidenori Goto (hidenorigoto)
- Arnaud Kleinpeter (nanocom)
- Jannik Zschiesche (apfelbox)
- Guilherme Blanco (guilhermeblanco)
- SpacePossum
- Pablo Godel (pgodel)
@ -164,18 +164,19 @@ Symfony is the result of the work of many people who made the code better
- jwdeitch
- Mikael Pajunen
- François-Xavier de Guillebon (de-gui_f)
- Alessandro Chitolina (alekitto)
- Massimiliano Arione (garak)
- Niels Keurentjes (curry684)
- Vyacheslav Pavlov
- Richard van Laak (rvanlaak)
- Richard Shank (iampersistent)
- Thomas Rabaix (rande)
- Rouven Weßling (realityking)
- Alexander Schranz (alexander-schranz)
- Clemens Tolboom
- Helmer Aaviksoo
- Alessandro Chitolina (alekitto)
- Hiromi Hishida (77web)
- Matthieu Ouellette-Vachon (maoueh)
- Massimiliano Arione (garak)
- Michał Pipa (michal.pipa)
- Dawid Nowak
- George Mponos (gmponos)
@ -186,7 +187,7 @@ Symfony is the result of the work of many people who made the code better
- GDIBass
- Samuel NELA (snela)
- Vincent Touzet (vincenttouzet)
- Alexander Schranz (alexander-schranz)
- Jérôme Parmentier (lctrs)
- jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent)
- James Halsall (jaitsu)
- Matthieu Napoli (mnapoli)
@ -194,6 +195,7 @@ Symfony is the result of the work of many people who made the code better
- Warnar Boekkooi (boekkooi)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
- Yanick Witschi (toflar)
- Marek Štípek (maryo)
- Daniel Espendiller
- Possum
@ -213,7 +215,7 @@ Symfony is the result of the work of many people who made the code better
- Andreas Hucks (meandmymonkey)
- Tom Van Looy (tvlooy)
- Noel Guilbert (noel)
- Yanick Witschi (toflar)
- Stadly
- Stepan Anchugov (kix)
- bronze1man
- sun (sun)
@ -231,6 +233,7 @@ Symfony is the result of the work of many people who made the code better
- Michael Lee (zerustech)
- Matthieu Auger (matthieuauger)
- Leszek Prabucki (l3l0)
- Ben Davies (bendavies)
- Fabien Bourigault (fbourigault)
- François Zaninotto (fzaninotto)
- Dustin Whittle (dustinwhittle)
@ -299,6 +302,7 @@ Symfony is the result of the work of many people who made the code better
- Jan Sorgalla (jsor)
- Ray
- Chekote
- François Pluchino (francoispluchino)
- Antoine Makdessi (amakdessi)
- Thomas Adam
- Jhonny Lidfors (jhonne)
@ -316,7 +320,6 @@ Symfony is the result of the work of many people who made the code better
- Giorgio Premi
- renanbr
- Alex Rock (pierstoval)
- Ben Davies (bendavies)
- Beau Simensen (simensen)
- Michael Hirschler (mvhirsch)
- Robert Kiss (kepten)
@ -325,18 +328,18 @@ Symfony is the result of the work of many people who made the code better
- Kim Hemsø Rasmussen (kimhemsoe)
- Pascal Luna (skalpa)
- Wouter Van Hecke
- Jérôme Parmentier (lctrs)
- Peter Kruithof (pkruithof)
- Michael Holm (hollo)
- Andreas Braun
- Mathieu Lechat
- Marc Weistroff (futurecat)
- Simon Mönch (sm)
- Christian Schmidt
- Patrick Landolt (scube)
- MatTheCat
- Chad Sikorra (chadsikorra)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
- Stadly
- Manuel Kiessling (manuelkiessling)
- Atsuhiro KUBO (iteman)
- Quynh Xuan Nguyen (xuanquynh)
@ -344,6 +347,7 @@ Symfony is the result of the work of many people who made the code better
- Serkan Yildiz (srknyldz)
- Andrew Moore (finewolf)
- Bertrand Zuchuat (garfield-fr)
- Tomas Norkūnas (norkunas)
- Sullivan SENECHAL (soullivaneuh)
- Gabor Toth (tgabi333)
- realmfoo
@ -354,7 +358,6 @@ Symfony is the result of the work of many people who made the code better
- Wouter J
- Ismael Ambrosi (iambrosi)
- Emmanuel BORGES (eborges78)
- François Pluchino (francoispluchino)
- Aurelijus Valeiša (aurelijus)
- Jan Decavele (jandc)
- Gustavo Piltcher
@ -394,7 +397,6 @@ Symfony is the result of the work of many people who made the code better
- Christian Gärtner (dagardner)
- Tomasz Kowalczyk (thunderer)
- Artur Eshenbrener
- Andreas Braun
- Arjen van der Meijden
- Damien Alexandre (damienalexandre)
- Thomas Perez (scullwm)
@ -407,6 +409,7 @@ Symfony is the result of the work of many people who made the code better
- David Badura (davidbadura)
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
- Thomas Bisignani (toma)
- Sanpi
- Eduardo Gulias (egulias)
- giulio de donato (liuggio)
@ -418,11 +421,13 @@ Symfony is the result of the work of many people who made the code better
- Kirill chEbba Chebunin (chebba)
- Greg Thornton (xdissent)
- Martin Hujer (martinhujer)
- Alex Bowers
- Philipp Cordes
- Costin Bereveanu (schniper)
- Loïc Chardonnet (gnusat)
- Marek Kalnik (marekkalnik)
- Vyacheslav Salakhutdinov (megazoll)
- Sébastien Alfaiate (seb33300)
- Hassan Amouhzi
- Tamas Szijarto
- Michele Locati
@ -445,6 +450,7 @@ Symfony is the result of the work of many people who made the code better
- Krzysztof Piasecki (krzysztek)
- Maximilian Reichel (phramz)
- Loick Piera (pyrech)
- Alain Hippolyte (aloneh)
- Karoly Negyesi (chx)
- Ivan Kurnosov
- Xavier HAUSHERR
@ -453,6 +459,7 @@ Symfony is the result of the work of many people who made the code better
- Miha Vrhovnik
- Alessandro Desantis
- hubert lecorche (hlecorche)
- Arman Hosseini
- Marc Morales Valldepérez (kuert)
- Jean-Baptiste GOMOND (mjbgo)
- Vadim Kharitonov (virtuozzz)
@ -483,6 +490,7 @@ Symfony is the result of the work of many people who made the code better
- Alessandro Lai (jean85)
- Arturs Vonda
- Josip Kruslin
- Matthew Smeets
- Asmir Mustafic (goetas)
- vagrant
- Aurimas Niekis (gcds)
@ -521,6 +529,7 @@ Symfony is the result of the work of many people who made the code better
- Rhodri Pugh (rodnaph)
- Sam Fleming (sam_fleming)
- Alex Bakhturin
- Patrick Reimers (preimers)
- Pol Dellaiera (drupol)
- insekticid
- Alexander Obuhovich (aik099)
@ -533,6 +542,7 @@ Symfony is the result of the work of many people who made the code better
- Frank Neff (fneff)
- Roman Lapin (memphys)
- Yoshio HANAWA
- Jan van Thoor (janvt)
- Gladhon
- Haralan Dobrev (hkdobrev)
- Sebastian Bergmann
@ -542,8 +552,9 @@ Symfony is the result of the work of many people who made the code better
- Sergio Santoro
- Robin van der Vleuten (robinvdvleuten)
- Philipp Rieber (bicpi)
- Tomas Norkūnas (norkunas)
- Manuel de Ruiter (manuel)
- Nathanael Noblet (gnat)
- nikos.sotiropoulos
- Eduardo Oliveira (entering)
- Ilya Antipenko (aivus)
- Ricardo Oliveira (ricardolotr)
@ -551,7 +562,6 @@ Symfony is the result of the work of many people who made the code better
- ondrowan
- Barry vd. Heuvel (barryvdh)
- Craig Duncan (duncan3dc)
- Sébastien Alfaiate (seb33300)
- Evan S Kaufman (evanskaufman)
- mcben
- Jérôme Vieilledent (lolautruche)
@ -607,7 +617,6 @@ Symfony is the result of the work of many people who made the code better
- NothingWeAre
- Ryan
- Alexander Deruwe (aderuwe)
- Alain Hippolyte (aloneh)
- Dave Hulbert (dave1010)
- Ivan Rey (ivanrey)
- Marcin Chyłek (songoq)
@ -629,6 +638,7 @@ Symfony is the result of the work of many people who made the code better
- Geoffrey Tran (geoff)
- Jan Behrens
- Mantas Var (mvar)
- Chris Tanaskoski
- Sebastian Krebs
- Piotr Stankowski
- Baptiste Leduc (bleduc)
@ -640,6 +650,7 @@ Symfony is the result of the work of many people who made the code better
- vitaliytv
- Dalibor Karlović (dkarlovi)
- Sebastian Blum
- Alexis Lefebvre
- aubx
- Marvin Butkereit
- Renan
@ -751,7 +762,6 @@ Symfony is the result of the work of many people who made the code better
- Tiago Brito (blackmx)
-
- Richard van den Brand (ricbra)
- Thomas Bisignani (toma)
- develop
- flip111
- Greg Anderson
@ -781,7 +791,6 @@ Symfony is the result of the work of many people who made the code better
- Dominik Ritter (dritter)
- Sebastian Grodzicki (sgrodzicki)
- Jeroen van den Enden (stoefke)
- nikos.sotiropoulos
- Pascal Helfenstein
- Anthony GRASSIOT (antograssiot)
- Baldur Rensch (brensch)
@ -795,6 +804,7 @@ Symfony is the result of the work of many people who made the code better
- Tarjei Huse (tarjei)
- Besnik Br
- Jose Gonzalez
- Jonathan (jls-esokia)
- Oleksii Zhurbytskyi
- Dariusz Ruminski
- Joshua Nye
@ -822,6 +832,7 @@ Symfony is the result of the work of many people who made the code better
- Marc Morera (mmoreram)
- Saif Eddin Gmati (azjezz)
- BENOIT POLASZEK (bpolaszek)
- Mathieu Rochette (mathroc)
- Andrew Hilobok (hilobok)
- Noah Heck (myesain)
- Christian Soronellas (theunic)
@ -887,7 +898,6 @@ Symfony is the result of the work of many people who made the code better
- Sergey Zolotov (enleur)
- Maksim Kotlyar (makasim)
- Neil Ferreira
- Nathanael Noblet (gnat)
- Indra Gunawan (indragunawan)
- Julie Hourcade (juliehde)
- Dmitry Parnas (parnas)
@ -914,6 +924,7 @@ Symfony is the result of the work of many people who made the code better
- Stefan Kruppa
- mmokhi
- corphi
- JoppeDC
- grizlik
- Derek ROTH
- Ben Johnson
@ -921,6 +932,7 @@ Symfony is the result of the work of many people who made the code better
- Dmytro Boiko (eagle)
- Shin Ohno (ganchiku)
- Geert De Deckere (geertdd)
- Ion Bazan (ionbazan)
- Jacek Jędrzejewski (jacek.jedrzejewski)
- Jan Kramer (jankramer)
- abdul malik ikhsan (samsonasik)
@ -977,12 +989,12 @@ Symfony is the result of the work of many people who made the code better
- Benoît Merlet (trompette)
- Koen Kuipers
- datibbaw
- Pablo Lozano (arkadis)
- Erik Saunier (snickers)
- Rootie
- Kyle
- Daniel Alejandro Castro Arellano (lexcast)
- sensio
- Chris Tanaskoski
- Thomas Jarrand
- Antoine Bluchet (soyuka)
- Sebastien Morel (plopix)
@ -1006,7 +1018,6 @@ Symfony is the result of the work of many people who made the code better
- Mikkel Paulson
- ergiegonzaga
- Farhad Safarov
- Alexis Lefebvre
- Liverbool (liverbool)
- Sam Malone
- Phan Thanh Ha (haphan)
@ -1058,6 +1069,7 @@ Symfony is the result of the work of many people who made the code better
- dantleech
- Bastien DURAND (deamon)
- Xavier Leune
- Sander Goossens (sandergo90)
- Rudy Onfroy
- Tero Alén (tero)
- Stanislav Kocanda
@ -1068,6 +1080,7 @@ Symfony is the result of the work of many people who made the code better
- Silvio Ginter
- MGDSoft
- Vadim Tyukov (vatson)
- Arman
- David Wolter (davewww)
- Sortex
- chispita
@ -1099,6 +1112,7 @@ Symfony is the result of the work of many people who made the code better
- Mert Simsek (mrtsmsk0)
- Lin Clark
- Jeremy David (jeremy.david)
- Timo Bakx (timobakx)
- Jordi Rejas
- Troy McCabe
- Ville Mattila
@ -1113,7 +1127,6 @@ Symfony is the result of the work of many people who made the code better
- nacho
- Piotr Antosik (antek88)
- Artem Lopata
- Patrick Reimers (preimers)
- Sergey Novikov (s12v)
- Marcos Quesada (marcos_quesada)
- Matthew Vickery (mattvick)
@ -1139,6 +1152,7 @@ Symfony is the result of the work of many people who made the code better
- Michał Strzelecki
- Soner Sayakci
- hugofonseca (fonsecas72)
- Marc Duboc (icemad)
- Martynas Narbutas
- Toon Verwerft (veewee)
- Bailey Parker
@ -1182,7 +1196,6 @@ Symfony is the result of the work of many people who made the code better
- Jochen Bayer (jocl)
- Patrick Carlo-Hickman
- Bruno MATEU
- Alex Bowers
- Jeremy Bush
- wizhippo
- Mathias STRASSER (roukmoute)
@ -1237,7 +1250,9 @@ Symfony is the result of the work of many people who made the code better
- Max Voloshin (maxvoloshin)
- Nicolas Fabre (nfabre)
- Raul Rodriguez (raul782)
- Piet Steinhart
- mshavliuk
- Rémy LESCALLIER
- WybrenKoelmans
- Derek Lambert
- MightyBranch
@ -1263,10 +1278,10 @@ Symfony is the result of the work of many people who made the code better
- Marco
- Marc Torres
- Alberto Aldegheri
- Philippe Segatori
- Dmitri Petmanson
- heccjj
- Alexandre Melard
- Jonathan (jls-esokia)
- Jay Klehr
- Sergey Yuferev
- Tobias Stöckler
@ -1385,6 +1400,7 @@ Symfony is the result of the work of many people who made the code better
- Tom Corrigan (tomcorrigan)
- Luis Galeas
- Martin Pärtel
- Bastien Jaillot (bastnic)
- Frédéric Bouchery (fbouchery)
- Patrick Daley (padrig)
- Xavier Briand (xavierbriand)
@ -1408,7 +1424,6 @@ Symfony is the result of the work of many people who made the code better
- Dāvis Zālītis (k0d3r1s)
- Carsten Nielsen (phreaknerd)
- Roger Guasch (rogerguasch)
- Mathieu Rochette
- Jay Severson
- René Kerner
- Nathaniel Catchpole
@ -1456,6 +1471,7 @@ Symfony is the result of the work of many people who made the code better
- Ergie Gonzaga
- Matthew J Mucklo
- AnrDaemon
- Emre Akinci (emre)
- fdgdfg (psampaz)
- Stéphane Seng
- Maxwell Vandervelde
@ -1567,6 +1583,7 @@ Symfony is the result of the work of many people who made the code better
- Arnau González (arnaugm)
- Simon Bouland (bouland)
- Jibé Barth (jibbarth)
- Julien Montel (julienmgel)
- Matthew Foster (mfoster)
- Reyo Stallenberg (reyostallenberg)
- Paul Seiffert (seiffert)
@ -1587,6 +1604,7 @@ Symfony is the result of the work of many people who made the code better
- Ulugbek Miniyarov
- Jeremy Benoist
- Michal Gebauer
- Phil Davis
- Gleb Sidora
- David Stone
- Jovan Perovic (jperovic)
@ -1601,6 +1619,7 @@ Symfony is the result of the work of many people who made the code better
- Andreas
- Markus
- Daniel Gorgan
- kernig
- Thomas Chmielowiec
- shdev
- Andrey Ryaguzov
@ -1611,6 +1630,7 @@ Symfony is the result of the work of many people who made the code better
- Mickael GOETZ
- Maciej Schmidt
- Dennis Væversted
- Timon van der Vorm
- nuncanada
- flack
- František Bereň
@ -1634,6 +1654,7 @@ Symfony is the result of the work of many people who made the code better
- me_shaon
- 蝦米
- Grayson Koonce (breerly)
- Mardari Dorel (dorumd)
- Andrey Helldar (helldar)
- Karim Cassam Chenaï (ka)
- Maksym Slesarenko (maksym_slesarenko)
@ -1683,7 +1704,6 @@ Symfony is the result of the work of many people who made the code better
- Brian Graham (incognito)
- Kevin Vergauwen (innocenzo)
- Alessio Baglio (ioalessio)
- Jan van Thoor (janvt)
- Johannes Müller (johmue)
- Jordi Llonch (jordillonch)
- Nicholas Ruunu (nicholasruunu)
@ -1754,6 +1774,7 @@ Symfony is the result of the work of many people who made the code better
- thib92
- Rudolf Ratusiński
- Bertalan Attila
- Amin Hosseini (aminh)
- AmsTaFF (amstaff)
- Simon Müller (boscho)
- Yannick Bensacq (cibou)
@ -1830,7 +1851,6 @@ Symfony is the result of the work of many people who made the code better
- Marco Lipparini
- Haritz
- Matthieu Prat
- Ion Bazan
- Grummfy
- Paul Le Corre
- Filipe Guerra
@ -1855,7 +1875,6 @@ Symfony is the result of the work of many people who made the code better
- Alexis MARQUIS
- Gerrit Drost
- Linnaea Von Lavia
- Simon Mönch
- Javan Eskander
- Lenar Lõhmus
- Cristian Gonzalez
@ -1873,6 +1892,7 @@ Symfony is the result of the work of many people who made the code better
- Klaas Naaijkens
- Daniel González Cerviño
- Rafał
- Lctrs
- Achilles Kaloeridis (achilles)
- Adria Lopez (adlpz)
- Aaron Scherer (aequasi)
@ -1964,11 +1984,13 @@ Symfony is the result of the work of many people who made the code better
- goohib
- Chi-teck
- Tom Counsell
- George Bateman
- Xavier HAUSHERR
- Ron Gähler
- Edwin Hageman
- Mantas Urnieža
- temperatur
- misterx
- Cas
- Dusan Kasan
- Karolis
@ -2015,6 +2037,7 @@ Symfony is the result of the work of many people who made the code better
- Alexandru Bucur
- cmfcmf
- Drew Butler
- Alexey Berezuev
- Steve Müller
- Andras Ratz
- andreabreu98
@ -2059,6 +2082,7 @@ Symfony is the result of the work of many people who made the code better
- Sébastien HOUZE
- Abdulkadir N. A.
- Adam Klvač
- Bruno Nogueira Nascimento Wowk
- Yevgen Kovalienia
- Lebnik
- nsbx
@ -2068,6 +2092,7 @@ Symfony is the result of the work of many people who made the code better
- Elan Ruusamäe
- Jon Dufresne
- Thorsten Hallwas
- Alex Nostadt
- Michael Squires
- Egor Gorbachev
- Derek Stephen McLean
@ -2187,6 +2212,7 @@ Symfony is the result of the work of many people who made the code better
- ollie harridge (ollietb)
- Dimitri Gritsajuk (ottaviano)
- Paul Andrieux (paulandrieux)
- Paulo Ribeiro (paulo)
- Paweł Szczepanek (pauluz)
- Philippe Degeeter (pdegeeter)
- Christian López Espínola (penyaskito)
@ -2215,6 +2241,7 @@ Symfony is the result of the work of many people who made the code better
- Tom Newby (tomnewbyau)
- Andrew Clark (tqt_andrew_clark)
- David Lumaye (tux1124)
- Roman Tymoshyk (tymoshyk)
- Tyler Stroud (tystr)
- Moritz Kraft (userfriendly)
- Víctor Mateo (victormateo)
@ -2232,6 +2259,7 @@ Symfony is the result of the work of many people who made the code better
- simpson
- drublic
- Andreas Streichardt
- Alexandre Segura
- Pascal Hofmann
- smokeybear87
- Gustavo Adrian
@ -2255,7 +2283,6 @@ Symfony is the result of the work of many people who made the code better
- Mohamed Karnichi (amiral)
- Andrew Carter (andrewcarteruk)
- Adam Elsodaney (archfizz)
- Pablo Lozano (arkadis)
- Gregório Bonfante Borba (bonfante)
- Bogdan Rancichi (devck)
- Daniel Kolvik (dkvk)

View File

@ -77,7 +77,7 @@ Form
FrameworkBundle
---------------
* Deprecated the `framework.templating` option, use Twig instead.
* Deprecated the `framework.templating` option, configure the Twig bundle instead.
* Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will
be mandatory in 5.0.
* Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead.

View File

@ -217,7 +217,7 @@ FrameworkBundle
* Dropped support for booting the kernel before running `WebTestCase::createClient()`. `createClient()` will throw an
exception if the kernel was already booted before.
* Removed the `framework.templating` option, use Twig instead.
* Removed the `framework.templating` option, configure the Twig bundle instead.
* The project dir argument of the constructor of `AssetsInstallCommand` is required.
* Removed support for `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method`
instead where `serviceOrFqcn` is either the service ID when using controllers as services or the FQCN of the controller.

View File

@ -15,7 +15,7 @@ CHANGELOG
4.3.0
-----
* Deprecated the `framework.templating` option, use Twig instead.
* Deprecated the `framework.templating` option, configure the Twig bundle instead.
* Added `WebTestAssertionsTrait` (included by default in `WebTestCase`)
* Renamed `Client` to `KernelBrowser`
* Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will

View File

@ -605,7 +605,7 @@ class Configuration implements ConfigurationInterface
->arrayNode('templating')
->info('templating configuration')
->canBeEnabled()
->setDeprecated('The "%path%.%node%" configuration is deprecated since Symfony 4.3. Use the "twig" service directly instead.')
->setDeprecated('The "%path%.%node%" configuration is deprecated since Symfony 4.3. Configure the "twig" section provided by the Twig Bundle instead.')
->beforeNormalization()
->ifTrue(function ($v) { return false === $v || \is_array($v) && false === $v['enabled']; })
->then(function () { return ['enabled' => false, 'engines' => false]; })

View File

@ -15,10 +15,9 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
/**
* TimeDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
@ -77,7 +76,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
/**
* Sets the request events.
*
* @param array $events The request events
* @param StopwatchEvent[] $events The request events
*/
public function setEvents(array $events)
{
@ -91,7 +90,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
/**
* Gets the request events.
*
* @return array The request events
* @return StopwatchEvent[] The request events
*/
public function getEvents()
{

View File

@ -41,6 +41,9 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
break;
case KernelEvents::TERMINATE:
$token = $event->getResponse()->headers->get('X-Debug-Token');
if (null === $token) {
break;
}
// There is a very special case when using built-in AppCache class as kernel wrapper, in the case
// of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A].
// In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID
@ -65,12 +68,18 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
break;
case KernelEvents::RESPONSE:
$token = $event->getResponse()->headers->get('X-Debug-Token');
if (null === $token) {
break;
}
$this->stopwatch->stopSection($token);
break;
case KernelEvents::TERMINATE:
// In the special case described in the `preDispatch` method above, the `$token` section
// does not exist, then closing it throws an exception which must be caught.
$token = $event->getResponse()->headers->get('X-Debug-Token');
if (null === $token) {
break;
}
try {
$this->stopwatch->stopSection($token);
} catch (\LogicException $e) {

View File

@ -62,15 +62,13 @@ class TraceableEventDispatcherTest extends TestCase
public function testStopwatchStopControllerOnRequestEvent()
{
$stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')
->setMethods(['isStarted', 'stop', 'stopSection'])
->setMethods(['isStarted', 'stop'])
->getMock();
$stopwatch->expects($this->once())
->method('isStarted')
->willReturn(true);
$stopwatch->expects($this->once())
->method('stop');
$stopwatch->expects($this->once())
->method('stopSection');
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch);

View File

@ -308,7 +308,7 @@ class ConnectionTest extends TestCase
);
// makes sure the channel looks connected, so it's not re-created
$amqpChannel->expects($this->exactly(2))->method('isConnected')->willReturn(true);
$amqpChannel->expects($this->any())->method('isConnected')->willReturn(true);
$amqpChannel->expects($this->exactly(2))->method('setPrefetchCount')->with(2);
$connection = Connection::fromDsn('amqp://localhost?prefetch_count=2', [], $factory);
@ -317,30 +317,57 @@ class ConnectionTest extends TestCase
$connection->setup();
}
public function testItDelaysTheMessage()
public function testAutoSetupWithDelayDeclaresExchangeQueuesAndDelay()
{
$amqpConnection = $this->createMock(\AMQPConnection::class);
$amqpChannel = $this->createMock(\AMQPChannel::class);
$delayQueue = $this->createMock(\AMQPQueue::class);
$factory = $this->createMock(AmqpFactory::class);
$factory->method('createConnection')->willReturn($amqpConnection);
$factory->method('createChannel')->willReturn($amqpChannel);
$factory->method('createQueue')->willReturn($delayQueue);
$factory->method('createQueue')->will($this->onConsecutiveCalls(
$amqpQueue = $this->createMock(\AMQPQueue::class),
$delayQueue = $this->createMock(\AMQPQueue::class)
));
$factory->method('createExchange')->will($this->onConsecutiveCalls(
$amqpExchange = $this->getMockBuilder(\AMQPExchange::class)->disableOriginalConstructor()->getMock(),
$delayExchange = $this->getMockBuilder(\AMQPExchange::class)->disableOriginalConstructor()->getMock()
$amqpExchange = $this->createMock(\AMQPExchange::class),
$delayExchange = $this->createMock(\AMQPExchange::class)
));
$amqpExchange->expects($this->once())->method('setName')->with(self::DEFAULT_EXCHANGE_NAME);
$amqpExchange->expects($this->once())->method('declareExchange');
$amqpQueue->expects($this->once())->method('setName')->with(self::DEFAULT_EXCHANGE_NAME);
$amqpQueue->expects($this->once())->method('declareQueue');
$delayExchange->expects($this->once())->method('setName')->with('delay');
$delayExchange->expects($this->once())->method('declareExchange');
$delayExchange->expects($this->once())->method('publish');
$delayQueue->expects($this->once())->method('setName')->with('delay_queue_messages__5000');
$connection = Connection::fromDsn('amqp://localhost', [], $factory);
$connection->publish('{}', ['x-some-headers' => 'foo'], 5000);
}
public function testItDelaysTheMessage()
{
$amqpConnection = $this->createMock(\AMQPConnection::class);
$amqpChannel = $this->createMock(\AMQPChannel::class);
$factory = $this->createMock(AmqpFactory::class);
$factory->method('createConnection')->willReturn($amqpConnection);
$factory->method('createChannel')->willReturn($amqpChannel);
$factory->method('createQueue')->will($this->onConsecutiveCalls(
$this->createMock(\AMQPQueue::class),
$delayQueue = $this->createMock(\AMQPQueue::class)
));
$factory->method('createExchange')->will($this->onConsecutiveCalls(
$this->createMock(\AMQPExchange::class),
$delayExchange = $this->createMock(\AMQPExchange::class)
));
$delayQueue->expects($this->once())->method('setName')->with('delay_messages__5000');
$delayQueue->expects($this->once())->method('setArguments')->with([
'x-message-ttl' => 5000,
'x-expires' => 5000 + 10000,
'x-dead-letter-exchange' => self::DEFAULT_EXCHANGE_NAME,
'x-dead-letter-routing-key' => '',
]);
@ -358,22 +385,18 @@ class ConnectionTest extends TestCase
{
$amqpConnection = $this->createMock(\AMQPConnection::class);
$amqpChannel = $this->createMock(\AMQPChannel::class);
$delayQueue = $this->createMock(\AMQPQueue::class);
$factory = $this->createMock(AmqpFactory::class);
$factory->method('createConnection')->willReturn($amqpConnection);
$factory->method('createChannel')->willReturn($amqpChannel);
$factory->method('createQueue')->willReturn($delayQueue);
$factory->method('createExchange')->will($this->onConsecutiveCalls(
$amqpExchange = $this->getMockBuilder(\AMQPExchange::class)->disableOriginalConstructor()->getMock(),
$delayExchange = $this->getMockBuilder(\AMQPExchange::class)->disableOriginalConstructor()->getMock()
$factory->method('createQueue')->will($this->onConsecutiveCalls(
$this->createMock(\AMQPQueue::class),
$delayQueue = $this->createMock(\AMQPQueue::class)
));
$factory->method('createExchange')->will($this->onConsecutiveCalls(
$this->createMock(\AMQPExchange::class),
$delayExchange = $this->createMock(\AMQPExchange::class)
));
$amqpExchange->expects($this->once())->method('setName')->with(self::DEFAULT_EXCHANGE_NAME);
$amqpExchange->expects($this->once())->method('declareExchange');
$delayExchange->expects($this->once())->method('setName')->with('delay');
$delayExchange->expects($this->once())->method('declareExchange');
$connectionOptions = [
'retry' => [
@ -383,9 +406,10 @@ class ConnectionTest extends TestCase
$connection = Connection::fromDsn('amqp://localhost', $connectionOptions, $factory);
$delayQueue->expects($this->once())->method('setName')->with('delay_queue_messages__120000');
$delayQueue->expects($this->once())->method('setName')->with('delay_messages__120000');
$delayQueue->expects($this->once())->method('setArguments')->with([
'x-message-ttl' => 120000,
'x-expires' => 120000 + 10000,
'x-dead-letter-exchange' => self::DEFAULT_EXCHANGE_NAME,
'x-dead-letter-routing-key' => '',
]);
@ -467,23 +491,19 @@ class ConnectionTest extends TestCase
{
$amqpConnection = $this->createMock(\AMQPConnection::class);
$amqpChannel = $this->createMock(\AMQPChannel::class);
$delayQueue = $this->createMock(\AMQPQueue::class);
$factory = $this->createMock(AmqpFactory::class);
$factory->method('createConnection')->willReturn($amqpConnection);
$factory->method('createChannel')->willReturn($amqpChannel);
$factory->method('createQueue')->willReturn($delayQueue);
$factory->method('createQueue')->will($this->onConsecutiveCalls(
$this->createMock(\AMQPQueue::class),
$delayQueue = $this->createMock(\AMQPQueue::class)
));
$factory->method('createExchange')->will($this->onConsecutiveCalls(
$amqpExchange = $this->createMock(\AMQPExchange::class),
$this->createMock(\AMQPExchange::class),
$delayExchange = $this->createMock(\AMQPExchange::class)
));
$amqpExchange->expects($this->once())->method('setName')->with(self::DEFAULT_EXCHANGE_NAME);
$amqpExchange->expects($this->once())->method('declareExchange');
$delayExchange->expects($this->once())->method('setName')->with('delay');
$delayExchange->expects($this->once())->method('declareExchange');
$connectionOptions = [
'retry' => [
'dead_routing_key' => 'my_dead_routing_key',
@ -492,9 +512,10 @@ class ConnectionTest extends TestCase
$connection = Connection::fromDsn('amqp://localhost', $connectionOptions, $factory);
$delayQueue->expects($this->once())->method('setName')->with('delay_queue_messages_routing_key_120000');
$delayQueue->expects($this->once())->method('setName')->with('delay_messages_routing_key_120000');
$delayQueue->expects($this->once())->method('setArguments')->with([
'x-message-ttl' => 120000,
'x-expires' => 120000 + 10000,
'x-dead-letter-exchange' => self::DEFAULT_EXCHANGE_NAME,
'x-dead-letter-routing-key' => 'routing_key',
]);

View File

@ -15,6 +15,8 @@ use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\SchemaConfig;
use Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@ -102,25 +104,26 @@ class ConnectionTest extends TestCase
private function getDBALConnectionMock()
{
$driverConnection = $this->getMockBuilder(\Doctrine\DBAL\Connection::class)
->disableOriginalConstructor()
->getMock();
$platform = $this->getMockBuilder(AbstractPlatform::class)
->getMock();
$driverConnection = $this->createMock(\Doctrine\DBAL\Connection::class);
$platform = $this->createMock(AbstractPlatform::class);
$platform->method('getWriteLockSQL')->willReturn('FOR UPDATE');
$configuration = $this->getMockBuilder(\Doctrine\DBAL\Configuration::class)
->getMock();
$configuration = $this->createMock(\Doctrine\DBAL\Configuration::class);
$driverConnection->method('getDatabasePlatform')->willReturn($platform);
$driverConnection->method('getConfiguration')->willReturn($configuration);
$schemaManager = $this->createMock(AbstractSchemaManager::class);
$schemaConfig = $this->createMock(SchemaConfig::class);
$schemaConfig->method('getMaxIdentifierLength')->willReturn(63);
$schemaConfig->method('getDefaultTableOptions')->willReturn([]);
$schemaManager->method('createSchemaConfig')->willReturn($schemaConfig);
$driverConnection->method('getSchemaManager')->willReturn($schemaManager);
return $driverConnection;
}
private function getQueryBuilderMock()
{
$queryBuilder = $this->getMockBuilder(QueryBuilder::class)
->disableOriginalConstructor()
->getMock();
$queryBuilder = $this->createMock(QueryBuilder::class);
$queryBuilder->method('select')->willReturn($queryBuilder);
$queryBuilder->method('update')->willReturn($queryBuilder);
@ -138,9 +141,7 @@ class ConnectionTest extends TestCase
private function getStatementMock($expectedResult)
{
$stmt = $this->getMockBuilder(Statement::class)
->disableOriginalConstructor()
->getMock();
$stmt = $this->createMock(Statement::class);
$stmt->expects($this->once())
->method('fetch')
->willReturn($expectedResult);
@ -150,8 +151,7 @@ class ConnectionTest extends TestCase
private function getSchemaSynchronizerMock()
{
return $this->getMockBuilder(SchemaSynchronizer::class)
->getMock();
return $this->createMock(SchemaSynchronizer::class);
}
/**
@ -307,9 +307,7 @@ class ConnectionTest extends TestCase
'headers' => json_encode(['type' => DummyMessage::class]),
];
$stmt = $this->getMockBuilder(Statement::class)
->disableOriginalConstructor()
->getMock();
$stmt = $this->createMock(Statement::class);
$stmt->expects($this->once())
->method('fetchAll')
->willReturn([$message1, $message2]);

View File

@ -32,7 +32,7 @@ class DoctrineReceiverTest extends TestCase
$serializer = $this->createSerializer();
$doctrineEnvelope = $this->createDoctrineEnvelope();
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
$connection = $this->createMock(Connection::class);
$connection->method('get')->willReturn($doctrineEnvelope);
$receiver = new DoctrineReceiver($connection, $serializer);
@ -62,7 +62,7 @@ class DoctrineReceiverTest extends TestCase
$serializer->method('decode')->willThrowException(new MessageDecodingFailedException());
$doctrineEnvelop = $this->createDoctrineEnvelope();
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
$connection = $this->createMock(Connection::class);
$connection->method('get')->willReturn($doctrineEnvelop);
$connection->expects($this->once())->method('reject');

View File

@ -27,12 +27,10 @@ class DoctrineSenderTest extends TestCase
$envelope = new Envelope(new DummyMessage('Oy'));
$encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class]];
$connection = $this->getMockBuilder(Connection::class)
->disableOriginalConstructor()
->getMock();
$connection = $this->createMock(Connection::class);
$connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'])->willReturn(15);
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
$serializer = $this->createMock(SerializerInterface::class);
$serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded);
$sender = new DoctrineSender($connection, $serializer);
@ -49,12 +47,10 @@ class DoctrineSenderTest extends TestCase
$envelope = (new Envelope(new DummyMessage('Oy')))->with(new DelayStamp(500));
$encoded = ['body' => '...', 'headers' => ['type' => DummyMessage::class]];
$connection = $this->getMockBuilder(Connection::class)
->disableOriginalConstructor()
->getMock();
$connection = $this->createMock(Connection::class);
$connection->expects($this->once())->method('send')->with($encoded['body'], $encoded['headers'], 500);
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
$serializer = $this->createMock(SerializerInterface::class);
$serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded);
$sender = new DoctrineSender($connection, $serializer);

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\Messenger\Tests\Transport\Doctrine;
use Doctrine\Common\Persistence\ConnectionRegistry;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\SchemaConfig;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Transport\Doctrine\Connection;
use Symfony\Component\Messenger\Transport\Doctrine\DoctrineTransport;
@ -23,7 +25,7 @@ class DoctrineTransportFactoryTest extends TestCase
public function testSupports()
{
$factory = new DoctrineTransportFactory(
$this->getMockBuilder(ConnectionRegistry::class)->getMock()
$this->createMock(ConnectionRegistry::class)
);
$this->assertTrue($factory->supports('doctrine://default', []));
@ -32,19 +34,22 @@ class DoctrineTransportFactoryTest extends TestCase
public function testCreateTransport()
{
$connection = $this->getMockBuilder(\Doctrine\DBAL\Connection::class)
->disableOriginalConstructor()
->getMock();
$registry = $this->getMockBuilder(ConnectionRegistry::class)->getMock();
$driverConnection = $this->createMock(\Doctrine\DBAL\Connection::class);
$schemaManager = $this->createMock(AbstractSchemaManager::class);
$schemaConfig = $this->createMock(SchemaConfig::class);
$schemaManager->method('createSchemaConfig')->willReturn($schemaConfig);
$driverConnection->method('getSchemaManager')->willReturn($schemaManager);
$registry = $this->createMock(ConnectionRegistry::class);
$registry->expects($this->once())
->method('getConnection')
->willReturn($connection);
->willReturn($driverConnection);
$factory = new DoctrineTransportFactory($registry);
$serializer = $this->createMock(SerializerInterface::class);
$this->assertEquals(
new DoctrineTransport(new Connection(Connection::buildConfiguration('doctrine://default'), $connection), $serializer),
new DoctrineTransport(new Connection(Connection::buildConfiguration('doctrine://default'), $driverConnection), $serializer),
$factory->createTransport('doctrine://default', [], $serializer)
);
}
@ -55,7 +60,7 @@ class DoctrineTransportFactoryTest extends TestCase
*/
public function testCreateTransportMustThrowAnExceptionIfManagerIsNotFound()
{
$registry = $this->getMockBuilder(ConnectionRegistry::class)->getMock();
$registry = $this->createMock(ConnectionRegistry::class);
$registry->expects($this->once())
->method('getConnection')
->willReturnCallback(function () {

View File

@ -31,8 +31,8 @@ class DoctrineTransportTest extends TestCase
public function testReceivesMessages()
{
$transport = $this->getTransport(
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock(),
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()
$serializer = $this->createMock(SerializerInterface::class),
$connection = $this->createMock(Connection::class)
);
$decodedMessage = new DummyMessage('Decoded.');
@ -52,8 +52,8 @@ class DoctrineTransportTest extends TestCase
private function getTransport(SerializerInterface $serializer = null, Connection $connection = null)
{
$serializer = $serializer ?: $this->getMockBuilder(SerializerInterface::class)->getMock();
$connection = $connection ?: $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
$serializer = $serializer ?: $this->createMock(SerializerInterface::class);
$connection = $connection ?: $this->createMock(Connection::class);
return new DoctrineTransport($connection, $serializer);
}

View File

@ -16,7 +16,7 @@ use Symfony\Component\Messenger\Exception\TransportException;
use Symfony\Component\Messenger\Transport\RedisExt\Connection;
/**
* @requires extension redis
* @requires extension redis >= 4.3.0
*/
class ConnectionTest extends TestCase
{
@ -119,7 +119,7 @@ class ConnectionTest extends TestCase
$redis->expects($this->once())->method('xreadgroup')->willReturn(false);
$redis->expects($this->once())->method('getLastError')->willReturn('Redis error happens');
$connection = Connection::fromDsn('redis://localhost/queue', [], $redis);
$connection = Connection::fromDsn('redis://localhost/queue', ['auto_setup' => false], $redis);
$connection->get();
}
@ -164,4 +164,31 @@ class ConnectionTest extends TestCase
$connection = Connection::fromDsn('redis://localhost/queue?stream_max_entries=20000', [], $redis); // 1 = always
$connection->add('1', []);
}
public function testLastErrorGetsCleared()
{
$redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock();
$redis->expects($this->once())->method('xadd')->willReturn(0);
$redis->expects($this->once())->method('xack')->willReturn(0);
$redis->method('getLastError')->willReturnOnConsecutiveCalls('xadd error', 'xack error');
$redis->expects($this->exactly(2))->method('clearLastError');
$connection = Connection::fromDsn('redis://localhost/messenger-clearlasterror', ['auto_setup' => false], $redis);
try {
$connection->add('message', []);
} catch (TransportException $e) {
}
$this->assertSame('xadd error', $e->getMessage());
try {
$connection->ack('1');
} catch (TransportException $e) {
}
$this->assertSame('xack error', $e->getMessage());
}
}

View File

@ -43,10 +43,7 @@ class AmqpSender implements SenderInterface
/** @var DelayStamp|null $delayStamp */
$delayStamp = $envelope->last(DelayStamp::class);
$delay = 0;
if (null !== $delayStamp) {
$delay = $delayStamp->getDelay();
}
$delay = $delayStamp ? $delayStamp->getDelay() : 0;
$amqpStamp = $envelope->last(AmqpStamp::class);
if (isset($encodedMessage['headers']['Content-Type'])) {

View File

@ -60,9 +60,8 @@ class Connection
{
$this->connectionOptions = array_replace_recursive([
'delay' => [
'routing_key_pattern' => 'delay_%exchange_name%_%routing_key%_%delay%',
'exchange_name' => 'delay',
'queue_name_pattern' => 'delay_queue_%exchange_name%_%routing_key%_%delay%',
'queue_name_pattern' => 'delay_%exchange_name%_%routing_key%_%delay%',
],
], $connectionOptions);
$this->exchangeOptions = $exchangeOptions;
@ -91,9 +90,8 @@ class Connection
* * flags: Exchange flags (Default: AMQP_DURABLE)
* * arguments: Extra arguments
* * delay:
* * routing_key_pattern: The pattern of the routing key (Default: "delay_%exchange_name%_%routing_key%_%delay%")
* * queue_name_pattern: Pattern to use to create the queues (Default: "delay_queue_%exchange_name%_%routing_key%_%delay%")
* * exchange_name: Name of the exchange to be used for the retried messages (Default: "delay")
* * queue_name_pattern: Pattern to use to create the queues (Default: "delay_%exchange_name%_%routing_key%_%delay%")
* * exchange_name: Name of the exchange to be used for the delayed/retried messages (Default: "delay")
* * auto_setup: Enable or not the auto-setup of queues and exchanges (Default: true)
* * prefetch_count: set channel prefetch count
*/
@ -169,20 +167,20 @@ class Connection
}
/**
* @param int $delay The delay in milliseconds
*
* @throws \AMQPException
*/
public function publish(string $body, array $headers = [], int $delay = 0, AmqpStamp $amqpStamp = null): void
public function publish(string $body, array $headers = [], int $delayInMs = 0, AmqpStamp $amqpStamp = null): void
{
if (0 !== $delay) {
$this->publishWithDelay($body, $headers, $delay, $amqpStamp);
$this->clearWhenDisconnected();
if (0 !== $delayInMs) {
$this->publishWithDelay($body, $headers, $delayInMs, $amqpStamp);
return;
}
if ($this->shouldSetup()) {
$this->setup();
$this->setupExchangeAndQueues();
}
$this->publishOnExchange(
@ -211,9 +209,7 @@ class Connection
{
$routingKey = $this->getRoutingKeyForMessage($amqpStamp);
if ($this->shouldSetup()) {
$this->setupDelay($delay, $routingKey);
}
$this->setupDelay($delay, $routingKey);
$this->publishOnExchange(
$this->getDelayExchange(),
@ -239,15 +235,12 @@ class Connection
private function setupDelay(int $delay, ?string $routingKey)
{
if (!$this->channel()->isConnected()) {
$this->clear();
if ($this->shouldSetup()) {
$this->setup(); // setup delay exchange and normal exchange for delay queue to DLX messages to
}
$this->exchange()->declareExchange(); // setup normal exchange for delay queue to DLX messages to
$this->getDelayExchange()->declareExchange();
$queue = $this->createDelayQueue($delay, $routingKey);
$queue->declareQueue();
$queue->declareQueue(); // the delay queue always need to be declared because the name is dynamic and cannot be declared in advance
$queue->bind($this->connectionOptions['delay']['exchange_name'], $this->getRoutingKeyForDelay($delay, $routingKey));
}
@ -281,6 +274,9 @@ class Connection
));
$queue->setArguments([
'x-message-ttl' => $delay,
// delete the delay queue 10 seconds after the message expires
// publishing another message redeclares the queue which renews the lease
'x-expires' => $delay + 10000,
'x-dead-letter-exchange' => $this->exchangeOptions['name'],
// after being released from to DLX, make sure the original routing key will be used
// we must use an empty string instead of null for the argument to be picked up
@ -295,7 +291,7 @@ class Connection
return str_replace(
['%delay%', '%exchange_name%', '%routing_key%'],
[$delay, $this->exchangeOptions['name'], $finalRoutingKey ?? ''],
$this->connectionOptions['delay']['routing_key_pattern']
$this->connectionOptions['delay']['queue_name_pattern']
);
}
@ -306,8 +302,10 @@ class Connection
*/
public function get(string $queueName): ?\AMQPEnvelope
{
$this->clearWhenDisconnected();
if ($this->shouldSetup()) {
$this->setup();
$this->setupExchangeAndQueues();
}
try {
@ -317,7 +315,7 @@ class Connection
} catch (\AMQPQueueException $e) {
if (404 === $e->getCode() && $this->shouldSetup()) {
// If we get a 404 for the queue, it means we need to setup the exchange & queue.
$this->setup();
$this->setupExchangeAndQueues();
return $this->get();
}
@ -340,10 +338,12 @@ class Connection
public function setup(): void
{
if (!$this->channel()->isConnected()) {
$this->clear();
}
$this->setupExchangeAndQueues();
$this->getDelayExchange()->declareExchange();
}
private function setupExchangeAndQueues(): void
{
$this->exchange()->declareExchange();
foreach ($this->queuesOptions as $queueName => $queueConfig) {
@ -422,12 +422,14 @@ class Connection
return $this->amqpExchange;
}
private function clear(): void
private function clearWhenDisconnected(): void
{
$this->amqpChannel = null;
$this->amqpQueues = [];
$this->amqpExchange = null;
$this->amqpDelayExchange = null;
if (!$this->channel()->isConnected()) {
$this->amqpChannel = null;
$this->amqpQueues = [];
$this->amqpExchange = null;
$this->amqpDelayExchange = null;
}
}
private function shouldSetup(): bool

View File

@ -302,7 +302,7 @@ class Connection
private function getSchema(): Schema
{
$schema = new Schema();
$schema = new Schema([], [], $this->driverConnection->getSchemaManager()->createSchemaConfig());
$table = $schema->createTable($this->configuration['table_name']);
$table->addColumn('id', Type::BIGINT)
->setAutoincrement(true)

View File

@ -127,12 +127,15 @@ class Connection
1
);
} catch (\RedisException $e) {
throw new TransportException($e->getMessage(), 0, $e);
}
if ($e || false === $messages) {
throw new TransportException(
($e ? $e->getMessage() : $this->connection->getLastError()) ?? 'Could not read messages from the redis stream.'
);
if (false === $messages) {
if ($error = $this->connection->getLastError() ?: null) {
$this->connection->clearLastError();
}
throw new TransportException($error ?? 'Could not read messages from the redis stream.');
}
if ($this->couldHavePendingMessages && empty($messages[$this->stream])) {
@ -157,28 +160,34 @@ class Connection
public function ack(string $id): void
{
$e = null;
try {
$acknowledged = $this->connection->xack($this->stream, $this->group, [$id]);
} catch (\RedisException $e) {
throw new TransportException($e->getMessage(), 0, $e);
}
if ($e || !$acknowledged) {
throw new TransportException(($e ? $e->getMessage() : $this->connection->getLastError()) ?? sprintf('Could not acknowledge redis message "%s".', $id), 0, $e);
if (!$acknowledged) {
if ($error = $this->connection->getLastError() ?: null) {
$this->connection->clearLastError();
}
throw new TransportException($error ?? sprintf('Could not acknowledge redis message "%s".', $id));
}
}
public function reject(string $id): void
{
$e = null;
try {
$deleted = $this->connection->xack($this->stream, $this->group, [$id]);
$deleted = $this->connection->xdel($this->stream, [$id]) && $deleted;
} catch (\RedisException $e) {
throw new TransportException($e->getMessage(), 0, $e);
}
if ($e || !$deleted) {
throw new TransportException(($e ? $e->getMessage() : $this->connection->getLastError()) ?? sprintf('Could not delete message "%s" from the redis stream.', $id), 0, $e);
if (!$deleted) {
if ($error = $this->connection->getLastError() ?: null) {
$this->connection->clearLastError();
}
throw new TransportException($error ?? sprintf('Could not delete message "%s" from the redis stream.', $id));
}
}
@ -188,7 +197,6 @@ class Connection
$this->setup();
}
$e = null;
try {
if ($this->maxEntries) {
$added = $this->connection->xadd($this->stream, '*', ['message' => json_encode(
@ -200,10 +208,14 @@ class Connection
)]);
}
} catch (\RedisException $e) {
throw new TransportException($e->getMessage(), 0, $e);
}
if ($e || !$added) {
throw new TransportException(($e ? $e->getMessage() : $this->connection->getLastError()) ?? 'Could not add a message to the redis stream.', 0, $e);
if (!$added) {
if ($error = $this->connection->getLastError() ?: null) {
$this->connection->clearLastError();
}
throw new TransportException($error ?? 'Could not add a message to the redis stream.');
}
}
@ -215,6 +227,11 @@ class Connection
throw new TransportException($e->getMessage(), 0, $e);
}
// group might already exist, ignore
if ($this->connection->getLastError()) {
$this->connection->clearLastError();
}
$this->autoSetup = false;
}
}

View File

@ -71,6 +71,8 @@ class Section
return $child;
}
}
return null;
}
/**
@ -114,8 +116,8 @@ class Section
/**
* Starts an event.
*
* @param string $name The event name
* @param string $category The event category
* @param string $name The event name
* @param string|null $category The event category
*
* @return StopwatchEvent The event
*/