From 4fc0ecbf90cb8d34189e11dc70445d801ed99cc7 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Fri, 2 Feb 2018 08:30:49 +0100 Subject: [PATCH 01/75] Fixed being logged out on failed attempt in guard --- .../Security/Guard/GuardAuthenticatorHandler.php | 6 ------ .../Guard/Tests/GuardAuthenticatorHandlerTest.php | 15 +++++---------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index 507e5362123b6..3b62c41253a22 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -18,7 +18,6 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; @@ -116,11 +115,6 @@ public function authenticateUserAndHandleSuccess(UserInterface $user, Request $r */ public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) { - $token = $this->tokenStorage->getToken(); - if ($token instanceof PostAuthenticationGuardToken && $providerKey === $token->getProviderKey()) { - $this->tokenStorage->setToken(null); - } - $response = $guardAuthenticator->onAuthenticationFailure($request, $authenticationException); if ($response instanceof Response || null === $response) { // returning null is ok, it means they want the request to continue diff --git a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php index b46bc4a78d4f1..662bace30877c 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -81,7 +81,7 @@ public function testHandleAuthenticationFailure() /** * @dataProvider getTokenClearingTests */ - public function testHandleAuthenticationClearsToken($tokenClass, $tokenProviderKey, $actualProviderKey, $shouldTokenBeCleared) + public function testHandleAuthenticationClearsToken($tokenClass, $tokenProviderKey, $actualProviderKey) { $token = $this->getMockBuilder($tokenClass) ->disableOriginalConstructor() @@ -90,12 +90,7 @@ public function testHandleAuthenticationClearsToken($tokenClass, $tokenProviderK ->method('getProviderKey') ->will($this->returnValue($tokenProviderKey)); - // make the $token be the current token - $this->tokenStorage->expects($this->once()) - ->method('getToken') - ->will($this->returnValue($token)); - - $this->tokenStorage->expects($shouldTokenBeCleared ? $this->once() : $this->never()) + $this->tokenStorage->expects($this->never()) ->method('setToken') ->with(null); $authException = new AuthenticationException('Bad password!'); @@ -115,9 +110,9 @@ public function getTokenClearingTests() { $tests = array(); // correct token class and matching firewall => clear the token - $tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'the_firewall_key', true); - $tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'different_key', false); - $tests[] = array('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', 'the_firewall_key', 'the_firewall_key', false); + $tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'the_firewall_key'); + $tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'different_key'); + $tests[] = array('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', 'the_firewall_key', 'the_firewall_key'); return $tests; } From 43599362a2c33fa065164d8fe52d8ef5348389dc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 6 Apr 2018 13:01:31 +0200 Subject: [PATCH 02/75] [Yaml] Throw parse error on unfinished inline map --- src/Symfony/Component/Yaml/Inline.php | 3 +++ src/Symfony/Component/Yaml/Tests/InlineTest.php | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 31a0514fd4972..5e5b1a1767ee2 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -231,6 +231,9 @@ public static function parseScalar($scalar, $delimiters = null, $stringDelimiter if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); + if ('' === $tmp) { + throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode($delimiters))); + } if (!in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); } diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index f28f360489f66..418c7876a13c9 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -432,4 +432,13 @@ public function testTheEmptyStringIsAValidMappingKey() { $this->assertSame(array('' => 'foo'), Inline::parse('{ "": foo }')); } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Unexpected end of line, expected one of ",}". + */ + public function testUnfinishedInlineMap() + { + Inline::parse("{abc: 'def'"); + } } From e350ea000ff34ef15aa50f161b3fad17e81e079d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Dec 2017 10:31:46 +0100 Subject: [PATCH 03/75] [HttpFoundation] Send cookies using header() to fix "SameSite" ones --- src/Symfony/Component/HttpFoundation/Response.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 6f8a6239593b1..f3e45b57cbc7d 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -327,7 +327,7 @@ public function sendHeaders() } // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { + foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.': '.$value, false, $this->statusCode); } @@ -336,15 +336,6 @@ public function sendHeaders() // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - // cookies - foreach ($this->headers->getCookies() as $cookie) { - if ($cookie->isRaw()) { - setrawcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } else { - setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } - } - return $this; } From f331d964d9c0d6daa7d701b3bb885a52018e44df Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 14:49:17 +0200 Subject: [PATCH 04/75] updated CHANGELOG for 2.7.45 --- CHANGELOG-2.7.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 70677f3d18e3d..6c8ff11ea85cb 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,12 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.45 (2018-04-06) + + * bug #26763 [Finder] Remove duplicate slashes in filenames (helhum) + * bug #26749 Add PHPDbg support to HTTP components (hkdobrev) + * bug #26609 [Console] Fix check of color support on Windows (mlocati) + * 2.7.44 (2018-04-02) * bug #26727 [HttpCache] Unlink tmp file on error (Chansig) From 175e883e6cc80ff8f148b649eb5bd9edf946a797 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 14:49:33 +0200 Subject: [PATCH 05/75] update CONTRIBUTORS for 2.7.45 --- CONTRIBUTORS.md | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1cb4373ec2030..57bd22e5c521d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,14 +14,14 @@ Symfony is the result of the work of many people who made the code better - Victor Berchet (victor) - Kévin Dunglas (dunglas) - Johannes S (johannes) - - Jakub Zalas (jakubzalas) - Robin Chalas (chalas_r) + - Jakub Zalas (jakubzalas) - Kris Wallsmith (kriswallsmith) - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) - Maxime Steinhausser (ogizanagi) - - Hugo Hamon (hhamon) - Grégoire Pineau (lyrixx) + - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) - Romain Neutron (romain) - Pascal Borreli (pborreli) @@ -49,16 +49,16 @@ Symfony is the result of the work of many people who made the code better - Iltar van der Berg (kjarli) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) + - Samuel ROZE (sroze) - Yonel Ceruto (yonelceruto) - Bulat Shakirzyanov (avalanche123) - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Matthias Pigulla (mpdude) - - Samuel ROZE (sroze) + - Pierre du Plessis (pierredup) - Henrik Bjørnskov (henrikbjorn) - Dany Maillard (maidmaid) - Miha Vrhovnik - - Pierre du Plessis (pierredup) - Tobias Nyholm (tobias) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) @@ -81,8 +81,8 @@ Symfony is the result of the work of many people who made the code better - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Douglas Greenshields (shieldo) - Issei Murasawa (issei_m) + - Douglas Greenshields (shieldo) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) @@ -94,10 +94,10 @@ Symfony is the result of the work of many people who made the code better - Jordan Alliot (jalliot) - Jérôme Tamarelle (gromnan) - John Wards (johnwards) + - David Maicher (dmaicher) - Fran Moreno (franmomu) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - - David Maicher (dmaicher) - Vladimir Reznichenko (kalessil) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER @@ -148,6 +148,7 @@ Symfony is the result of the work of many people who made the code better - Julien Falque (julienfalque) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) + - gadelat (gadelat) - jwdeitch - Mikael Pajunen - Joel Wurtz (brouznouf) @@ -158,7 +159,6 @@ Symfony is the result of the work of many people who made the code better - Richard van Laak (rvanlaak) - Richard Shank (iampersistent) - Thomas Rabaix (rande) - - gadelat (gadelat) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - Clemens Tolboom @@ -292,6 +292,7 @@ Symfony is the result of the work of many people who made the code better - Roumen Damianoff (roumen) - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) + - Florent Mata (fmata) - Wouter Van Hecke - Jérôme Parmentier (lctrs) - Michael Babker (mbabker) @@ -371,13 +372,13 @@ Symfony is the result of the work of many people who made the code better - Philipp Kräutli (pkraeutli) - Kirill chEbba Chebunin (chebba) - Greg Thornton (xdissent) - - Florent Mata (fmata) - Costin Bereveanu (schniper) - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) - Vyacheslav Salakhutdinov (megazoll) - Hassan Amouhzi - Tamas Szijarto + - Michele Locati - Pavel Volokitin (pvolok) - Arthur de Moulins (4rthem) - Nicolas Dewez (nicolas_dewez) @@ -435,6 +436,7 @@ Symfony is the result of the work of many people who made the code better - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) - Andreas Braun + - Boris Vujicic (boris.vujicic) - Chris Sedlmayr (catchamonkey) - Seb Koelen - Christoph Mewes (xrstf) @@ -467,6 +469,7 @@ Symfony is the result of the work of many people who made the code better - Roman Lapin (memphys) - Yoshio HANAWA - Gladhon + - Haralan Dobrev (hkdobrev) - Sebastian Bergmann - Miroslav Sustek - Sullivan SENECHAL (soullivaneuh) @@ -499,7 +502,6 @@ Symfony is the result of the work of many people who made the code better - Andrew Udvare (audvare) - alexpods - Arjen van der Meijden - - Michele Locati - Dariusz Ruminski - Mathieu Lechat - Erik Trapman (eriktrapman) @@ -588,7 +590,6 @@ Symfony is the result of the work of many people who made the code better - Javier López (loalf) - Reinier Kip - Geoffrey Brier (geoffrey-brier) - - Boris Vujicic (boris.vujicic) - Dustin Dobervich (dustin10) - dantleech - Anne-Sophie Bachelard (annesophie) @@ -603,6 +604,7 @@ Symfony is the result of the work of many people who made the code better - mcfedr (mcfedr) - Rostyslav Kinash - Maciej Malarz (malarzm) + - Pascal Luna (skalpa) - Daisuke Ohata - Vincent Simonin - Alex Bogomazov (alebo) @@ -623,6 +625,7 @@ Symfony is the result of the work of many people who made the code better - Denis Brumann (dbrumann) - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) + - Shaun Simmons (simshaun) - Richard Bradley - Ulumuddin Yunus (joenoez) - Johann Saunier (prophet777) @@ -765,6 +768,7 @@ Symfony is the result of the work of many people who made the code better - Maksim Kotlyar (makasim) - Neil Ferreira - Nathanael Noblet (gnat) + - Indra Gunawan (indragunawan) - Dmitry Parnas (parnas) - Paul LE CORRE - Emanuele Iannone @@ -951,6 +955,7 @@ Symfony is the result of the work of many people who made the code better - Ken Marfilla (marfillaster) - benatespina (benatespina) - Denis Kop + - Jean-Guilhem Rouel (jean-gui) - jfcixmedia - Nikita Konstantinov - Martijn Evers @@ -982,7 +987,6 @@ Symfony is the result of the work of many people who made the code better - Olaf Klischat - orlovv - Peter Smeets (darkspartan) - - Haralan Dobrev (hkdobrev) - Jhonny Lidfors (jhonny) - Julien Bianchi (jubianchi) - Robert Meijers @@ -1001,6 +1005,7 @@ Symfony is the result of the work of many people who made the code better - Jeremy Bush - wizhippo - Viacheslav Sychov + - Helmut Hummel (helhum) - Matt Brunt - Carlos Ortega Huetos - rpg600 @@ -1025,6 +1030,7 @@ Symfony is the result of the work of many people who made the code better - rchoquet - gitlost - Taras Girnyk + - Anthony GRASSIOT (antograssiot) - Eduardo García Sanz (coma) - James Gilliland - fduch (fduch) @@ -1054,6 +1060,7 @@ Symfony is the result of the work of many people who made the code better - Peter Thompson (petert82) - Felicitus - Krzysztof Przybyszewski + - alexpozzi - Paul Matthews - Jakub Kisielewski - Vacheslav Silyutin @@ -1133,6 +1140,7 @@ Symfony is the result of the work of many people who made the code better - Berat Doğan - Guillaume LECERF - Juanmi Rodriguez Cerón + - Sergey Yastrebov - Andy Raines - Anthony Ferrara - Klaas Cuvelier (kcuvelier) @@ -1226,6 +1234,7 @@ Symfony is the result of the work of many people who made the code better - Ergie Gonzaga - Matthew J Mucklo - AnrDaemon + - Smaine Milianni (ismail1432) - fdgdfg (psampaz) - Stéphane Seng - Maxwell Vandervelde @@ -1362,7 +1371,6 @@ Symfony is the result of the work of many people who made the code better - Christopher Parotat - 蝦米 - Grayson Koonce (breerly) - - Indra Gunawan (indragunawan) - Karim Cassam Chenaï (ka) - Michal Kurzeja (mkurzeja) - Nicolas Bastien (nicolas_bastien) @@ -1446,6 +1454,7 @@ Symfony is the result of the work of many people who made the code better - Edvinas Klovas - Drew Butler - Peter Breuls + - Chansig - Tischoi - J Bruni - Alexey Prilipko @@ -1530,6 +1539,7 @@ Symfony is the result of the work of many people who made the code better - Erik van Wingerden - Valouleloup - Dane Powell + - mweimerskirch - Gerrit Drost - Linnaea Von Lavia - Simon Mönch @@ -1633,6 +1643,7 @@ Symfony is the result of the work of many people who made the code better - temperatur - Cas - Dusan Kasan + - Karolis - Myke79 - Brian Debuire - Piers Warmers @@ -1703,7 +1714,6 @@ Symfony is the result of the work of many people who made the code better - Neophy7e - bokonet - Arrilot - - Shaun Simmons - Markus Staab - Pierre-Louis LAUNAY - djama @@ -1832,6 +1842,7 @@ Symfony is the result of the work of many people who made the code better - emilienbouard (neime) - Nicholas Byfleet (nickbyfleet) - Tomas Norkūnas (norkunas) + - Marco Petersen (ocrampete16) - ollie harridge (ollietb) - Paul Andrieux (paulandrieux) - Paweł Szczepanek (pauluz) @@ -1851,11 +1862,11 @@ Symfony is the result of the work of many people who made the code better - scourgen hung (scourgen) - Sébastien Alfaiate (seb33300) - Sebastian Busch (sebu) + - Christophe Villeger (seragan) - André Filipe Gonçalves Neves (seven) - Bruno Ziegler (sfcoder) - Andrea Giuliano (shark) - Schuyler Jager (sjager) - - Pascal Luna (skalpa) - Volker (skydiablo) - Serkan Yildiz (srknyldz) - Julien Sanchez (sumbobyboys) @@ -1886,6 +1897,7 @@ Symfony is the result of the work of many people who made the code better - Ben Scott - Dionysis Arvanitis - Sergey Fedotov + - Konstantin Scheumann - Michael - fh-github@fholzhauer.de - AbdElKader Bouadjadja From 952879e147e9bf93f576056e6d798ae9184d52f3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 14:49:33 +0200 Subject: [PATCH 06/75] updated VERSION for 2.7.45 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 687760865b6ea..ca42a5e29958f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.45-DEV'; + const VERSION = '2.7.45'; const VERSION_ID = 20745; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 45; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From e73aa2985b435400ed76c6fd7bea80366dc21b67 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 16:50:48 +0200 Subject: [PATCH 07/75] bumped Symfony version to 2.7.46 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ca42a5e29958f..1b8abba1474dc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.45'; - const VERSION_ID = 20745; + const VERSION = '2.7.46-DEV'; + const VERSION_ID = 20746; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 45; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 46; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From fa3f105f61d7068592d40cd2217397a20d81b745 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 16:51:52 +0200 Subject: [PATCH 08/75] updated CHANGELOG for 2.8.38 --- CHANGELOG-2.8.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index e933be2021abd..e53256bdc8327 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,14 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.38 (2018-04-06) + + * bug #26788 [Security] Load the user before pre/post auth checks when needed (chalasr) + * bug #26774 [SecurityBundle] Add missing argument to security.authentication.provider.simple (i3or1s, chalasr) + * bug #26763 [Finder] Remove duplicate slashes in filenames (helhum) + * bug #26749 Add PHPDbg support to HTTP components (hkdobrev) + * bug #26609 [Console] Fix check of color support on Windows (mlocati) + * 2.8.37 (2018-04-02) * bug #26727 [HttpCache] Unlink tmp file on error (Chansig) From 47b29834cb08e20c4618eab9973a5e03d13a8814 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 16:52:08 +0200 Subject: [PATCH 09/75] updated VERSION for 2.8.38 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index defbf43974e42..3d54fdffcfa19 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.38-DEV'; + const VERSION = '2.8.38'; const VERSION_ID = 20838; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 38; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From b04452a223f9ce4279d18795745351aeb6581fd4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 17:19:00 +0200 Subject: [PATCH 10/75] bumped Symfony version to 2.8.39 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 3d54fdffcfa19..3193b61e8b18e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.38'; - const VERSION_ID = 20838; + const VERSION = '2.8.39-DEV'; + const VERSION_ID = 20839; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 38; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 39; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 0cbee5e9aa1ef7c5d6582e4370596a6e63a20fc8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 17:19:35 +0200 Subject: [PATCH 11/75] updated CHANGELOG for 3.4.8 --- CHANGELOG-3.4.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index ee69e43fc8382..abc5e0a9f4da1 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -7,6 +7,16 @@ in 3.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.4.0...v3.4.1 +* 3.4.8 (2018-04-06) + + * bug #26802 [Security] register custom providers on ExpressionLanguage directly (dmaicher) + * bug #26794 [PhpUnitBridge] Catch deprecation error handler (cvilleger) + * bug #26788 [Security] Load the user before pre/post auth checks when needed (chalasr) + * bug #26792 [Routing] Fix throwing NoConfigurationException instead of 405 (nicolas-grekas) + * bug #26774 [SecurityBundle] Add missing argument to security.authentication.provider.simple (i3or1s, chalasr) + * bug #26763 [Finder] Remove duplicate slashes in filenames (helhum) + * bug #26758 [WebProfilerBundle][HttpKernel] Make FileLinkFormatter URL format generation lazy (nicolas-grekas) + * 3.4.7 (2018-04-03) * bug #26387 [Yaml] Fix regression when trying to parse multiline (antograssiot) From 884b994be98571ead1f30fa86a5aabd89f3c6ec1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 17:19:48 +0200 Subject: [PATCH 12/75] updated VERSION for 3.4.8 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 7cb3621744d3e..03cd708ebf241 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.8-DEV'; + const VERSION = '3.4.8'; const VERSION_ID = 30408; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 8; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 4dda7abdce442b97acea21256e7044309630966d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 18:24:29 +0200 Subject: [PATCH 13/75] bumped Symfony version to 3.4.9 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 03cd708ebf241..0d68c4f7ff044 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.8'; - const VERSION_ID = 30408; + const VERSION = '3.4.9-DEV'; + const VERSION_ID = 30409; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 8; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 9; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 02e5fbceeaeacf7265ad7276a63f3d804e49f483 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Apr 2018 18:49:36 +0200 Subject: [PATCH 14/75] bumped Symfony version to 4.0.9 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index db80323c206d9..1c87544c6b93f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -63,12 +63,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.0.8'; - const VERSION_ID = 40008; + const VERSION = '4.0.9-DEV'; + const VERSION_ID = 40009; const MAJOR_VERSION = 4; const MINOR_VERSION = 0; - const RELEASE_VERSION = 8; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 9; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2018'; const END_OF_LIFE = '01/2019'; From c36f6db14b42a68e5ddafc05bfbad5839f643c8c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 7 Apr 2018 15:20:24 +0200 Subject: [PATCH 15/75] [Translation] Use unix-style EOL for xliff-core-1.2-strict.xsd --- .../schemas/xliff-core-1.2-strict.xsd | 4446 ++++++++--------- 1 file changed, 2223 insertions(+), 2223 deletions(-) diff --git a/src/Symfony/Component/Translation/Resources/schemas/xliff-core-1.2-strict.xsd b/src/Symfony/Component/Translation/Resources/schemas/xliff-core-1.2-strict.xsd index 803eb602def50..dface628ce3e4 100644 --- a/src/Symfony/Component/Translation/Resources/schemas/xliff-core-1.2-strict.xsd +++ b/src/Symfony/Component/Translation/Resources/schemas/xliff-core-1.2-strict.xsd @@ -1,2223 +1,2223 @@ - - - - - - - - - - - - - - - Values for the attribute 'context-type'. - - - - - Indicates a database content. - - - - - Indicates the content of an element within an XML document. - - - - - Indicates the name of an element within an XML document. - - - - - Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. - - - - - Indicates a the number of parameters contained within the <source>. - - - - - Indicates notes pertaining to the parameters in the <source>. - - - - - Indicates the content of a record within a database. - - - - - Indicates the name of a record within a database. - - - - - Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. - - - - - - - Values for the attribute 'count-type'. - - - - - Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. - - - - - Indicates the count units are translation units existing already in the same document. - - - - - Indicates a total count. - - - - - - - Values for the attribute 'ctype' when used other elements than <ph> or <x>. - - - - - Indicates a run of bolded text. - - - - - Indicates a run of text in italics. - - - - - Indicates a run of underlined text. - - - - - Indicates a run of hyper-text. - - - - - - - Values for the attribute 'ctype' when used with <ph> or <x>. - - - - - Indicates a inline image. - - - - - Indicates a page break. - - - - - Indicates a line break. - - - - - - - - - - - - Values for the attribute 'datatype'. - - - - - Indicates Active Server Page data. - - - - - Indicates C source file data. - - - - - Indicates Channel Definition Format (CDF) data. - - - - - Indicates ColdFusion data. - - - - - Indicates C++ source file data. - - - - - Indicates C-Sharp data. - - - - - Indicates strings from C, ASM, and driver files data. - - - - - Indicates comma-separated values data. - - - - - Indicates database data. - - - - - Indicates portions of document that follows data and contains metadata. - - - - - Indicates portions of document that precedes data and contains metadata. - - - - - Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). - - - - - Indicates standard user input screen data. - - - - - Indicates HyperText Markup Language (HTML) data - document instance. - - - - - Indicates content within an HTML document’s <body> element. - - - - - Indicates Windows INI file data. - - - - - Indicates Interleaf data. - - - - - Indicates Java source file data (extension '.java'). - - - - - Indicates Java property resource bundle data. - - - - - Indicates Java list resource bundle data. - - - - - Indicates JavaScript source file data. - - - - - Indicates JScript source file data. - - - - - Indicates information relating to formatting. - - - - - Indicates LISP source file data. - - - - - Indicates information relating to margin formats. - - - - - Indicates a file containing menu. - - - - - Indicates numerically identified string table. - - - - - Indicates Maker Interchange Format (MIF) data. - - - - - Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. - - - - - Indicates GNU Machine Object data. - - - - - Indicates Message Librarian strings created by Novell's Message Librarian Tool. - - - - - Indicates information to be displayed at the bottom of each page of a document. - - - - - Indicates information to be displayed at the top of each page of a document. - - - - - Indicates a list of property values (e.g., settings within INI files or preferences dialog). - - - - - Indicates Pascal source file data. - - - - - Indicates Hypertext Preprocessor data. - - - - - Indicates plain text file (no formatting other than, possibly, wrapping). - - - - - Indicates GNU Portable Object file. - - - - - Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. - - - - - Indicates Windows .NET binary resources. - - - - - Indicates Windows .NET Resources. - - - - - Indicates Rich Text Format (RTF) data. - - - - - Indicates Standard Generalized Markup Language (SGML) data - document instance. - - - - - Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). - - - - - Indicates Scalable Vector Graphic (SVG) data. - - - - - Indicates VisualBasic Script source file. - - - - - Indicates warning message. - - - - - Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). - - - - - Indicates Extensible HyperText Markup Language (XHTML) data - document instance. - - - - - Indicates Extensible Markup Language (XML) data - document instance. - - - - - Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). - - - - - Indicates Extensible Stylesheet Language (XSL) data. - - - - - Indicates XUL elements. - - - - - - - Values for the attribute 'mtype'. - - - - - Indicates the marked text is an abbreviation. - - - - - ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. - - - - - ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). - - - - - ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). - - - - - ISO-12620: A proper-name term, such as the name of an agency or other proper entity. - - - - - ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. - - - - - ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. - - - - - Indicates the marked text is a date and/or time. - - - - - ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. - - - - - ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. - - - - - ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. - - - - - ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. - - - - - ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). - - - - - ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. - - - - - ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. - - - - - ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. - - - - - ISO-12620 2.1.17: A unit to track object. - - - - - Indicates the marked text is a name. - - - - - ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. - - - - - ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. - - - - - Indicates the marked text is a phrase. - - - - - ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. - - - - - Indicates the marked text should not be translated. - - - - - ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. - - - - - Indicates that the marked text represents a segment. - - - - - ISO-12620 2.1.18.2: A fixed, lexicalized phrase. - - - - - ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). - - - - - ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. - - - - - ISO-12620 2.1.19: A fixed chunk of recurring text. - - - - - ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. - - - - - ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. - - - - - ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. - - - - - Indicates the marked text is a term. - - - - - ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. - - - - - ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. - - - - - ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). - - - - - ISO-12620 2.1.9: One of the alternate forms of a term. - - - - - - - Values for the attribute 'restype'. - - - - - Indicates a Windows RC AUTO3STATE control. - - - - - Indicates a Windows RC AUTOCHECKBOX control. - - - - - Indicates a Windows RC AUTORADIOBUTTON control. - - - - - Indicates a Windows RC BEDIT control. - - - - - Indicates a bitmap, for example a BITMAP resource in Windows. - - - - - Indicates a button object, for example a BUTTON control Windows. - - - - - Indicates a caption, such as the caption of a dialog box. - - - - - Indicates the cell in a table, for example the content of the <td> element in HTML. - - - - - Indicates check box object, for example a CHECKBOX control in Windows. - - - - - Indicates a menu item with an associated checkbox. - - - - - Indicates a list box, but with a check-box for each item. - - - - - Indicates a color selection dialog. - - - - - Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. - - - - - Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). - - - - - Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). - - - - - Indicates a UI base class element that cannot be represented by any other element. - - - - - Indicates a context menu. - - - - - Indicates a Windows RC CTEXT control. - - - - - Indicates a cursor, for example a CURSOR resource in Windows. - - - - - Indicates a date/time picker. - - - - - Indicates a Windows RC DEFPUSHBUTTON control. - - - - - Indicates a dialog box. - - - - - Indicates a Windows RC DLGINIT resource block. - - - - - Indicates an edit box object, for example an EDIT control in Windows. - - - - - Indicates a filename. - - - - - Indicates a file dialog. - - - - - Indicates a footnote. - - - - - Indicates a font name. - - - - - Indicates a footer. - - - - - Indicates a frame object. - - - - - Indicates a XUL grid element. - - - - - Indicates a groupbox object, for example a GROUPBOX control in Windows. - - - - - Indicates a header item. - - - - - Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. - - - - - Indicates a Windows RC HEDIT control. - - - - - Indicates a horizontal scrollbar. - - - - - Indicates an icon, for example an ICON resource in Windows. - - - - - Indicates a Windows RC IEDIT control. - - - - - Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. - - - - - Indicates a label object. - - - - - Indicates a label that is also a HTML link (not necessarily a URL). - - - - - Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). - - - - - Indicates a listbox object, for example an LISTBOX control in Windows. - - - - - Indicates an list item (an entry in a list). - - - - - Indicates a Windows RC LTEXT control. - - - - - Indicates a menu (a group of menu-items). - - - - - Indicates a toolbar containing one or more tope level menus. - - - - - Indicates a menu item (an entry in a menu). - - - - - Indicates a XUL menuseparator element. - - - - - Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. - - - - - Indicates a calendar control. - - - - - Indicates an edit box beside a spin control. - - - - - Indicates a catch all for rectangular areas. - - - - - Indicates a standalone menu not necessarily associated with a menubar. - - - - - Indicates a pushbox object, for example a PUSHBOX control in Windows. - - - - - Indicates a Windows RC PUSHBUTTON control. - - - - - Indicates a radio button object. - - - - - Indicates a menuitem with associated radio button. - - - - - Indicates raw data resources for an application. - - - - - Indicates a row in a table. - - - - - Indicates a Windows RC RTEXT control. - - - - - Indicates a user navigable container used to show a portion of a document. - - - - - Indicates a generic divider object (e.g. menu group separator). - - - - - Windows accelerators, shortcuts in resource or property files. - - - - - Indicates a UI control to indicate process activity but not progress. - - - - - Indicates a splitter bar. - - - - - Indicates a Windows RC STATE3 control. - - - - - Indicates a window for providing feedback to the users, like 'read-only', etc. - - - - - Indicates a string, for example an entry in a STRINGTABLE resource in Windows. - - - - - Indicates a layers of controls with a tab to select layers. - - - - - Indicates a display and edits regular two-dimensional tables of cells. - - - - - Indicates a XUL textbox element. - - - - - Indicates a UI button that can be toggled to on or off state. - - - - - Indicates an array of controls, usually buttons. - - - - - Indicates a pop up tool tip text. - - - - - Indicates a bar with a pointer indicating a position within a certain range. - - - - - Indicates a control that displays a set of hierarchical data. - - - - - Indicates a URI (URN or URL). - - - - - Indicates a Windows RC USERBUTTON control. - - - - - Indicates a user-defined control like CONTROL control in Windows. - - - - - Indicates the text of a variable. - - - - - Indicates version information about a resource like VERSIONINFO in Windows. - - - - - Indicates a vertical scrollbar. - - - - - Indicates a graphical window. - - - - - - - Values for the attribute 'size-unit'. - - - - - Indicates a size in 8-bit bytes. - - - - - Indicates a size in Unicode characters. - - - - - Indicates a size in columns. Used for HTML text area. - - - - - Indicates a size in centimeters. - - - - - Indicates a size in dialog units, as defined in Windows resources. - - - - - Indicates a size in 'font-size' units (as defined in CSS). - - - - - Indicates a size in 'x-height' units (as defined in CSS). - - - - - Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' - - - - - Indicates a size in inches. - - - - - Indicates a size in millimeters. - - - - - Indicates a size in percentage. - - - - - Indicates a size in pixels. - - - - - Indicates a size in point. - - - - - Indicates a size in rows. Used for HTML text area. - - - - - - - Values for the attribute 'state'. - - - - - Indicates the terminating state. - - - - - Indicates only non-textual information needs adaptation. - - - - - Indicates both text and non-textual information needs adaptation. - - - - - Indicates only non-textual information needs review. - - - - - Indicates both text and non-textual information needs review. - - - - - Indicates that only the text of the item needs to be reviewed. - - - - - Indicates that the item needs to be translated. - - - - - Indicates that the item is new. For example, translation units that were not in a previous version of the document. - - - - - Indicates that changes are reviewed and approved. - - - - - Indicates that the item has been translated. - - - - - - - Values for the attribute 'state-qualifier'. - - - - - Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. - - - - - Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). - - - - - Indicates a match based on matching IDs (in addition to matching text). - - - - - Indicates a translation derived from a glossary. - - - - - Indicates a translation derived from existing translation. - - - - - Indicates a translation derived from machine translation. - - - - - Indicates a translation derived from a translation repository. - - - - - Indicates a translation derived from a translation memory. - - - - - Indicates the translation is suggested by machine translation. - - - - - Indicates that the item has been rejected because of incorrect grammar. - - - - - Indicates that the item has been rejected because it is incorrect. - - - - - Indicates that the item has been rejected because it is too long or too short. - - - - - Indicates that the item has been rejected because of incorrect spelling. - - - - - Indicates the translation is suggested by translation memory. - - - - - - - Values for the attribute 'unit'. - - - - - Refers to words. - - - - - Refers to pages. - - - - - Refers to <trans-unit> elements. - - - - - Refers to <bin-unit> elements. - - - - - Refers to glyphs. - - - - - Refers to <trans-unit> and/or <bin-unit> elements. - - - - - Refers to the occurrences of instances defined by the count-type value. - - - - - Refers to characters. - - - - - Refers to lines. - - - - - Refers to sentences. - - - - - Refers to paragraphs. - - - - - Refers to segments. - - - - - Refers to placeables (inline elements). - - - - - - - Values for the attribute 'priority'. - - - - - Highest priority. - - - - - High priority. - - - - - High priority, but not as important as 2. - - - - - High priority, but not as important as 3. - - - - - Medium priority, but more important than 6. - - - - - Medium priority, but less important than 5. - - - - - Low priority, but more important than 8. - - - - - Low priority, but more important than 9. - - - - - Low priority. - - - - - Lowest priority. - - - - - - - - - This value indicates that all properties can be reformatted. This value must be used alone. - - - - - This value indicates that no properties should be reformatted. This value must be used alone. - - - - - - - - - - - - - This value indicates that all information in the coord attribute can be modified. - - - - - This value indicates that the x information in the coord attribute can be modified. - - - - - This value indicates that the y information in the coord attribute can be modified. - - - - - This value indicates that the cx information in the coord attribute can be modified. - - - - - This value indicates that the cy information in the coord attribute can be modified. - - - - - This value indicates that all the information in the font attribute can be modified. - - - - - This value indicates that the name information in the font attribute can be modified. - - - - - This value indicates that the size information in the font attribute can be modified. - - - - - This value indicates that the weight information in the font attribute can be modified. - - - - - This value indicates that the information in the css-style attribute can be modified. - - - - - This value indicates that the information in the style attribute can be modified. - - - - - This value indicates that the information in the exstyle attribute can be modified. - - - - - - - - - - - - - Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. - - - - - Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. - - - - - Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. - - - - - - - - - Represents a translation proposal from a translation memory or other resource. - - - - - Represents a previous version of the target element. - - - - - Represents a rejected version of the target element. - - - - - Represents a translation to be used for reference purposes only, for example from a related product or a different language. - - - - - Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Values for the attribute 'coord'. - - - - - - - - Version values: 1.0 and 1.1 are allowed for backward compatibility. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + Values for the attribute 'context-type'. + + + + + Indicates a database content. + + + + + Indicates the content of an element within an XML document. + + + + + Indicates the name of an element within an XML document. + + + + + Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. + + + + + Indicates a the number of parameters contained within the <source>. + + + + + Indicates notes pertaining to the parameters in the <source>. + + + + + Indicates the content of a record within a database. + + + + + Indicates the name of a record within a database. + + + + + Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. + + + + + + + Values for the attribute 'count-type'. + + + + + Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. + + + + + Indicates the count units are translation units existing already in the same document. + + + + + Indicates a total count. + + + + + + + Values for the attribute 'ctype' when used other elements than <ph> or <x>. + + + + + Indicates a run of bolded text. + + + + + Indicates a run of text in italics. + + + + + Indicates a run of underlined text. + + + + + Indicates a run of hyper-text. + + + + + + + Values for the attribute 'ctype' when used with <ph> or <x>. + + + + + Indicates a inline image. + + + + + Indicates a page break. + + + + + Indicates a line break. + + + + + + + + + + + + Values for the attribute 'datatype'. + + + + + Indicates Active Server Page data. + + + + + Indicates C source file data. + + + + + Indicates Channel Definition Format (CDF) data. + + + + + Indicates ColdFusion data. + + + + + Indicates C++ source file data. + + + + + Indicates C-Sharp data. + + + + + Indicates strings from C, ASM, and driver files data. + + + + + Indicates comma-separated values data. + + + + + Indicates database data. + + + + + Indicates portions of document that follows data and contains metadata. + + + + + Indicates portions of document that precedes data and contains metadata. + + + + + Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). + + + + + Indicates standard user input screen data. + + + + + Indicates HyperText Markup Language (HTML) data - document instance. + + + + + Indicates content within an HTML document’s <body> element. + + + + + Indicates Windows INI file data. + + + + + Indicates Interleaf data. + + + + + Indicates Java source file data (extension '.java'). + + + + + Indicates Java property resource bundle data. + + + + + Indicates Java list resource bundle data. + + + + + Indicates JavaScript source file data. + + + + + Indicates JScript source file data. + + + + + Indicates information relating to formatting. + + + + + Indicates LISP source file data. + + + + + Indicates information relating to margin formats. + + + + + Indicates a file containing menu. + + + + + Indicates numerically identified string table. + + + + + Indicates Maker Interchange Format (MIF) data. + + + + + Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. + + + + + Indicates GNU Machine Object data. + + + + + Indicates Message Librarian strings created by Novell's Message Librarian Tool. + + + + + Indicates information to be displayed at the bottom of each page of a document. + + + + + Indicates information to be displayed at the top of each page of a document. + + + + + Indicates a list of property values (e.g., settings within INI files or preferences dialog). + + + + + Indicates Pascal source file data. + + + + + Indicates Hypertext Preprocessor data. + + + + + Indicates plain text file (no formatting other than, possibly, wrapping). + + + + + Indicates GNU Portable Object file. + + + + + Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. + + + + + Indicates Windows .NET binary resources. + + + + + Indicates Windows .NET Resources. + + + + + Indicates Rich Text Format (RTF) data. + + + + + Indicates Standard Generalized Markup Language (SGML) data - document instance. + + + + + Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). + + + + + Indicates Scalable Vector Graphic (SVG) data. + + + + + Indicates VisualBasic Script source file. + + + + + Indicates warning message. + + + + + Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). + + + + + Indicates Extensible HyperText Markup Language (XHTML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). + + + + + Indicates Extensible Stylesheet Language (XSL) data. + + + + + Indicates XUL elements. + + + + + + + Values for the attribute 'mtype'. + + + + + Indicates the marked text is an abbreviation. + + + + + ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. + + + + + ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). + + + + + ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). + + + + + ISO-12620: A proper-name term, such as the name of an agency or other proper entity. + + + + + ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. + + + + + ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. + + + + + Indicates the marked text is a date and/or time. + + + + + ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. + + + + + ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. + + + + + ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. + + + + + ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. + + + + + ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). + + + + + ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. + + + + + ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. + + + + + ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. + + + + + ISO-12620 2.1.17: A unit to track object. + + + + + Indicates the marked text is a name. + + + + + ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. + + + + + ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. + + + + + Indicates the marked text is a phrase. + + + + + ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. + + + + + Indicates the marked text should not be translated. + + + + + ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. + + + + + Indicates that the marked text represents a segment. + + + + + ISO-12620 2.1.18.2: A fixed, lexicalized phrase. + + + + + ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). + + + + + ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. + + + + + ISO-12620 2.1.19: A fixed chunk of recurring text. + + + + + ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. + + + + + ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. + + + + + ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. + + + + + Indicates the marked text is a term. + + + + + ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. + + + + + ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. + + + + + ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). + + + + + ISO-12620 2.1.9: One of the alternate forms of a term. + + + + + + + Values for the attribute 'restype'. + + + + + Indicates a Windows RC AUTO3STATE control. + + + + + Indicates a Windows RC AUTOCHECKBOX control. + + + + + Indicates a Windows RC AUTORADIOBUTTON control. + + + + + Indicates a Windows RC BEDIT control. + + + + + Indicates a bitmap, for example a BITMAP resource in Windows. + + + + + Indicates a button object, for example a BUTTON control Windows. + + + + + Indicates a caption, such as the caption of a dialog box. + + + + + Indicates the cell in a table, for example the content of the <td> element in HTML. + + + + + Indicates check box object, for example a CHECKBOX control in Windows. + + + + + Indicates a menu item with an associated checkbox. + + + + + Indicates a list box, but with a check-box for each item. + + + + + Indicates a color selection dialog. + + + + + Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. + + + + + Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). + + + + + Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). + + + + + Indicates a UI base class element that cannot be represented by any other element. + + + + + Indicates a context menu. + + + + + Indicates a Windows RC CTEXT control. + + + + + Indicates a cursor, for example a CURSOR resource in Windows. + + + + + Indicates a date/time picker. + + + + + Indicates a Windows RC DEFPUSHBUTTON control. + + + + + Indicates a dialog box. + + + + + Indicates a Windows RC DLGINIT resource block. + + + + + Indicates an edit box object, for example an EDIT control in Windows. + + + + + Indicates a filename. + + + + + Indicates a file dialog. + + + + + Indicates a footnote. + + + + + Indicates a font name. + + + + + Indicates a footer. + + + + + Indicates a frame object. + + + + + Indicates a XUL grid element. + + + + + Indicates a groupbox object, for example a GROUPBOX control in Windows. + + + + + Indicates a header item. + + + + + Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. + + + + + Indicates a Windows RC HEDIT control. + + + + + Indicates a horizontal scrollbar. + + + + + Indicates an icon, for example an ICON resource in Windows. + + + + + Indicates a Windows RC IEDIT control. + + + + + Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. + + + + + Indicates a label object. + + + + + Indicates a label that is also a HTML link (not necessarily a URL). + + + + + Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). + + + + + Indicates a listbox object, for example an LISTBOX control in Windows. + + + + + Indicates an list item (an entry in a list). + + + + + Indicates a Windows RC LTEXT control. + + + + + Indicates a menu (a group of menu-items). + + + + + Indicates a toolbar containing one or more tope level menus. + + + + + Indicates a menu item (an entry in a menu). + + + + + Indicates a XUL menuseparator element. + + + + + Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. + + + + + Indicates a calendar control. + + + + + Indicates an edit box beside a spin control. + + + + + Indicates a catch all for rectangular areas. + + + + + Indicates a standalone menu not necessarily associated with a menubar. + + + + + Indicates a pushbox object, for example a PUSHBOX control in Windows. + + + + + Indicates a Windows RC PUSHBUTTON control. + + + + + Indicates a radio button object. + + + + + Indicates a menuitem with associated radio button. + + + + + Indicates raw data resources for an application. + + + + + Indicates a row in a table. + + + + + Indicates a Windows RC RTEXT control. + + + + + Indicates a user navigable container used to show a portion of a document. + + + + + Indicates a generic divider object (e.g. menu group separator). + + + + + Windows accelerators, shortcuts in resource or property files. + + + + + Indicates a UI control to indicate process activity but not progress. + + + + + Indicates a splitter bar. + + + + + Indicates a Windows RC STATE3 control. + + + + + Indicates a window for providing feedback to the users, like 'read-only', etc. + + + + + Indicates a string, for example an entry in a STRINGTABLE resource in Windows. + + + + + Indicates a layers of controls with a tab to select layers. + + + + + Indicates a display and edits regular two-dimensional tables of cells. + + + + + Indicates a XUL textbox element. + + + + + Indicates a UI button that can be toggled to on or off state. + + + + + Indicates an array of controls, usually buttons. + + + + + Indicates a pop up tool tip text. + + + + + Indicates a bar with a pointer indicating a position within a certain range. + + + + + Indicates a control that displays a set of hierarchical data. + + + + + Indicates a URI (URN or URL). + + + + + Indicates a Windows RC USERBUTTON control. + + + + + Indicates a user-defined control like CONTROL control in Windows. + + + + + Indicates the text of a variable. + + + + + Indicates version information about a resource like VERSIONINFO in Windows. + + + + + Indicates a vertical scrollbar. + + + + + Indicates a graphical window. + + + + + + + Values for the attribute 'size-unit'. + + + + + Indicates a size in 8-bit bytes. + + + + + Indicates a size in Unicode characters. + + + + + Indicates a size in columns. Used for HTML text area. + + + + + Indicates a size in centimeters. + + + + + Indicates a size in dialog units, as defined in Windows resources. + + + + + Indicates a size in 'font-size' units (as defined in CSS). + + + + + Indicates a size in 'x-height' units (as defined in CSS). + + + + + Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' + + + + + Indicates a size in inches. + + + + + Indicates a size in millimeters. + + + + + Indicates a size in percentage. + + + + + Indicates a size in pixels. + + + + + Indicates a size in point. + + + + + Indicates a size in rows. Used for HTML text area. + + + + + + + Values for the attribute 'state'. + + + + + Indicates the terminating state. + + + + + Indicates only non-textual information needs adaptation. + + + + + Indicates both text and non-textual information needs adaptation. + + + + + Indicates only non-textual information needs review. + + + + + Indicates both text and non-textual information needs review. + + + + + Indicates that only the text of the item needs to be reviewed. + + + + + Indicates that the item needs to be translated. + + + + + Indicates that the item is new. For example, translation units that were not in a previous version of the document. + + + + + Indicates that changes are reviewed and approved. + + + + + Indicates that the item has been translated. + + + + + + + Values for the attribute 'state-qualifier'. + + + + + Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. + + + + + Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). + + + + + Indicates a match based on matching IDs (in addition to matching text). + + + + + Indicates a translation derived from a glossary. + + + + + Indicates a translation derived from existing translation. + + + + + Indicates a translation derived from machine translation. + + + + + Indicates a translation derived from a translation repository. + + + + + Indicates a translation derived from a translation memory. + + + + + Indicates the translation is suggested by machine translation. + + + + + Indicates that the item has been rejected because of incorrect grammar. + + + + + Indicates that the item has been rejected because it is incorrect. + + + + + Indicates that the item has been rejected because it is too long or too short. + + + + + Indicates that the item has been rejected because of incorrect spelling. + + + + + Indicates the translation is suggested by translation memory. + + + + + + + Values for the attribute 'unit'. + + + + + Refers to words. + + + + + Refers to pages. + + + + + Refers to <trans-unit> elements. + + + + + Refers to <bin-unit> elements. + + + + + Refers to glyphs. + + + + + Refers to <trans-unit> and/or <bin-unit> elements. + + + + + Refers to the occurrences of instances defined by the count-type value. + + + + + Refers to characters. + + + + + Refers to lines. + + + + + Refers to sentences. + + + + + Refers to paragraphs. + + + + + Refers to segments. + + + + + Refers to placeables (inline elements). + + + + + + + Values for the attribute 'priority'. + + + + + Highest priority. + + + + + High priority. + + + + + High priority, but not as important as 2. + + + + + High priority, but not as important as 3. + + + + + Medium priority, but more important than 6. + + + + + Medium priority, but less important than 5. + + + + + Low priority, but more important than 8. + + + + + Low priority, but more important than 9. + + + + + Low priority. + + + + + Lowest priority. + + + + + + + + + This value indicates that all properties can be reformatted. This value must be used alone. + + + + + This value indicates that no properties should be reformatted. This value must be used alone. + + + + + + + + + + + + + This value indicates that all information in the coord attribute can be modified. + + + + + This value indicates that the x information in the coord attribute can be modified. + + + + + This value indicates that the y information in the coord attribute can be modified. + + + + + This value indicates that the cx information in the coord attribute can be modified. + + + + + This value indicates that the cy information in the coord attribute can be modified. + + + + + This value indicates that all the information in the font attribute can be modified. + + + + + This value indicates that the name information in the font attribute can be modified. + + + + + This value indicates that the size information in the font attribute can be modified. + + + + + This value indicates that the weight information in the font attribute can be modified. + + + + + This value indicates that the information in the css-style attribute can be modified. + + + + + This value indicates that the information in the style attribute can be modified. + + + + + This value indicates that the information in the exstyle attribute can be modified. + + + + + + + + + + + + + Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. + + + + + Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. + + + + + Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. + + + + + + + + + Represents a translation proposal from a translation memory or other resource. + + + + + Represents a previous version of the target element. + + + + + Represents a rejected version of the target element. + + + + + Represents a translation to be used for reference purposes only, for example from a related product or a different language. + + + + + Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Values for the attribute 'coord'. + + + + + + + + Version values: 1.0 and 1.1 are allowed for backward compatibility. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 86b850ebd8f7843a8a85cbe8a48953811c5ef32e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 7 Apr 2018 16:29:23 +0200 Subject: [PATCH 16/75] [HttpKernel] Dont create mock cookie for new sessions in tests --- .../EventListener/AbstractTestSessionListener.php | 2 +- .../Tests/EventListener/TestSessionListenerTest.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php index 0a153dd943297..82061fd6ea0fc 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php @@ -69,7 +69,7 @@ public function onKernelResponse(FilterResponseEvent $event) $session->save(); } - if ($session instanceof Session ? !$session->isEmpty() || $session->getId() !== $this->sessionId : $wasStarted) { + if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { $params = session_get_cookie_params(); $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); $this->sessionId = $session->getId(); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php index 0a2263d5a8e78..22a2b71239874 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -46,6 +45,9 @@ protected function setUp() { $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener'); $this->session = $this->getSession(); + $this->listener->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($this->session)); } public function testShouldSaveMasterRequestSession() @@ -95,7 +97,7 @@ public function testEmptySessionWithNewSessionIdDoesSendCookie() $this->fixSessionId('456'); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); - $request = Request::create('/', 'GET', array(), array(new Cookie('MOCKSESSID', '123'))); + $request = Request::create('/', 'GET', array(), array('MOCKSESSID' => '123')); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $this->listener->onKernelRequest($event); From cd914209bd3acbc637c4b435626f003696ebacb7 Mon Sep 17 00:00:00 2001 From: Pascal Montoya <> Date: Fri, 6 Apr 2018 07:52:15 +0200 Subject: [PATCH 17/75] [Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't an existing class --- .../Factory/LazyLoadingMetadataFactory.php | 8 ++++---- .../Factory/LazyLoadingMetadataFactoryTest.php | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index 1a4f3074b6e4f..84375ec69495e 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -90,6 +90,10 @@ public function getMetadataFor($value) return $this->loadedClasses[$class]; } + if (!class_exists($class) && !interface_exists($class)) { + throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); + } + if (null !== $this->cache && false !== ($metadata = $this->cache->read($class))) { // Include constraints from the parent class $this->mergeConstraints($metadata); @@ -97,10 +101,6 @@ public function getMetadataFor($value) return $this->loadedClasses[$class] = $metadata; } - if (!class_exists($class) && !interface_exists($class)) { - throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); - } - $metadata = new ClassMetadata($class); if (null !== $this->loader) { diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index b5d1a9dc84d4d..de6852271e17f 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -149,6 +149,21 @@ public function testReadMetadataFromCache() $this->assertEquals($metadata, $factory->getMetadataFor(self::PARENT_CLASS)); } + /** + * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException + */ + public function testNonClassNameStringValues() + { + $testedValue = 'error@example.com'; + $loader = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); + $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock(); + $factory = new LazyLoadingMetadataFactory($loader, $cache); + $cache + ->expects($this->never()) + ->method('read'); + $factory->getMetadataFor($testedValue); + } + public function testMetadataCacheWithRuntimeConstraint() { $cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock(); From 5198f435a047aad8d5ed119e918cf8c008ea65b7 Mon Sep 17 00:00:00 2001 From: Pascal Montoya Date: Mon, 9 Apr 2018 10:29:56 +0200 Subject: [PATCH 18/75] Disable autoloader call on interface_exists check --- .../Validator/Mapping/Factory/LazyLoadingMetadataFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index 84375ec69495e..e088caa897a71 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -90,7 +90,7 @@ public function getMetadataFor($value) return $this->loadedClasses[$class]; } - if (!class_exists($class) && !interface_exists($class)) { + if (!class_exists($class) && !interface_exists($class, false)) { throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); } From 7f398117f490b724dcfedd3663c76dfc49553392 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 7 Apr 2018 15:42:06 +0200 Subject: [PATCH 19/75] [DI] Improve error message for non-autowirable scalar argument --- .../Compiler/AutowirePass.php | 5 ++++- .../Tests/Compiler/AutowirePassTest.php | 22 ++++++++++++++++++- .../Fixtures/includes/autowiring_classes.php | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 8bfc3cd9d9677..803490cecd295 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -233,7 +233,10 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a if ($parameter->isOptional()) { continue; } - throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" must have a type-hint or be given a value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); + $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false); + $type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint'; + + throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type)); } // specifically pass the default value diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index ee0b4baef8452..924a490942492 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -436,6 +436,7 @@ public function testSomeSpecificArgumentsAreSet() // args are: A, Foo, Dunglas ->setArguments(array( 1 => new Reference('foo'), + 3 => array('bar'), )); (new ResolveClassPass())->process($container); @@ -447,6 +448,7 @@ public function testSomeSpecificArgumentsAreSet() new TypedReference(A::class, A::class, MultipleArguments::class), new Reference('foo'), new TypedReference(Dunglas::class, Dunglas::class, MultipleArguments::class), + array('bar'), ), $definition->getArguments() ); @@ -454,12 +456,30 @@ public function testSomeSpecificArgumentsAreSet() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" must have a type-hint or be given a value explicitly. + * @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$bar" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" is type-hinted "array", you should configure its value explicitly. */ public function testScalarArgsCannotBeAutowired() { $container = new ContainerBuilder(); + $container->register(A::class); + $container->register(Dunglas::class); + $container->register('arg_no_type_hint', __NAMESPACE__.'\MultipleArguments') + ->setArguments(array(1 => 'foo')) + ->setAutowired(true); + + (new ResolveClassPass())->process($container); + (new AutowirePass())->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" has no type-hint, you should configure its value explicitly. + */ + public function testNoTypeArgsCannotBeAutowired() + { + $container = new ContainerBuilder(); + $container->register(A::class); $container->register(Dunglas::class); $container->register('arg_no_type_hint', __NAMESPACE__.'\MultipleArguments') diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php index 990a873f34985..6f93957753a49 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php @@ -181,7 +181,7 @@ public function __construct(A $k) } class MultipleArguments { - public function __construct(A $k, $foo, Dunglas $dunglas) + public function __construct(A $k, $foo, Dunglas $dunglas, array $bar) { } } From adba79a6b01800bd7cc0bc9795dcb46539330f7f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Apr 2018 12:07:56 -0500 Subject: [PATCH 20/75] [Console] Don't go past exact matches when autocompleting --- .../Console/Helper/QuestionHelper.php | 2 +- .../Tests/Helper/QuestionHelperTest.php | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index bce0534ed0991..36187f8cea486 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -284,7 +284,7 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret) && $i !== strlen($value)) { + if (0 === strpos($value, $ret)) { $matches[$numMatches++] = $value; } } diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index d9bdb606ac340..9f837d0f9ed49 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -160,6 +160,30 @@ public function testAskWithAutocompleteWithNonSequentialKeys() $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); } + public function testAskWithAutocompleteWithExactMatch() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + $inputStream = $this->getInputStream("b\n"); + + $possibleChoices = array( + 'a' => 'berlin', + 'b' => 'copenhagen', + 'c' => 'amsterdam', + ); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($inputStream); + $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); + + $question = new ChoiceQuestion('Please select a city', $possibleChoices); + $question->setMaxAttempts(1); + + $this->assertSame('b', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + public function testAutocompleteWithTrailingBackslash() { if (!$this->hasSttyAvailable()) { From 2a9c668ad7f187a94e8d071d51ad300b22c57520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Tue, 10 Apr 2018 18:33:39 +0200 Subject: [PATCH 21/75] [Routing] Fix loading multiple class annotations for invokable classes --- .../Routing/Loader/AnnotationClassLoader.php | 13 +++-- .../Loader/AnnotationClassLoaderTest.php | 51 +++++++++++++++++-- .../Loader/AnnotationDirectoryLoaderTest.php | 15 +++++- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index 2fe6fb596e42a..fd1d2b655ab29 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -119,10 +119,15 @@ public function load($class, $type = null) } } - if (0 === $collection->count() && $class->hasMethod('__invoke') && $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { - $globals['path'] = ''; - $globals['name'] = ''; - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + if (0 === $collection->count() && $class->hasMethod('__invoke')) { + foreach ($this->reader->getClassAnnotations($class) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $globals['path'] = ''; + $globals['name'] = ''; + + $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + } + } } return $collection; diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php index 70db1ccd9ad6a..32e401294ec81 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -191,9 +191,9 @@ public function testInvokableClassRouteLoad() ); $this->reader - ->expects($this->exactly(2)) - ->method('getClassAnnotation') - ->will($this->returnValue($this->getAnnotatedRoute($classRouteData))) + ->expects($this->exactly(1)) + ->method('getClassAnnotations') + ->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData)))) ; $this->reader ->expects($this->once()) @@ -205,8 +205,49 @@ public function testInvokableClassRouteLoad() $route = $routeCollection->get($classRouteData['name']); $this->assertSame($classRouteData['path'], $route->getPath(), '->load preserves class route path'); - $this->assertEquals(array_merge($classRouteData['schemes'], $classRouteData['schemes']), $route->getSchemes(), '->load preserves class route schemes'); - $this->assertEquals(array_merge($classRouteData['methods'], $classRouteData['methods']), $route->getMethods(), '->load preserves class route methods'); + $this->assertEquals($classRouteData['schemes'], $route->getSchemes(), '->load preserves class route schemes'); + $this->assertEquals($classRouteData['methods'], $route->getMethods(), '->load preserves class route methods'); + } + + public function testInvokableClassMultipleRouteLoad() + { + $classRouteData1 = array( + 'name' => 'route1', + 'path' => '/1', + 'schemes' => array('https'), + 'methods' => array('GET'), + ); + + $classRouteData2 = array( + 'name' => 'route2', + 'path' => '/2', + 'schemes' => array('https'), + 'methods' => array('GET'), + ); + + $this->reader + ->expects($this->exactly(1)) + ->method('getClassAnnotations') + ->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData1), $this->getAnnotatedRoute($classRouteData2)))) + ; + $this->reader + ->expects($this->once()) + ->method('getMethodAnnotations') + ->will($this->returnValue(array())) + ; + + $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass'); + $route = $routeCollection->get($classRouteData1['name']); + + $this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path'); + $this->assertEquals($classRouteData1['schemes'], $route->getSchemes(), '->load preserves class route schemes'); + $this->assertEquals($classRouteData1['methods'], $route->getMethods(), '->load preserves class route methods'); + + $route = $routeCollection->get($classRouteData2['name']); + + $this->assertSame($classRouteData2['path'], $route->getPath(), '->load preserves class route path'); + $this->assertEquals($classRouteData2['schemes'], $route->getSchemes(), '->load preserves class route schemes'); + $this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods'); } public function testInvokableClassWithMethodRouteLoad() diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php index 1e8ee394015e1..8a6668e0c2beb 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php @@ -29,7 +29,7 @@ protected function setUp() public function testLoad() { - $this->reader->expects($this->exactly(4))->method('getClassAnnotation'); + $this->reader->expects($this->exactly(3))->method('getClassAnnotation'); $this->reader ->expects($this->any()) @@ -37,6 +37,12 @@ public function testLoad() ->will($this->returnValue(array())) ; + $this->reader + ->expects($this->any()) + ->method('getClassAnnotations') + ->will($this->returnValue(array())) + ; + $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); } @@ -45,7 +51,6 @@ public function testLoadIgnoresHiddenDirectories() $this->expectAnnotationsToBeReadFrom(array( 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass', - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass', 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\FooClass', )); @@ -55,6 +60,12 @@ public function testLoadIgnoresHiddenDirectories() ->will($this->returnValue(array())) ; + $this->reader + ->expects($this->any()) + ->method('getClassAnnotations') + ->will($this->returnValue(array())) + ; + $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); } From 99302e72fca92e53b3555981a563889043750453 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Apr 2018 17:39:33 +0200 Subject: [PATCH 22/75] fix rendering exception stack traces --- .../TwigBundle/Resources/views/Exception/traces.txt.twig | 2 -- .../Resources/views/Exception/traces_text.html.twig | 8 +++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.txt.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.txt.twig index 96ecd44480819..88a2d6922d6c3 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.txt.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.txt.twig @@ -1,5 +1,4 @@ {% if exception.trace|length %} -
 {{ exception.class }}:
 {% if exception.message is not empty %}
     {{- exception.message }}
@@ -8,5 +7,4 @@
 {% for trace in exception.trace %}
   {{ include('@Twig/Exception/trace.txt.twig', { trace: trace }, with_context = false) }}
 {% endfor %}
-
{% endif %} diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces_text.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces_text.html.twig index ffe7f31ad5ec4..318a5bbeeb0c7 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces_text.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces_text.html.twig @@ -17,7 +17,13 @@ - {{ include('@Twig/Exception/traces.txt.twig', { exception: exception }, with_context = false) }} + {% if exception.trace|length %} +
+                {%- filter escape('html') -%}
+                    {{- include('@Twig/Exception/traces.txt.twig', { exception: exception, format: 'html' }, with_context = false) }}
+                {% endfilter %}
+                
+ {% endif %} From 40bd8bd797ae8921e2a04f71a1ba7e1d3c0c29a3 Mon Sep 17 00:00:00 2001 From: Normunds Date: Mon, 9 Apr 2018 15:54:29 +0300 Subject: [PATCH 23/75] Add d-block to bootstrap 4 alerts --- .../Twig/Resources/views/Form/bootstrap_4_layout.html.twig | 2 +- .../Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php | 2 +- .../Component/Form/Tests/AbstractBootstrap4LayoutTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index df88a00011883..1c5c390954790 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -267,7 +267,7 @@ {% block form_errors -%} {%- if errors|length > 0 -%} - + {%- for error in errors -%} {{ 'Error'|trans({}, 'validators') }} {{ error.message }} diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php index c906c6549ad2f..016792e0edaf6 100644 --- a/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php @@ -32,7 +32,7 @@ public function testRow() [ ./label[@for="name"] [ - ./span[@class="alert alert-danger"] + ./span[@class="alert alert-danger d-block"] [./span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] [./span[.="[trans]Error![/trans]"]] diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php index beabaa21cdb1a..2cadba0ba9e67 100644 --- a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php @@ -32,7 +32,7 @@ public function testRow() [ ./label[@for="name"] [ - ./span[@class="alert alert-danger"] + ./span[@class="alert alert-danger d-block"] [./span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] [./span[.="[trans]Error![/trans]"]] @@ -161,7 +161,7 @@ public function testErrors() $this->assertMatchesXpath($html, '/span - [@class="alert alert-danger"] + [@class="alert alert-danger d-block"] [ ./span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] From 3b47441fd5be8714ea7086c581a2f8d07fc64173 Mon Sep 17 00:00:00 2001 From: Mathieu TUDISCO Date: Tue, 3 Apr 2018 15:10:16 +0200 Subject: [PATCH 24/75] [HttpKernel] Make ServiceValueResolver work if controller namespace starts with a backslash in routing --- .../ArgumentResolver/ServiceValueResolver.php | 12 +++++++++++- .../ServiceValueResolverTest.php | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php index c55564c0467ef..7bc195f233114 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php @@ -39,9 +39,15 @@ public function supports(Request $request, ArgumentMetadata $argument) if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; } - return \is_string($controller) && $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); } /** @@ -53,6 +59,10 @@ public function resolve(Request $request, ArgumentMetadata $argument) $controller = $controller[0].'::'.$controller[1]; } + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + yield $this->container->get($controller)->get($argument->getName()); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php index b05828f5bf6d2..7d34172ce3d8f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php @@ -47,6 +47,25 @@ public function testExistingController() $this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument)); } + public function testExistingControllerWithATrailingBackSlash() + { + $resolver = new ServiceValueResolver(new ServiceLocator(array( + 'App\\Controller\\Mine::method' => function () { + return new ServiceLocator(array( + 'dummy' => function () { + return new DummyService(); + }, + )); + }, + ))); + + $request = $this->requestWithAttributes(array('_controller' => '\\App\\Controller\\Mine::method')); + $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); + + $this->assertTrue($resolver->supports($request, $argument)); + $this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument)); + } + public function testControllerNameIsAnArray() { $resolver = new ServiceValueResolver(new ServiceLocator(array( From 00cdf5e0a51e302cf65220f4dcf049688e0114fa Mon Sep 17 00:00:00 2001 From: HeahDude Date: Sun, 15 Apr 2018 09:55:18 +0200 Subject: [PATCH 25/75] [Form] Fixed trimming choice values --- .../Form/Extension/Core/Type/ChoiceType.php | 1 + .../Extension/Core/Type/ChoiceTypeTest.php | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 601583b7839f8..19f1d62e4f371 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -413,6 +413,7 @@ public function configureOptions(OptionsResolver $resolver) // See https://github.com/symfony/symfony/pull/5582 'data_class' => null, 'choice_translation_domain' => true, + 'trim' => false, )); $resolver->setNormalizer('choices', $choicesNormalizer); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 842136e14c677..875a0ba0f60b4 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -2421,4 +2421,59 @@ public function invalidNestedValueTestMatrix() 'multiple, expanded' => array(true, true, array(array())), ); } + + /** + * @dataProvider provideTrimCases + */ + public function testTrimIsDisabled($multiple, $expanded) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'multiple' => $multiple, + 'expanded' => $expanded, + 'choices' => array( + 'a' => '1', + ), + 'choices_as_values' => true, + )); + + $submittedData = ' 1'; + + $form->submit($multiple ? (array) $submittedData : $submittedData); + + // When the choice does not exist the transformation fails + $this->assertFalse($form->isSynchronized()); + $this->assertNull($form->getData()); + } + + /** + * @dataProvider provideTrimCases + */ + public function testSubmitValueWithWhiteSpace($multiple, $expanded) + { + $valueWhitWhiteSpace = '1 '; + + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'multiple' => $multiple, + 'expanded' => $expanded, + 'choices' => array( + 'a' => $valueWhitWhiteSpace, + ), + 'choices_as_values' => true, + )); + + $form->submit($multiple ? (array) $valueWhitWhiteSpace : $valueWhitWhiteSpace); + + $this->assertTrue($form->isSynchronized()); + $this->assertSame($multiple ? (array) $valueWhitWhiteSpace : $valueWhitWhiteSpace, $form->getData()); + } + + public function provideTrimCases() + { + return array( + 'Simple' => array(false, false), + 'Multiple' => array(true, false), + 'Simple expanded' => array(false, true), + 'Multiple expanded' => array(true, true), + ); + } } From 3d27b5946db147da7d96b14bb2a89b8a25d8a58b Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Thu, 22 Mar 2018 20:40:31 +0100 Subject: [PATCH 26/75] Fix that ESI/SSI processing can turn a \"private\" response \"public\" --- .../Component/HttpFoundation/Response.php | 10 +++++++-- .../HttpCache/ResponseCacheStrategy.php | 2 +- .../HttpCache/ResponseCacheStrategyTest.php | 22 +++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 4aabc0da236b1..cbeaf27621f2c 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -507,13 +507,19 @@ public function getCharset() } /** - * Returns true if the response is worth caching under any circumstance. + * Returns true if the response may safely be kept in a shared (surrogate) cache. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable. + * validator (Last-Modified, ETag) are considered uncacheable because there is + * no way to tell when or how to remove them from the cache. + * + * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, + * for example "status codes that are defined as cacheable by default [...] + * can be reused by a cache with heuristic expiration unless otherwise indicated" + * (https://tools.ietf.org/html/rfc7231#section-6.1) * * @return bool true if the response is worth caching, false otherwise */ diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 027b2b1761334..672cc893feb6d 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -72,7 +72,7 @@ public function update(Response $response) $response->setLastModified(null); } - if (!$response->isFresh()) { + if (!$response->isFresh() || !$response->isCacheable()) { $this->cacheable = false; } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index 5e4c322223eb3..6d67a177398c2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -175,8 +175,26 @@ public function testEmbeddingPrivateResponseMakesMainResponsePrivate() $cacheStrategy->update($masterResponse); $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); - // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and - // that's the more conservative of both the master and embedded response...? + $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public')); + } + + public function testEmbeddingPublicResponseDoesNotMakeMainResponsePublic() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setPrivate(); // this is the default, but let's be explicit + $masterResponse->setMaxAge(100); + + $embeddedResponse = new Response(); + $embeddedResponse->setPublic(); + $embeddedResponse->setSharedMaxAge(100); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); + $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public')); } public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation() From e2c1f24fbd17c47e32ecc2531950ab8d79ce4a7f Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Wed, 11 Apr 2018 14:53:24 +0200 Subject: [PATCH 27/75] Don't assume that file binary exists on *nix OS Certain lightweight distributions such as Alpine Linux (popular for smaller Docker images) do not include it by default. --- .../File/MimeType/FileBinaryMimeTypeGuesser.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php index c2ac6768c3013..3c358104651b8 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -43,7 +43,21 @@ public function __construct($cmd = 'file -b --mime %s 2>/dev/null') */ public static function isSupported() { - return '\\' !== DIRECTORY_SEPARATOR && function_exists('passthru') && function_exists('escapeshellarg'); + static $supported = null; + + if (null !== $supported) { + return $supported; + } + + if ('\\' === DIRECTORY_SEPARATOR || !function_exists('passthru') || !function_exists('escapeshellarg')) { + return $supported = false; + } + + ob_start(); + passthru('command -v file', $exitStatus); + $binPath = trim(ob_get_clean()); + + return $supported = 0 === $exitStatus && '' !== $binPath; } /** From a28393e482ec6f45f1e6693eb0876f61ffb4b54c Mon Sep 17 00:00:00 2001 From: "Pavel.Batanov" Date: Tue, 17 Apr 2018 11:56:08 +0300 Subject: [PATCH 28/75] Fix PSR exception context key --- src/Symfony/Component/Console/EventListener/ErrorListener.php | 4 ++-- .../Console/Tests/EventListener/ErrorListenerTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/EventListener/ErrorListener.php b/src/Symfony/Component/Console/EventListener/ErrorListener.php index 3774f9e6666d4..909d6ea3a1ddb 100644 --- a/src/Symfony/Component/Console/EventListener/ErrorListener.php +++ b/src/Symfony/Component/Console/EventListener/ErrorListener.php @@ -40,10 +40,10 @@ public function onConsoleError(ConsoleErrorEvent $event) $error = $event->getError(); if (!$inputString = $this->getInputString($event)) { - return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage())); + return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => $error->getMessage())); } - $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage())); + $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => $inputString, 'message' => $error->getMessage())); } public function onConsoleTerminate(ConsoleTerminateEvent $event) diff --git a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php index 17eaae09084c8..3794a2660ab5f 100644 --- a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php +++ b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php @@ -34,7 +34,7 @@ public function testOnConsoleError() $logger ->expects($this->once()) ->method('error') - ->with('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred')) + ->with('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred')) ; $listener = new ErrorListener($logger); @@ -49,7 +49,7 @@ public function testOnConsoleErrorWithNoCommandAndNoInputString() $logger ->expects($this->once()) ->method('error') - ->with('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => 'An error occurred')) + ->with('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => 'An error occurred')) ; $listener = new ErrorListener($logger); From f1c1d36fdaf0080aeacc3a6479839b22437a795c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 19 Apr 2018 10:26:28 +0200 Subject: [PATCH 29/75] fix formatting arguments in plaintext format --- .../Bundle/TwigBundle/Resources/views/Exception/trace.txt.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.txt.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.txt.twig index fb1e49d826eb5..538355cbe17f1 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.txt.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.txt.twig @@ -1,5 +1,5 @@ {% if trace.function %} -at {{ trace.class ~ trace.type ~ trace.function }}({{ trace.args|format_args }}) +at {{ trace.class ~ trace.type ~ trace.function }}({{ trace.args|format_args_as_text }}) {%- endif -%} {% if trace.file|default('') is not empty and trace.line|default('') is not empty %} {{- trace.function ? '\n (' : 'at '}}{{ trace.file|format_file(trace.line)|striptags|replace({ (' at line ' ~ trace.line): '' }) }}:{{ trace.line }}{{ trace.function ? ')' }} From 3d7c7cf39a91a7608bdd4ab8500e9dce2f13d016 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 19 Apr 2018 13:01:15 +0200 Subject: [PATCH 30/75] [Cache] Add missing `@internal` tag on ProxyTrait --- src/Symfony/Component/Cache/Traits/ProxyTrait.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Cache/Traits/ProxyTrait.php b/src/Symfony/Component/Cache/Traits/ProxyTrait.php index 06dba7e59bf7e..d9e085b9ea887 100644 --- a/src/Symfony/Component/Cache/Traits/ProxyTrait.php +++ b/src/Symfony/Component/Cache/Traits/ProxyTrait.php @@ -16,6 +16,8 @@ /** * @author Nicolas Grekas + * + * @internal */ trait ProxyTrait { From f981f7aae849418d7e9af9f4d393c934b6da0ba4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 20 Apr 2018 08:14:58 +0200 Subject: [PATCH 31/75] fixed Twig URL --- src/Symfony/Bridge/Twig/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/README.md b/src/Symfony/Bridge/Twig/README.md index eb084147c37f8..602f5a54c3dd6 100644 --- a/src/Symfony/Bridge/Twig/README.md +++ b/src/Symfony/Bridge/Twig/README.md @@ -1,7 +1,7 @@ Twig Bridge =========== -Provides integration for [Twig](http://twig.sensiolabs.org/) with various +Provides integration for [Twig](https://twig.symfony.com/) with various Symfony components. Resources From f180bfe2a2e4a63205df23587a11e78d37f95148 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 20 Apr 2018 08:20:06 +0200 Subject: [PATCH 32/75] fixed deprecations in tests --- .../Extension/Core/Type/ChoiceTypeTest.php | 34 ++++--------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index fc9f2f8d95a69..9cbe941581418 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1887,9 +1887,7 @@ public function testInheritTranslationDomainFromParent() ->createNamedBuilder('parent', FormTypeTest::TESTED_TYPE, null, array( 'translation_domain' => 'domain', )) - ->add('child', static::TESTED_TYPE, array( - 'choices_as_values' => true, - )) + ->add('child', static::TESTED_TYPE) ->getForm() ->createView(); @@ -1899,7 +1897,6 @@ public function testInheritTranslationDomainFromParent() public function testPassTranslationDomainToView() { $view = $this->factory->create(static::TESTED_TYPE, null, array( - 'choices_as_values' => true, 'translation_domain' => 'domain', )) ->createView(); @@ -1914,7 +1911,6 @@ public function testPreferOwnTranslationDomain() 'translation_domain' => 'parent_domain', )) ->add('child', static::TESTED_TYPE, array( - 'choices_as_values' => true, 'translation_domain' => 'domain', )) ->getForm() @@ -1926,9 +1922,7 @@ public function testPreferOwnTranslationDomain() public function testDefaultTranslationDomain() { $view = $this->factory->createNamedBuilder('parent', FormTypeTest::TESTED_TYPE) - ->add('child', static::TESTED_TYPE, array( - 'choices_as_values' => true, - )) + ->add('child', static::TESTED_TYPE) ->getForm() ->createView(); @@ -1937,9 +1931,7 @@ public function testDefaultTranslationDomain() public function testPassMultipartFalseToView() { - $view = $this->factory->create(static::TESTED_TYPE, null, array( - 'choices_as_values' => true, - )) + $view = $this->factory->create(static::TESTED_TYPE, null) ->createView(); $this->assertFalse($view->vars['multipart']); @@ -1949,7 +1941,6 @@ public function testPassLabelToView() { $view = $this->factory->createNamed('__test___field', static::TESTED_TYPE, null, array( 'label' => 'My label', - 'choices_as_values' => true, )) ->createView(); @@ -1960,9 +1951,7 @@ public function testPassIdAndNameToViewWithGrandParent() { $builder = $this->factory->createNamedBuilder('parent', FormTypeTest::TESTED_TYPE) ->add('child', FormTypeTest::TESTED_TYPE); - $builder->get('child')->add('grand_child', static::TESTED_TYPE, array( - 'choices_as_values' => true, - )); + $builder->get('child')->add('grand_child', static::TESTED_TYPE); $view = $builder->getForm()->createView(); $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); @@ -1973,9 +1962,7 @@ public function testPassIdAndNameToViewWithGrandParent() public function testPassIdAndNameToViewWithParent() { $view = $this->factory->createNamedBuilder('parent', FormTypeTest::TESTED_TYPE) - ->add('child', static::TESTED_TYPE, array( - 'choices_as_values' => true, - )) + ->add('child', static::TESTED_TYPE) ->getForm() ->createView(); @@ -1988,7 +1975,6 @@ public function testPassDisabledAsOption() { $form = $this->factory->create(static::TESTED_TYPE, null, array( 'disabled' => true, - 'choices_as_values' => true, )); $this->assertTrue($form->isDisabled()); @@ -1996,9 +1982,7 @@ public function testPassDisabledAsOption() public function testPassIdAndNameToView() { - $view = $this->factory->createNamed('name', static::TESTED_TYPE, null, array( - 'choices_as_values' => true, - )) + $view = $this->factory->createNamed('name', static::TESTED_TYPE, null) ->createView(); $this->assertEquals('name', $view->vars['id']); @@ -2008,9 +1992,7 @@ public function testPassIdAndNameToView() public function testStripLeadingUnderscoresAndDigitsFromId() { - $view = $this->factory->createNamed('_09name', static::TESTED_TYPE, null, array( - 'choices_as_values' => true, - )) + $view = $this->factory->createNamed('_09name', static::TESTED_TYPE, null) ->createView(); $this->assertEquals('name', $view->vars['id']); @@ -2029,7 +2011,6 @@ public function testTrimIsDisabled($multiple, $expanded) 'choices' => array( 'a' => '1', ), - 'choices_as_values' => true, )); $submittedData = ' 1'; @@ -2054,7 +2035,6 @@ public function testSubmitValueWithWhiteSpace($multiple, $expanded) 'choices' => array( 'a' => $valueWhitWhiteSpace, ), - 'choices_as_values' => true, )); $form->submit($multiple ? (array) $valueWhitWhiteSpace : $valueWhitWhiteSpace); From d05f0a0e038f44da0448467a6d024223fb33b89b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 20 Apr 2018 08:21:07 +0200 Subject: [PATCH 33/75] fixed Silex project's URL --- .../Resources/views/Collector/config.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6b84aaf65663a..76061d39a7a9c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig @@ -99,7 +99,7 @@ Resources {% if 'Silex' == collector.applicationname %} - + Read Silex Docs {% else %} From 52b4bfc042b344c6ff141c8071e515ca447acb7e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 19 Apr 2018 16:46:47 +0200 Subject: [PATCH 34/75] [Cache] Inline some hot function calls --- .../Cache/Adapter/AbstractAdapter.php | 2 +- .../Component/Cache/Adapter/ChainAdapter.php | 39 ++++++++++++------- .../Cache/Adapter/PhpArrayAdapter.php | 14 +++---- .../Cache/Adapter/TagAwareAdapter.php | 6 +-- src/Symfony/Component/Cache/CacheItem.php | 12 +++--- .../Component/Cache/Simple/AbstractCache.php | 12 +++--- .../Component/Cache/Simple/ArrayCache.php | 10 ++--- .../Component/Cache/Simple/ChainCache.php | 4 +- .../Component/Cache/Simple/PhpArrayCache.php | 24 ++++++------ .../Component/Cache/Simple/Psr6Cache.php | 10 ++--- .../Component/Cache/Simple/TraceableCache.php | 6 +-- .../Component/Cache/Traits/AbstractTrait.php | 2 +- .../Component/Cache/Traits/PhpArrayTrait.php | 10 ++--- .../Component/Cache/Traits/PhpFilesTrait.php | 10 ++--- .../Component/Cache/Traits/RedisTrait.php | 2 +- 15 files changed, 86 insertions(+), 77 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 727fc84c98473..5861cd3cd2383 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -237,7 +237,7 @@ public function commit() if (true === $e || array() === $e) { continue; } - if (is_array($e) || 1 === count($values)) { + if (\is_array($e) || 1 === \count($values)) { foreach (is_array($e) ? $e : array_keys($values) as $id) { $ok = false; $v = $values[$id]; diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index 6bdf6b2d54f14..9334ce3d3bed4 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -30,13 +30,13 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn { private $adapters = array(); private $adapterCount; - private $saveUp; + private $syncItem; /** - * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items - * @param int $maxLifetime The max lifetime of items propagated from lower adapters to upper ones + * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items + * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones */ - public function __construct(array $adapters, $maxLifetime = 0) + public function __construct(array $adapters, $defaultLifetime = 0) { if (!$adapters) { throw new InvalidArgumentException('At least one adapter must be specified.'); @@ -55,16 +55,20 @@ public function __construct(array $adapters, $maxLifetime = 0) } $this->adapterCount = count($this->adapters); - $this->saveUp = \Closure::bind( - function ($adapter, $item) use ($maxLifetime) { - $origDefaultLifetime = $item->defaultLifetime; + $this->syncItem = \Closure::bind( + function ($sourceItem, $item) use ($defaultLifetime) { + $item->value = $sourceItem->value; + $item->expiry = $sourceItem->expiry; + $item->isHit = $sourceItem->isHit; - if (0 < $maxLifetime && ($origDefaultLifetime <= 0 || $maxLifetime < $origDefaultLifetime)) { - $item->defaultLifetime = $maxLifetime; + if (0 < $sourceItem->defaultLifetime && $sourceItem->defaultLifetime < $defaultLifetime) { + $defaultLifetime = $sourceItem->defaultLifetime; + } + if (0 < $defaultLifetime && ($item->defaultLifetime <= 0 || $defaultLifetime < $item->defaultLifetime)) { + $item->defaultLifetime = $defaultLifetime; } - $adapter->save($item); - $item->defaultLifetime = $origDefaultLifetime; + return $item; }, null, CacheItem::class @@ -76,18 +80,21 @@ function ($adapter, $item) use ($maxLifetime) { */ public function getItem($key) { - $saveUp = $this->saveUp; + $syncItem = $this->syncItem; + $misses = array(); foreach ($this->adapters as $i => $adapter) { $item = $adapter->getItem($key); if ($item->isHit()) { while (0 <= --$i) { - $saveUp($this->adapters[$i], $item); + $this->adapters[$i]->save($syncItem($item, $misses[$i])); } return $item; } + + $misses[$i] = $item; } return $item; @@ -104,6 +111,7 @@ public function getItems(array $keys = array()) private function generateItems($items, $adapterIndex) { $missing = array(); + $misses = array(); $nextAdapterIndex = $adapterIndex + 1; $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null; @@ -112,17 +120,18 @@ private function generateItems($items, $adapterIndex) yield $k => $item; } else { $missing[] = $k; + $misses[$k] = $item; } } if ($missing) { - $saveUp = $this->saveUp; + $syncItem = $this->syncItem; $adapter = $this->adapters[$adapterIndex]; $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); foreach ($items as $k => $item) { if ($item->isHit()) { - $saveUp($adapter, $item); + $adapter->save($syncItem($item, $misses[$k])); } yield $k => $item; diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index d3b9d77d45bb1..e84b0ba0c41d2 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -84,7 +84,7 @@ public static function create($file, CacheItemPoolInterface $fallbackPool) */ public function getItem($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -99,7 +99,7 @@ public function getItem($key) if ('N;' === $value) { $value = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { $e = null; $value = unserialize($value); @@ -123,7 +123,7 @@ public function getItem($key) public function getItems(array $keys = array()) { foreach ($keys as $key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } } @@ -139,7 +139,7 @@ public function getItems(array $keys = array()) */ public function hasItem($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -154,7 +154,7 @@ public function hasItem($key) */ public function deleteItem($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -173,7 +173,7 @@ public function deleteItems(array $keys) $fallbackKeys = array(); foreach ($keys as $key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } @@ -240,7 +240,7 @@ private function generateItems(array $keys) if ('N;' === $value) { yield $key => $f($key, null, true); - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { yield $key => $f($key, unserialize($value), true); } catch (\Error $e) { diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 72bbc143cedff..a71b903d734f6 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -107,7 +107,7 @@ function (AdapterInterface $tagsAdapter, array $tags) { public function invalidateTags(array $tags) { foreach ($tags as $k => $tag) { - if ('' !== $tag && is_string($tag)) { + if ('' !== $tag && \is_string($tag)) { $tags[$k] = $tag.static::TAGS_PREFIX; } } @@ -161,7 +161,7 @@ public function getItems(array $keys = array()) $tagKeys = array(); foreach ($keys as $key) { - if ('' !== $key && is_string($key)) { + if ('' !== $key && \is_string($key)) { $key = static::TAGS_PREFIX.$key; $tagKeys[$key] = $key; } @@ -202,7 +202,7 @@ public function deleteItem($key) public function deleteItems(array $keys) { foreach ($keys as $key) { - if ('' !== $key && is_string($key)) { + if ('' !== $key && \is_string($key)) { $keys[] = static::TAGS_PREFIX.$key; } } diff --git a/src/Symfony/Component/Cache/CacheItem.php b/src/Symfony/Component/Cache/CacheItem.php index 93ffea495e88f..cecaa126d9129 100644 --- a/src/Symfony/Component/Cache/CacheItem.php +++ b/src/Symfony/Component/Cache/CacheItem.php @@ -89,7 +89,7 @@ public function expiresAfter($time) $this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null; } elseif ($time instanceof \DateInterval) { $this->expiry = (int) \DateTime::createFromFormat('U', time())->add($time)->format('U'); - } elseif (is_int($time)) { + } elseif (\is_int($time)) { $this->expiry = $time + time(); } else { throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', is_object($time) ? get_class($time) : gettype($time))); @@ -109,17 +109,17 @@ public function expiresAfter($time) */ public function tag($tags) { - if (!is_array($tags)) { + if (!\is_array($tags)) { $tags = array($tags); } foreach ($tags as $tag) { - if (!is_string($tag)) { + if (!\is_string($tag)) { throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', is_object($tag) ? get_class($tag) : gettype($tag))); } if (isset($this->tags[$tag])) { continue; } - if (!isset($tag[0])) { + if ('' === $tag) { throw new InvalidArgumentException('Cache tag length must be greater than zero'); } if (false !== strpbrk($tag, '{}()/\@:')) { @@ -152,10 +152,10 @@ public function getPreviousTags() */ public static function validateKey($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given', is_object($key) ? get_class($key) : gettype($key))); } - if (!isset($key[0])) { + if ('' === $key) { throw new InvalidArgumentException('Cache key length must be greater than zero'); } if (false !== strpbrk($key, '{}()/\@:')) { diff --git a/src/Symfony/Component/Cache/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php index e666effaf93f9..e3fc790479dc3 100644 --- a/src/Symfony/Component/Cache/Simple/AbstractCache.php +++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php @@ -79,7 +79,7 @@ public function getMultiple($keys, $default = null) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } $ids = array(); @@ -103,13 +103,13 @@ public function getMultiple($keys, $default = null) */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { + if (!\is_array($values) && !$values instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); } $valuesById = array(); foreach ($values as $key => $value) { - if (is_int($key)) { + if (\is_int($key)) { $key = (string) $key; } $valuesById[$this->getId($key)] = $value; @@ -126,7 +126,7 @@ public function setMultiple($values, $ttl = null) return true; } $keys = array(); - foreach (is_array($e) ? $e : array_keys($valuesById) as $id) { + foreach (\is_array($e) ? $e : array_keys($valuesById) as $id) { $keys[] = substr($id, strlen($this->namespace)); } CacheItem::log($this->logger, 'Failed to save values', array('keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null)); @@ -141,7 +141,7 @@ public function deleteMultiple($keys) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } @@ -156,7 +156,7 @@ private function normalizeTtl($ttl) if ($ttl instanceof \DateInterval) { $ttl = (int) \DateTime::createFromFormat('U', 0)->add($ttl)->format('U'); } - if (is_int($ttl)) { + if (\is_int($ttl)) { return 0 < $ttl ? $ttl : false; } diff --git a/src/Symfony/Component/Cache/Simple/ArrayCache.php b/src/Symfony/Component/Cache/Simple/ArrayCache.php index 8d027cd2a3722..8657573e35116 100644 --- a/src/Symfony/Component/Cache/Simple/ArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/ArrayCache.php @@ -57,7 +57,7 @@ public function getMultiple($keys, $default = null) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } foreach ($keys as $key) { @@ -72,7 +72,7 @@ public function getMultiple($keys, $default = null) */ public function deleteMultiple($keys) { - if (!is_array($keys) && !$keys instanceof \Traversable) { + if (!\is_array($keys) && !$keys instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } foreach ($keys as $key) { @@ -97,13 +97,13 @@ public function set($key, $value, $ttl = null) */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { + if (!\is_array($values) && !$values instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); } $valuesArray = array(); foreach ($values as $key => $value) { - is_int($key) || CacheItem::validateKey($key); + \is_int($key) || CacheItem::validateKey($key); $valuesArray[$key] = $value; } if (false === $ttl = $this->normalizeTtl($ttl)) { @@ -139,7 +139,7 @@ private function normalizeTtl($ttl) if ($ttl instanceof \DateInterval) { $ttl = (int) \DateTime::createFromFormat('U', 0)->add($ttl)->format('U'); } - if (is_int($ttl)) { + if (\is_int($ttl)) { return 0 < $ttl ? $ttl : false; } diff --git a/src/Symfony/Component/Cache/Simple/ChainCache.php b/src/Symfony/Component/Cache/Simple/ChainCache.php index 9d0c75870eb7e..dd825f268af93 100644 --- a/src/Symfony/Component/Cache/Simple/ChainCache.php +++ b/src/Symfony/Component/Cache/Simple/ChainCache.php @@ -58,7 +58,7 @@ public function __construct(array $caches, $defaultLifetime = 0) */ public function get($key, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; foreach ($this->caches as $i => $cache) { $value = $cache->get($key, $miss); @@ -80,7 +80,7 @@ public function get($key, $default = null) */ public function getMultiple($keys, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; return $this->generateItems($this->caches[0]->getMultiple($keys, $miss), 0, $miss, $default); } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 3db8a2ac1c044..35a82b65158b1 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -63,7 +63,7 @@ public static function create($file, CacheInterface $fallbackPool) */ public function get($key, $default = null) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -77,7 +77,7 @@ public function get($key, $default = null) if ('N;' === $value) { $value = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { $e = null; $value = unserialize($value); @@ -99,11 +99,11 @@ public function getMultiple($keys, $default = null) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } foreach ($keys as $key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } } @@ -119,7 +119,7 @@ public function getMultiple($keys, $default = null) */ public function has($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -134,7 +134,7 @@ public function has($key) */ public function delete($key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -149,7 +149,7 @@ public function delete($key) */ public function deleteMultiple($keys) { - if (!is_array($keys) && !$keys instanceof \Traversable) { + if (!\is_array($keys) && !$keys instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } @@ -157,7 +157,7 @@ public function deleteMultiple($keys) $fallbackKeys = array(); foreach ($keys as $key) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } @@ -183,7 +183,7 @@ public function deleteMultiple($keys) */ public function set($key, $value, $ttl = null) { - if (!is_string($key)) { + if (!\is_string($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } if (null === $this->values) { @@ -198,7 +198,7 @@ public function set($key, $value, $ttl = null) */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { + if (!\is_array($values) && !$values instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); } @@ -206,7 +206,7 @@ public function setMultiple($values, $ttl = null) $fallbackValues = array(); foreach ($values as $key => $value) { - if (!is_string($key) && !is_int($key)) { + if (!\is_string($key) && !\is_int($key)) { throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); } @@ -234,7 +234,7 @@ private function generateItems(array $keys, $default) if ('N;' === $value) { yield $key => null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { yield $key => unserialize($value); } catch (\Error $e) { diff --git a/src/Symfony/Component/Cache/Simple/Psr6Cache.php b/src/Symfony/Component/Cache/Simple/Psr6Cache.php index 81f14d4a7045c..4a71346d2ce52 100644 --- a/src/Symfony/Component/Cache/Simple/Psr6Cache.php +++ b/src/Symfony/Component/Cache/Simple/Psr6Cache.php @@ -38,7 +38,7 @@ public function __construct(CacheItemPoolInterface $pool) if ($pool instanceof AbstractAdapter) { $this->createCacheItem = \Closure::bind( function ($key, $value, $allowInt = false) { - if ($allowInt && is_int($key)) { + if ($allowInt && \is_int($key)) { $key = (string) $key; } else { CacheItem::validateKey($key); @@ -121,7 +121,7 @@ public function getMultiple($keys, $default = null) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } @@ -146,7 +146,7 @@ public function getMultiple($keys, $default = null) */ public function setMultiple($values, $ttl = null) { - $valuesIsArray = is_array($values); + $valuesIsArray = \is_array($values); if (!$valuesIsArray && !$values instanceof \Traversable) { throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); } @@ -166,7 +166,7 @@ public function setMultiple($values, $ttl = null) $items = $this->pool->getItems($items); } else { foreach ($values as $key => $value) { - if (is_int($key)) { + if (\is_int($key)) { $key = (string) $key; } $items[$key] = $this->pool->getItem($key)->set($value); @@ -199,7 +199,7 @@ public function deleteMultiple($keys) { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { + } elseif (!\is_array($keys)) { throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); } diff --git a/src/Symfony/Component/Cache/Simple/TraceableCache.php b/src/Symfony/Component/Cache/Simple/TraceableCache.php index 756403bf1430e..181934eff5012 100644 --- a/src/Symfony/Component/Cache/Simple/TraceableCache.php +++ b/src/Symfony/Component/Cache/Simple/TraceableCache.php @@ -37,7 +37,7 @@ public function __construct(CacheInterface $pool) */ public function get($key, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; $event = $this->start(__FUNCTION__); try { $value = $this->pool->get($key, $miss); @@ -109,7 +109,7 @@ public function setMultiple($values, $ttl = null) } }; $values = $values(); - } elseif (is_array($values)) { + } elseif (\is_array($values)) { $event->result['keys'] = array_keys($values); } @@ -125,7 +125,7 @@ public function setMultiple($values, $ttl = null) */ public function getMultiple($keys, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; $event = $this->start(__FUNCTION__); try { $result = $this->pool->getMultiple($keys, $miss); diff --git a/src/Symfony/Component/Cache/Traits/AbstractTrait.php b/src/Symfony/Component/Cache/Traits/AbstractTrait.php index d7af3b559e0ee..92999a2f3c34d 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractTrait.php @@ -241,7 +241,7 @@ private function getId($key) if (null === $this->maxIdLength) { return $this->namespace.$this->namespaceVersion.$key; } - if (strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { + if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -22); } diff --git a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php index ae634d6baa295..e90492b3a14d3 100644 --- a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php @@ -66,15 +66,15 @@ public function warmUp(array $values) EOF; foreach ($values as $key => $value) { - CacheItem::validateKey(is_int($key) ? (string) $key : $key); + CacheItem::validateKey(\is_int($key) ? (string) $key : $key); - if (null === $value || is_object($value)) { + if (null === $value || \is_object($value)) { try { $value = serialize($value); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, get_class($value)), 0, $e); } - } elseif (is_array($value)) { + } elseif (\is_array($value)) { try { $serialized = serialize($value); $unserialized = unserialize($serialized); @@ -85,12 +85,12 @@ public function warmUp(array $values) if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { $value = $serialized; } - } elseif (is_string($value)) { + } elseif (\is_string($value)) { // Serialize strings if they could be confused with serialized objects or arrays if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { $value = serialize($value); } - } elseif (!is_scalar($value)) { + } elseif (!\is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, gettype($value))); } diff --git a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php index c800e1a1798e5..32bbeb71237e2 100644 --- a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php @@ -96,7 +96,7 @@ protected function doFetch(array $ids) foreach ($values as $id => $value) { if ('N;' === $value) { $values[$id] = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { $values[$id] = parent::unserialize($value); } } @@ -122,21 +122,21 @@ protected function doSave(array $values, $lifetime) $allowCompile = 'cli' !== PHP_SAPI || ini_get('opcache.enable_cli'); foreach ($values as $key => $value) { - if (null === $value || is_object($value)) { + if (null === $value || \is_object($value)) { $value = serialize($value); - } elseif (is_array($value)) { + } elseif (\is_array($value)) { $serialized = serialize($value); $unserialized = parent::unserialize($serialized); // Store arrays serialized if they contain any objects or references if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { $value = $serialized; } - } elseif (is_string($value)) { + } elseif (\is_string($value)) { // Serialize strings if they could be confused with serialized objects or arrays if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { $value = serialize($value); } - } elseif (!is_scalar($value)) { + } elseif (!\is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, gettype($value))); } diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index ac8b5a5fccda2..b8e05d9e417c9 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -240,7 +240,7 @@ protected function doClear($namespace) $cursor = null; do { $keys = $host instanceof \Predis\Client ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000); - if (isset($keys[1]) && is_array($keys[1])) { + if (isset($keys[1]) && \is_array($keys[1])) { $cursor = $keys[0]; $keys = $keys[1]; } From 877e67883cd3c440bc16e124dd8da216f9c3babd Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Sun, 15 Apr 2018 22:26:30 +0200 Subject: [PATCH 35/75] [minor] SCA --- .../Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php | 5 ++--- .../Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php | 2 +- src/Symfony/Component/Console/Descriptor/JsonDescriptor.php | 2 +- .../Component/Console/Descriptor/MarkdownDescriptor.php | 2 +- src/Symfony/Component/Console/Descriptor/XmlDescriptor.php | 2 +- src/Symfony/Component/Console/Input/InputOption.php | 2 +- .../Mapping/Factory/LazyLoadingMetadataFactory.php | 6 +----- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php index d68fa7ce77674..e49bf22a35627 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php @@ -96,11 +96,10 @@ private function findTemplatesInFolder($dir) private function findTemplatesInBundle(BundleInterface $bundle) { $name = $bundle->getName(); - $templates = array_merge( + $templates = array_unique(array_merge( $this->findTemplatesInFolder($bundle->getPath().'/Resources/views'), $this->findTemplatesInFolder($this->rootDir.'/'.$name.'/views') - ); - $templates = array_unique($templates); + )); foreach ($templates as $i => $template) { $templates[$i] = $template->set('bundle', $name); diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 7390144dc8dd9..7a1eb9700aad4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -160,7 +160,7 @@ public function formatFile($file, $line, $text = null) $file = trim($file); $fileStr = $file; if (0 === strpos($fileStr, $this->rootDir)) { - $fileStr = str_replace($this->rootDir, '', str_replace('\\', '/', $fileStr)); + $fileStr = str_replace(array('\\', $this->rootDir), array('/', ''), $fileStr); $fileStr = htmlspecialchars($fileStr, $flags, $this->charset); $fileStr = sprintf('kernel.root_dir/%s', htmlspecialchars($this->rootDir, $flags, $this->charset), $fileStr); } diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php index 51c4d2ef0e619..0a22274b3508d 100644 --- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php @@ -109,7 +109,7 @@ private function getInputOptionData(InputOption $option) { return array( 'name' => '--'.$option->getName(), - 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), diff --git a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php index c2d6243e280cc..76399cae7d40a 100644 --- a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php @@ -50,7 +50,7 @@ protected function describeInputOption(InputOption $option, array $options = arr $this->write( '**'.$option->getName().':**'."\n\n" .'* Name: `--'.$option->getName().'`'."\n" - .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" + .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '')."\n" .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" diff --git a/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php index 177a054cc18d1..c42fa429dcf6e 100644 --- a/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php @@ -223,7 +223,7 @@ private function getInputOptionDocument(InputOption $option) $pos = strpos($option->getShortcut(), '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); - $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); } diff --git a/src/Symfony/Component/Console/Input/InputOption.php b/src/Symfony/Component/Console/Input/InputOption.php index e6ca45aa42c56..c2b57c7c27a3e 100644 --- a/src/Symfony/Component/Console/Input/InputOption.php +++ b/src/Symfony/Component/Console/Input/InputOption.php @@ -192,7 +192,7 @@ public function getDescription() * * @return bool */ - public function equals(InputOption $option) + public function equals(self $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index e088caa897a71..cb253f844ba78 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -162,10 +162,6 @@ public function hasMetadataFor($value) $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); - if (class_exists($class) || interface_exists($class)) { - return true; - } - - return false; + return class_exists($class) || interface_exists($class, false); } } From 47153979792dc10fd6c1c25a7e89ca05ec7b9d80 Mon Sep 17 00:00:00 2001 From: Alexis MARQUIS Date: Thu, 19 Apr 2018 15:21:21 +0200 Subject: [PATCH 36/75] Fix PercentType error rendering. --- .../Twig/Resources/views/Form/bootstrap_4_layout.html.twig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index 44141f1b383b0..43c031b933366 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -106,8 +106,7 @@ {%- endblock dateinterval_widget %} {% block percent_widget -%} -
- {% set valid = true %} +
{{- block('form_widget_simple') -}}
% From 583759f0b6006e1e910f34227ad3b4914695463c Mon Sep 17 00:00:00 2001 From: insekticid Date: Sat, 31 Mar 2018 01:03:42 +0200 Subject: [PATCH 37/75] PropertyInfo\DoctrineExtractor - There is bug when indexBy is meta key --- .../Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php | 10 ++++++++++ .../Tests/PropertyInfo/DoctrineExtractorTest.php | 9 +++++++++ .../Tests/PropertyInfo/Fixtures/DoctrineDummy.php | 6 ++++++ .../Tests/PropertyInfo/Fixtures/DoctrineRelation.php | 7 +++++++ 4 files changed, 32 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index fee254da65abd..4bf684bf3aec6 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -95,9 +95,19 @@ public function getTypes($class, $property, array $context = array()) if (isset($associationMapping['indexBy'])) { $indexProperty = $associationMapping['indexBy']; + /** @var ClassMetadataInfo $subMetadata */ $subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); $typeOfField = $subMetadata->getTypeOfField($indexProperty); + if (null === $typeOfField) { + $associationMapping = $subMetadata->getAssociationMapping($indexProperty); + + /** @var ClassMetadataInfo $subMetadata */ + $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($indexProperty); + $subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); + } + $collectionKeyType = $this->getPhpType($typeOfField); } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 139601710ede3..8bc25718ecd6f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -59,6 +59,7 @@ public function testGetProperties() 'foo', 'bar', 'indexedBar', + 'indexedFoo', ), $this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy') ); @@ -136,6 +137,14 @@ public function typesProvider() new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') ))), + array('indexedFoo', array(new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + 'Doctrine\Common\Collections\Collection', + true, + new Type(Type::BUILTIN_TYPE_STRING), + new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') + ))), array('simpleArray', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))), array('customFoo', null), array('notMapped', null), diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 580e75803db8f..60fce8954cec3 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -14,6 +14,7 @@ use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\OneToMany; use Doctrine\ORM\Mapping\ManyToMany; use Doctrine\ORM\Mapping\ManyToOne; @@ -45,6 +46,11 @@ class DoctrineDummy */ protected $indexedBar; + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="foo", indexBy="foo") + */ + protected $indexedFoo; + /** * @Column(type="guid") */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php index 6e94e028faa7d..85660d3d6b66c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php @@ -14,6 +14,7 @@ use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\ManyToOne; /** * @Entity @@ -32,4 +33,10 @@ class DoctrineRelation * @Column(type="guid") */ protected $rguid; + + /** + * @Column(type="guid") + * @ManyToOne(targetEntity="DoctrineDummy", inversedBy="indexedFoo") + */ + protected $foo; } From 939a42f623062232b8c59ff2fcfe72f657fc0d80 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 20 Apr 2018 11:55:01 +0200 Subject: [PATCH 38/75] Fix tests --- .../Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json | 4 ++-- .../Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json index b0c083b5b71dc..6aba3b60ecb12 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json @@ -22,7 +22,8 @@ "compound", "data_class", "empty_data", - "error_bubbling" + "error_bubbling", + "trim" ] }, "parent": { @@ -44,7 +45,6 @@ "property_path", "required", "translation_domain", - "trim", "upload_max_size_message" ] }, diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt index 2b34ad960d672..874dede77f7f5 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt @@ -11,7 +11,7 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice") choice_name data_class attr csrf_message choice_translation_domain empty_data auto_initialize csrf_protection choice_value error_bubbling block_name csrf_token_id - choices by_reference csrf_token_manager + choices trim by_reference csrf_token_manager choices_as_values data expanded disabled group_by inherit_data @@ -24,7 +24,6 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice") property_path required translation_domain - trim upload_max_size_message --------------------------- -------------------- ------------------------- ----------------------- From 73fec237daf1ac550a76a41fb43bf7628d236299 Mon Sep 17 00:00:00 2001 From: cvilleger Date: Thu, 5 Apr 2018 14:19:22 +0200 Subject: [PATCH 39/75] [HttpFoundation] Add functional tests for Response::sendHeaders() --- .../Component/HttpFoundation/Cookie.php | 8 ++- .../HttpFoundation/Tests/CookieTest.php | 8 +-- .../Fixtures/response-functional/common.inc | 39 +++++++++++++ .../cookie_max_age.expected | 11 ++++ .../response-functional/cookie_max_age.php | 10 ++++ .../cookie_raw_urlencode.expected | 10 ++++ .../cookie_raw_urlencode.php | 12 ++++ .../cookie_samesite_lax.expected | 9 +++ .../cookie_samesite_lax.php | 8 +++ .../cookie_samesite_strict.expected | 9 +++ .../cookie_samesite_strict.php | 8 +++ .../cookie_urlencode.expected | 10 ++++ .../response-functional/cookie_urlencode.php | 12 ++++ .../invalid_cookie_name.expected | 6 ++ .../invalid_cookie_name.php | 11 ++++ .../Tests/ResponseFunctionalTest.php | 58 +++++++++++++++++++ .../Tests/ResponseHeaderBagTest.php | 4 +- .../Component/HttpKernel/Tests/ClientTest.php | 17 ++---- 18 files changed, 230 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/common.inc create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/ResponseFunctionalTest.php diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 4519a6adaeda5..d202dc6c1efb5 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -145,12 +145,12 @@ public function __toString() $str = ($this->isRaw() ? $this->getName() : urlencode($this->getName())).'='; if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001'; + $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; } else { $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; max-age='.$this->getMaxAge(); + $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); } } @@ -224,7 +224,9 @@ public function getExpiresTime() */ public function getMaxAge() { - return 0 !== $this->expire ? $this->expire - time() : 0; + $maxAge = $this->expire - time(); + + return 0 >= $maxAge ? 0 : $maxAge; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index 070b7dd4290e6..a47b71e1d4257 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -162,13 +162,13 @@ public function testCookieIsCleared() public function testToString() { $cookie = new Cookie('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); - $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); + $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); - $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); + $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); - $this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; max-age='.($expire - time()).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); + $this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; Max-Age=0; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); $cookie = new Cookie('foo', 'bar', 0, '/', ''); $this->assertEquals('foo=bar; path=/; httponly', (string) $cookie); @@ -194,7 +194,7 @@ public function testGetMaxAge() $this->assertEquals($expire - time(), $cookie->getMaxAge()); $cookie = new Cookie('foo', 'bar', $expire = time() - 100); - $this->assertEquals($expire - time(), $cookie->getMaxAge()); + $this->assertEquals(0, $cookie->getMaxAge()); } public function testFromString() diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/common.inc b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/common.inc new file mode 100644 index 0000000000000..ba101d357852d --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/common.inc @@ -0,0 +1,39 @@ +headers->set('Date', 'Sat, 12 Nov 1955 20:04:00 GMT'); + +return $r; diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.expected new file mode 100644 index 0000000000000..bdb9d023f8f3d --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.expected @@ -0,0 +1,11 @@ + +Warning: Expiry date cannot have a year greater than 9999 in %scookie_max_age.php on line 10 + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: foo=bar; expires=Sat, 01-Jan-10000 02:46:40 GMT; Max-Age=%d; path=/ +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.php new file mode 100644 index 0000000000000..8775a5cceeb88 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_max_age.php @@ -0,0 +1,10 @@ +headers->setCookie(new Cookie('foo', 'bar', 253402310800, '', null, false, false)); +$r->sendHeaders(); + +setcookie('foo2', 'bar', 253402310800, '/'); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected new file mode 100644 index 0000000000000..0c097972e78e2 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected @@ -0,0 +1,10 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: ?*():@&+$/%#[]=?*():@&+$/%#[]; path=/ + [4] => Set-Cookie: ?*():@&+$/%#[]=?*():@&+$/%#[]; path=/ +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php new file mode 100644 index 0000000000000..2ca5b59f1a3e5 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php @@ -0,0 +1,12 @@ +headers->setCookie(new Cookie($str, $str, 0, '/', null, false, false, true)); +$r->sendHeaders(); + +setrawcookie($str, $str, 0, '/', null, false, false); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected new file mode 100644 index 0000000000000..cbde2cbfe13f3 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected @@ -0,0 +1,9 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: CookieSamesiteLaxTest=LaxValue; path=/; httponly; samesite=lax +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php new file mode 100644 index 0000000000000..9a476f1d23fab --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php @@ -0,0 +1,8 @@ +headers->setCookie(new Cookie('CookieSamesiteLaxTest', 'LaxValue', 0, '/', null, false, true, false, Cookie::SAMESITE_LAX)); +$r->sendHeaders(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected new file mode 100644 index 0000000000000..adc491fd2bc51 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected @@ -0,0 +1,9 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: CookieSamesiteStrictTest=StrictValue; path=/; httponly; samesite=strict +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php new file mode 100644 index 0000000000000..3bcb41f8f059e --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php @@ -0,0 +1,8 @@ +headers->setCookie(new Cookie('CookieSamesiteStrictTest', 'StrictValue', 0, '/', null, false, true, false, Cookie::SAMESITE_STRICT)); +$r->sendHeaders(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.expected new file mode 100644 index 0000000000000..4e9c4c075f5ed --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.expected @@ -0,0 +1,10 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: %3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/ + [4] => Set-Cookie: ?*():@&+$/%#[]=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/ +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.php new file mode 100644 index 0000000000000..05b9af30d58f2 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/cookie_urlencode.php @@ -0,0 +1,12 @@ +headers->setCookie(new Cookie($str, $str, 0, '', null, false, false)); +$r->sendHeaders(); + +setcookie($str, $str, 0, '/'); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected new file mode 100644 index 0000000000000..2b560f0bd5689 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected @@ -0,0 +1,6 @@ +The cookie name "Hello + world" contains invalid characters. +Array +( + [0] => Content-Type: text/plain; charset=utf-8 +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.php b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.php new file mode 100644 index 0000000000000..3fe1571845628 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Fixtures/response-functional/invalid_cookie_name.php @@ -0,0 +1,11 @@ +headers->setCookie(new Cookie('Hello + world', 'hodor')); +} catch (\InvalidArgumentException $e) { + echo $e->getMessage(); +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseFunctionalTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseFunctionalTest.php new file mode 100644 index 0000000000000..22f25e978e5a2 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseFunctionalTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use PHPUnit\Framework\TestCase; + +/** + * @requires PHP 7.0 + */ +class ResponseFunctionalTest extends TestCase +{ + private static $server; + + public static function setUpBeforeClass() + { + $spec = array( + 1 => array('file', '/dev/null', 'w'), + 2 => array('file', '/dev/null', 'w'), + ); + if (!self::$server = @proc_open('exec php -S localhost:8054', $spec, $pipes, __DIR__.'/Fixtures/response-functional')) { + self::markTestSkipped('PHP server unable to start.'); + } + sleep(1); + } + + public static function tearDownAfterClass() + { + if (self::$server) { + proc_terminate(self::$server); + proc_close(self::$server); + } + } + + /** + * @dataProvider provideCookie + */ + public function testCookie($fixture) + { + $result = file_get_contents(sprintf('http://localhost:8054/%s.php', $fixture)); + $this->assertStringMatchesFormatFile(__DIR__.sprintf('/Fixtures/response-functional/%s.expected', $fixture), $result); + } + + public function provideCookie() + { + foreach (glob(__DIR__.'/Fixtures/response-functional/*.php') as $file) { + yield array(pathinfo($file, PATHINFO_FILENAME)); + } + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php index ce8553590dcdb..7b5e720afdb61 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -116,7 +116,7 @@ public function testToStringIncludesCookieHeaders() $bag->clearCookie('foo'); - $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; httponly', $bag); + $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; httponly', $bag); } public function testClearCookieSecureNotHttpOnly() @@ -125,7 +125,7 @@ public function testClearCookieSecureNotHttpOnly() $bag->clearCookie('foo', '/', null, true, false); - $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; secure', $bag); + $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure', $bag); } public function testReplace() diff --git a/src/Symfony/Component/HttpKernel/Tests/ClientTest.php b/src/Symfony/Component/HttpKernel/Tests/ClientTest.php index 051d5d47c0265..b774d8ec7ae1c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ClientTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ClientTest.php @@ -60,22 +60,17 @@ public function testFilterResponseConvertsCookies() $m = $r->getMethod('filterResponse'); $m->setAccessible(true); - $expected = array( - 'foo=bar; expires=Sun, 15-Feb-2009 20:00:00 GMT; max-age='.(strtotime('Sun, 15-Feb-2009 20:00:00 GMT') - time()).'; path=/foo; domain=http://example.com; secure; httponly', - 'foo1=bar1; expires=Sun, 15-Feb-2009 20:00:00 GMT; max-age='.(strtotime('Sun, 15-Feb-2009 20:00:00 GMT') - time()).'; path=/foo; domain=http://example.com; secure; httponly', - ); - $response = new Response(); - $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie($cookie1 = new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); $domResponse = $m->invoke($client, $response); - $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); + $this->assertSame((string) $cookie1, $domResponse->getHeader('Set-Cookie')); $response = new Response(); - $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); - $response->headers->setCookie(new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie($cookie1 = new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie($cookie2 = new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); $domResponse = $m->invoke($client, $response); - $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); - $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false)); + $this->assertSame((string) $cookie1, $domResponse->getHeader('Set-Cookie')); + $this->assertSame(array((string) $cookie1, (string) $cookie2), $domResponse->getHeader('Set-Cookie', false)); } public function testFilterResponseSupportsStreamedResponses() From b2ac6b6fbfdcd6894538786b44bccd37afa7eed2 Mon Sep 17 00:00:00 2001 From: Philipp Cordes Date: Sat, 21 Apr 2018 15:09:06 +0200 Subject: [PATCH 40/75] [VarDumper] Fix dumping of SplObjectStorage --- .../Component/VarDumper/Caster/SplCaster.php | 5 +++-- .../VarDumper/Tests/Caster/SplCasterTest.php | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index 835837266128e..f3fcf9748fb18 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -86,10 +86,11 @@ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $s $storage = array(); unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - foreach (clone $c as $obj) { + $clone = clone $c; + foreach ($clone as $obj) { $storage[spl_object_hash($obj)] = array( 'object' => $obj, - 'info' => $c->getInfo(), + 'info' => $clone->getInfo(), ); } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php index 96e0307385fb6..ece69424943a6 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php @@ -40,4 +40,23 @@ public function provideCastSplDoublyLinkedList() array(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'), ); } + + public function testCastObjectStorageIsntModified() + { + $var = new \SplObjectStorage(); + $var->attach(new \stdClass()); + $var->rewind(); + $current = $var->current(); + + $this->assertDumpMatchesFormat('%A', $var); + $this->assertSame($current, $var->current()); + } + + public function testCastObjectStorageDumpsInfo() + { + $var = new \SplObjectStorage(); + $var->attach(new \stdClass(), new \DateTime()); + + $this->assertDumpMatchesFormat('%ADateTime%A', $var); + } } From b0c92254a0ac4ca214f63c8f21080e50228000d3 Mon Sep 17 00:00:00 2001 From: johnstevenson Date: Thu, 12 Apr 2018 21:07:25 +0100 Subject: [PATCH 41/75] Use new PHP7.2 functions in hasColorSupport --- .../PhpUnit/DeprecationErrorHandler.php | 31 +++++-- .../Component/Console/Output/StreamOutput.php | 33 +++---- .../Component/VarDumper/Dumper/CliDumper.php | 88 +++++++++++++++---- 3 files changed, 114 insertions(+), 38 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index b0f241c862496..2b5c734c54c03 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -178,17 +178,38 @@ public static function register($mode = false) } } + /** + * Returns true if STDOUT is defined and supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @return bool + */ private static function hasColorSupport() { - if ('\\' === DIRECTORY_SEPARATOR) { - return - defined('STDOUT') && function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) - || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD + if (!defined('STDOUT')) { + return false; + } + + if (DIRECTORY_SEPARATOR === '\\') { + return (function_exists('sapi_windows_vt100_support') + && sapi_windows_vt100_support(STDOUT)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } - return defined('STDOUT') && function_exists('posix_isatty') && @posix_isatty(STDOUT); + if (function_exists('stream_isatty')) { + return stream_isatty(STDOUT); + } + + if (function_exists('posix_isatty')) { + return posix_isatty(STDOUT); + } + + $stat = fstat(STDOUT); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } } diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index 182622a29a5c8..b0897b206f70c 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -81,31 +81,34 @@ protected function doWrite($message, $newline) * * Colorization is disabled if not supported by the stream: * - * - the stream is redirected (eg php file.php >log) - * - Windows without VT100 support, Ansicon, ConEmu, Mintty - * - non tty consoles + * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo + * terminals via named pipes, so we can only check the environment. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler * * @return bool true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { - if (function_exists('stream_isatty') && !@stream_isatty($this->stream)) { - return false; - } if (DIRECTORY_SEPARATOR === '\\') { - if (function_exists('sapi_windows_vt100_support')) { - $vt100Enabled = @sapi_windows_vt100_support($this->stream); - } else { - $vt100Enabled = '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD; - } - - return - $vt100Enabled + return (function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } - return function_exists('posix_isatty') && @posix_isatty($this->stream); + if (function_exists('stream_isatty')) { + return @stream_isatty($this->stream); + } + + if (function_exists('posix_isatty')) { + return @posix_isatty($this->stream); + } + + $stat = @fstat($this->stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } } diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 689ada77c2460..8f3f7c7e99015 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -58,7 +58,7 @@ public function __construct($output = null, $charset = null) { parent::__construct($output, $charset); - if ('\\' === DIRECTORY_SEPARATOR && 'ON' !== @getenv('ConEmuANSI') && 'xterm' !== @getenv('TERM')) { + if ('\\' === DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI $this->setStyles(array( 'default' => '31', @@ -420,7 +420,7 @@ protected function style($style, $value, $attr = array()) protected function supportsColors() { if ($this->outputStream !== static::$defaultOutput) { - return @(is_resource($this->outputStream) && function_exists('posix_isatty') && posix_isatty($this->outputStream)); + return $this->hasColorSupport($this->outputStream); } if (null !== static::$defaultColors) { return static::$defaultColors; @@ -448,23 +448,10 @@ protected function supportsColors() } } - if ('\\' === DIRECTORY_SEPARATOR) { - static::$defaultColors = @( - function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->outputStream) - || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - ); - } elseif (function_exists('posix_isatty')) { - $h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null); - $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; - static::$defaultColors = @posix_isatty($h); - } else { - static::$defaultColors = false; - } + $h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null); + $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; - return static::$defaultColors; + return static::$defaultColors = $this->hasColorSupport($h); } /** @@ -477,4 +464,69 @@ protected function dumpLine($depth, $endOfValue = false) } parent::dumpLine($depth); } + + /** + * Returns true if the stream supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @param mixed $stream A CLI output stream + * + * @return bool + */ + private function hasColorSupport($stream) + { + if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { + return false; + } + + if (DIRECTORY_SEPARATOR === '\\') { + return (function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + if (function_exists('stream_isatty')) { + return @stream_isatty($stream); + } + + if (function_exists('posix_isatty')) { + return @posix_isatty($stream); + } + + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + /** + * Returns true if the Windows terminal supports true color. + * + * Note that this does not check an output stream, but relies on environment + * variables from known implementations, or a PHP and Windows version that + * supports true color. + * + * @return bool + */ + private function isWindowsTrueColor() + { + $result = strval(getenv('ANSICON_VER')) >= '183' + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + + if (!$result && PHP_VERSION_ID >= 70200) { + $version = sprintf( + '%s.%s.%s', + PHP_WINDOWS_VERSION_MAJOR, + PHP_WINDOWS_VERSION_MINOR, + PHP_WINDOWS_VERSION_BUILD + ); + $result = $version >= '10.0.15063'; + } + + return $result; + } } From 923417122abcf5eb4b8d0df84cc0730bdf4123b9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 22 Apr 2018 07:56:10 +0200 Subject: [PATCH 42/75] fixed CS --- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 8f3f7c7e99015..bc80e9f65b9af 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -513,7 +513,7 @@ private function hasColorSupport($stream) */ private function isWindowsTrueColor() { - $result = strval(getenv('ANSICON_VER')) >= '183' + $result = 183 <= getenv('ANSICON_VER') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); From 6fbcc515664429c54c28c92dc46c9307a7bc552b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sat, 21 Apr 2018 00:19:27 +0200 Subject: [PATCH 43/75] Add type hints This makes classes inheriting from phpunit classes compatible with phpunit 7. Fixes #26931 --- .../Legacy/{Command.php => CommandForV5.php} | 2 +- .../Bridge/PhpUnit/Legacy/CommandForV6.php | 32 ++++++++++++ .../{TestRunner.php => TestRunnerForV5.php} | 2 +- .../Bridge/PhpUnit/Legacy/TestRunnerForV6.php | 49 +++++++++++++++++++ src/Symfony/Bridge/PhpUnit/TextUI/Command.php | 22 +++------ .../Bridge/PhpUnit/TextUI/TestRunner.php | 43 +++------------- 6 files changed, 95 insertions(+), 55 deletions(-) rename src/Symfony/Bridge/PhpUnit/Legacy/{Command.php => CommandForV5.php} (90%) create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/CommandForV6.php rename src/Symfony/Bridge/PhpUnit/Legacy/{TestRunner.php => TestRunnerForV5.php} (95%) create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/Command.php b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php similarity index 90% rename from src/Symfony/Bridge/PhpUnit/Legacy/Command.php rename to src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php index 0aec8ab67f33e..d727881a11d81 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/Command.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php @@ -16,7 +16,7 @@ * * @internal */ -class Command extends \PHPUnit_TextUI_Command +class CommandForV5 extends \PHPUnit_TextUI_Command { /** * {@inheritdoc} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV6.php b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV6.php new file mode 100644 index 0000000000000..fc717ef415cb3 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV6.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\Command as BaseCommand; +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\TextUI\TestRunner; + +/** + * {@inheritdoc} + * + * @internal + */ +class CommandForV6 extends BaseCommand +{ + /** + * {@inheritdoc} + */ + protected function createRunner(): BaseRunner + { + return new TestRunner($this->arguments['loader']); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV5.php similarity index 95% rename from src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php rename to src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV5.php index 8a57416bd241f..7897861cf52f7 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV5.php @@ -16,7 +16,7 @@ * * @internal */ -class TestRunner extends \PHPUnit_TextUI_TestRunner +class TestRunnerForV5 extends \PHPUnit_TextUI_TestRunner { /** * {@inheritdoc} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php new file mode 100644 index 0000000000000..d709b873874fd --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * {@inheritdoc} + * + * @internal + */ +class TestRunnerForV6 extends BaseRunner +{ + /** + * {@inheritdoc} + */ + protected function handleConfiguration(array &$arguments): void + { + $listener = new SymfonyTestsListener(); + + parent::handleConfiguration($arguments); + + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + $registeredLocally = false; + + foreach ($arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (!$registeredLocally) { + $arguments['listeners'][] = $listener; + } + } +} diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php index 869a8a8dbe85d..4a26fc7fad278 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php @@ -11,24 +11,14 @@ namespace Symfony\Bridge\PhpUnit\TextUI; -use PHPUnit\TextUI\Command as BaseCommand; - if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\Command', 'Symfony\Bridge\PhpUnit\TextUI\Command'); + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV5', 'Symfony\Bridge\PhpUnit\TextUI\Command'); } else { - /** - * {@inheritdoc} - * - * @internal - */ - class Command extends BaseCommand + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV6', 'Symfony\Bridge\PhpUnit\TextUI\Command'); +} + +if (false) { + class Command { - /** - * {@inheritdoc} - */ - protected function createRunner() - { - return new TestRunner($this->arguments['loader']); - } } } diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php index 4e1fdca4d54be..af1abd3866787 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php @@ -11,45 +11,14 @@ namespace Symfony\Bridge\PhpUnit\TextUI; -use PHPUnit\TextUI\TestRunner as BaseRunner; -use Symfony\Bridge\PhpUnit\SymfonyTestsListener; - if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunner', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV5', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); } else { - /** - * {@inheritdoc} - * - * @internal - */ - class TestRunner extends BaseRunner - { - /** - * {@inheritdoc} - */ - protected function handleConfiguration(array &$arguments) - { - $listener = new SymfonyTestsListener(); - - $result = parent::handleConfiguration($arguments); - - $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); - - $registeredLocally = false; - - foreach ($arguments['listeners'] as $registeredListener) { - if ($registeredListener instanceof SymfonyTestsListener) { - $registeredListener->globalListenerDisabled(); - $registeredLocally = true; - break; - } - } - - if (!$registeredLocally) { - $arguments['listeners'][] = $listener; - } + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV6', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); +} - return $result; - } +if (false) { + class TestRunner + { } } From 5e98478d94a4f4c48bef5fb5b7cdb37d6f54ec12 Mon Sep 17 00:00:00 2001 From: Javier Spagnoletti Date: Sun, 22 Apr 2018 20:12:04 -0300 Subject: [PATCH 44/75] [DoctrineBridge] Improve exception message at `IdReader::getIdValue()` --- src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php index ee8ec2ddaba71..1d881849267d7 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php @@ -95,10 +95,7 @@ public function getIdValue($object) } if (!$this->om->contains($object)) { - throw new RuntimeException( - 'Entities passed to the choice field must be managed. Maybe '. - 'persist them in the entity manager?' - ); + throw new RuntimeException(sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', get_class($object))); } $this->om->initializeObject($object); From c606d60c54ce0b03f3e736dee9b0e8f72f35d130 Mon Sep 17 00:00:00 2001 From: Ahmad Mayahi Date: Mon, 23 Apr 2018 10:51:32 +0200 Subject: [PATCH 45/75] [HttpFoundation] Add HTTP_EARLY_HINTS const --- src/Symfony/Component/HttpFoundation/Response.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index ad551a85b9a8a..13b85b15d4e81 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -21,6 +21,7 @@ class Response const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; // RFC2518 + const HTTP_EARLY_HINTS = 103; // RFC8297 const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; From 314e8813b3e730bf09c3e6ee7280d93046a47a37 Mon Sep 17 00:00:00 2001 From: Sergey Rabochiy Date: Tue, 24 Apr 2018 14:18:57 +0700 Subject: [PATCH 46/75] [DI] Add check of internal type to ContainerBuilder::getReflectionClass --- .../DependencyInjection/ContainerBuilder.php | 19 +++++++++++++++++++ .../Tests/ContainerBuilderTest.php | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 512abd1d271a0..7f79e2f4ffc55 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -124,6 +124,20 @@ class ContainerBuilder extends Container implements TaggedContainerInterface private $removedIds = array(); private $alreadyLoading = array(); + private static $internalTypes = array( + 'int' => true, + 'float' => true, + 'string' => true, + 'bool' => true, + 'resource' => true, + 'object' => true, + 'array' => true, + 'null' => true, + 'callable' => true, + 'iterable' => true, + 'mixed' => true, + ); + public function __construct(ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); @@ -341,6 +355,11 @@ public function getReflectionClass($class, $throw = true) if (!$class = $this->getParameterBag()->resolveValue($class)) { return; } + + if (isset(self::$internalTypes[$class])) { + return null; + } + $resource = null; try { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 197bfae844532..51038b6b1550f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -906,6 +906,23 @@ public function testGetReflectionClass() $this->assertSame('BarMissingClass', (string) end($resources)); } + public function testGetReflectionClassOnInternalTypes() + { + $container = new ContainerBuilder(); + + $this->assertNull($container->getReflectionClass('int')); + $this->assertNull($container->getReflectionClass('float')); + $this->assertNull($container->getReflectionClass('string')); + $this->assertNull($container->getReflectionClass('bool')); + $this->assertNull($container->getReflectionClass('resource')); + $this->assertNull($container->getReflectionClass('object')); + $this->assertNull($container->getReflectionClass('array')); + $this->assertNull($container->getReflectionClass('null')); + $this->assertNull($container->getReflectionClass('callable')); + $this->assertNull($container->getReflectionClass('iterable')); + $this->assertNull($container->getReflectionClass('mixed')); + } + public function testCompilesClassDefinitionsOfLazyServices() { $container = new ContainerBuilder(); From 384acf9f7f33c37f2a1dc475169256bd72b7711d Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 25 Apr 2018 13:23:26 +0200 Subject: [PATCH 47/75] [Security] Skip user checks if not implementing UserInterface --- .../Provider/SimpleAuthenticationProvider.php | 6 ++++++ .../Provider/SimpleAuthenticationProviderTest.php | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index a82fb7eea4279..b4bdbf40c097d 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -13,6 +13,7 @@ use Symfony\Component\Security\Core\User\UserChecker; use Symfony\Component\Security\Core\User\UserCheckerInterface; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; @@ -45,6 +46,11 @@ public function authenticate(TokenInterface $token) } $user = $authToken->getUser(); + + if (!$user instanceof UserInterface) { + return $authToken; + } + $this->userChecker->checkPreAuth($user); $this->userChecker->checkPostAuth($user); diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php index 1e7069c1fa0bb..35247abe99c49 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider; use Symfony\Component\Security\Core\Exception\LockedException; +use Symfony\Component\Security\Core\User\UserChecker; class SimpleAuthenticationProviderTest extends TestCase { @@ -72,6 +73,20 @@ public function testAuthenticateWhenPostChecksFails() $provider->authenticate($token); } + public function testAuthenticateSkipsUserChecksForNonUserInterfaceObjects() + { + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue('string-user')); + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $this->assertSame($token, $this->getProvider($authenticator, null, new UserChecker())->authenticate($token)); + } + protected function getProvider($simpleAuthenticator = null, $userProvider = null, $userChecker = null, $key = 'test') { if (null === $userChecker) { From 715373fea6ed721bfc3b92ad9056701c35c0e076 Mon Sep 17 00:00:00 2001 From: gpenverne Date: Fri, 6 Apr 2018 11:56:21 +0200 Subject: [PATCH 48/75] [Bridge/Doctrine] fix count() notice on PHP 7.2 --- .../Constraints/UniqueEntityValidatorTest.php | 28 +++++++++++++++++++ .../Constraints/UniqueEntityValidator.php | 12 ++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 61131e47045aa..510c0f227afcc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -517,4 +517,32 @@ public function testEntityManagerNullObject() $this->validator->validate($entity, $constraint); } + + public function testValidateUniquenessOnNullResult() + { + $repository = $this->createRepositoryMock(); + $repository + ->method('find') + ->will($this->returnValue(null)) + ; + + $this->em = $this->createEntityManagerMock($repository); + $this->registry = $this->createRegistryMock($this->em); + $this->validator = $this->createValidator(); + $this->validator->initialize($this->context); + + $constraint = new UniqueEntity(array( + 'message' => 'myMessage', + 'fields' => array('name'), + 'em' => self::EM_NAME, + )); + + $entity = new SingleIntIdEntity(1, null); + + $this->em->persist($entity); + $this->em->flush(); + + $this->validator->validate($entity, $constraint); + $this->assertNoViolation(); + } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 8c7876eae342d..3effc89ca09af 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -133,15 +133,23 @@ public function validate($entity, Constraint $constraint) */ if ($result instanceof \Iterator) { $result->rewind(); - } elseif (is_array($result)) { + if ($result instanceof \Countable && 1 < \count($result)) { + $result = array($result->current(), $result->current()); + } else { + $result = $result->current(); + $result = null === $result ? array() : array($result); + } + } elseif (\is_array($result)) { reset($result); + } else { + $result = null === $result ? array() : array($result); } /* If no entity matched the query criteria or a single entity matched, * which is the same as the entity being validated, the criteria is * unique. */ - if (0 === count($result) || (1 === count($result) && $entity === ($result instanceof \Iterator ? $result->current() : current($result)))) { + if (!$result || (1 === \count($result) && current($result) === $entity)) { return; } From 4a8306e7be9398656012ccd344319f59f32ca991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 22 Apr 2018 11:17:37 +0200 Subject: [PATCH 49/75] [PropertyInfo] Minor cleanup and perf improvement --- .../Component/PropertyInfo/Extractor/PhpDocExtractor.php | 6 +++--- .../PropertyInfo/Extractor/ReflectionExtractor.php | 4 ++-- .../PropertyInfo/PropertyDescriptionExtractorInterface.php | 2 +- .../Component/PropertyInfo/PropertyInfoExtractor.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 6be39d29d225e..717baddab2b57 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -111,7 +111,7 @@ public function getTypes($class, $property, array $context = array()) $nullable = false !== $nullKey; // Remove the null type from the type if other types are defined - if ($nullable && count($varTypes) > 1) { + if ($nullable && \count($varTypes) > 1) { unset($varTypes[$nullKey]); } @@ -127,7 +127,7 @@ public function getTypes($class, $property, array $context = array()) return; } - if (!in_array($prefix, ReflectionExtractor::$arrayMutatorPrefixes)) { + if (!\in_array($prefix, ReflectionExtractor::$arrayMutatorPrefixes)) { return $types; } @@ -386,7 +386,7 @@ private function normalizeType($docType) */ private function getPhpTypeAndClass($docType) { - if (in_array($docType, Type::$builtinTypes)) { + if (\in_array($docType, Type::$builtinTypes)) { return array($docType, null); } diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 3ec1d8d6eab08..fcd443de9bcda 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -161,7 +161,7 @@ private function extractFromMutator($class, $property) return; } - if (in_array($prefix, self::$arrayMutatorPrefixes)) { + if (\in_array($prefix, self::$arrayMutatorPrefixes)) { $type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type); } @@ -187,7 +187,7 @@ private function extractFromAccessor($class, $property) return array($this->extractFromReflectionType($reflectionType)); } - if (in_array($prefix, array('is', 'can'))) { + if (\in_array($prefix, array('is', 'can'))) { return array(new Type(Type::BUILTIN_TYPE_BOOL)); } } diff --git a/src/Symfony/Component/PropertyInfo/PropertyDescriptionExtractorInterface.php b/src/Symfony/Component/PropertyInfo/PropertyDescriptionExtractorInterface.php index a2e98d0febb29..3f400a8fa53ea 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyDescriptionExtractorInterface.php +++ b/src/Symfony/Component/PropertyInfo/PropertyDescriptionExtractorInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\PropertyInfo; /** - * Description extractor Interface. + * Guesses the property's human readable description. * * @author Kévin Dunglas */ diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php index 031c8ac05e26a..1361a94378434 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php @@ -112,7 +112,7 @@ public function isWritable($class, $property, array $context = array()) private function extract(array $extractors, $method, array $arguments) { foreach ($extractors as $extractor) { - $value = call_user_func_array(array($extractor, $method), $arguments); + $value = \call_user_func_array(array($extractor, $method), $arguments); if (null !== $value) { return $value; } From c4daef9db6d50e5aeb1ae17275b07eed25288a56 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 25 Apr 2018 16:05:38 +0200 Subject: [PATCH 50/75] [VarDumper] Remove decoration from actual output in tests --- .../Tests/DataCollector/DumpDataCollectorTest.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 2dbb799109708..4c7cd9a51c0e9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -67,7 +67,7 @@ public function testCollectDefault() ob_start(); $collector->collect(new Request(), new Response()); - $output = ob_get_clean(); + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); if (\PHP_VERSION_ID >= 50400) { $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output); @@ -125,10 +125,11 @@ public function testFlush() ob_start(); $collector->__destruct(); + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); if (\PHP_VERSION_ID >= 50400) { - $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean()); + $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", $output); } else { - $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", ob_get_clean()); + $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", $output); } } @@ -141,10 +142,11 @@ public function testFlushNothingWhenDataDumperIsProvided() ob_start(); $collector->dump($data); $line = __LINE__ - 1; + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); if (\PHP_VERSION_ID >= 50400) { - $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean()); + $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", $output); } else { - $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", ob_get_clean()); + $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", $output); } ob_start(); From e9cc947aef3db8675161741237f288fb5a5ecd0c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 25 Apr 2018 16:21:38 +0200 Subject: [PATCH 51/75] [PhpUnitBridge] Fix #26994 --- src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php index d727881a11d81..d4b5ea26d8cd8 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV5.php @@ -23,6 +23,6 @@ class CommandForV5 extends \PHPUnit_TextUI_Command */ protected function createRunner() { - return new TestRunner($this->arguments['loader']); + return new TestRunnerForV5($this->arguments['loader']); } } From 9dff22ca9911d4bc478b04933a571cfe95eb9be3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 23 Apr 2018 14:06:09 +0200 Subject: [PATCH 52/75] [Security] guardAuthenticationProvider::authenticate cannot return null according to interface specification --- .../Provider/GuardAuthenticationProvider.php | 57 +++++++++++-------- .../GuardAuthenticationProviderTest.php | 35 ++++++++++++ 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index 4347e020021fe..b9e1f66abb853 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -13,6 +13,7 @@ use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; +use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; @@ -63,7 +64,7 @@ public function __construct(array $guardAuthenticators, UserProviderInterface $u */ public function authenticate(TokenInterface $token) { - if (!$this->supports($token)) { + if (!$token instanceof GuardTokenInterface) { throw new \InvalidArgumentException('GuardAuthenticationProvider only supports GuardTokenInterface.'); } @@ -87,19 +88,13 @@ public function authenticate(TokenInterface $token) throw new AuthenticationExpiredException(); } - // find the *one* GuardAuthenticator that this token originated from - foreach ($this->guardAuthenticators as $key => $guardAuthenticator) { - // get a key that's unique to *this* guard authenticator - // this MUST be the same as GuardAuthenticationListener - $uniqueGuardKey = $this->providerKey.'_'.$key; + $guardAuthenticator = $this->findOriginatingAuthenticator($token); - if ($uniqueGuardKey == $token->getGuardProviderKey()) { - return $this->authenticateViaGuard($guardAuthenticator, $token); - } + if (null === $guardAuthenticator) { + throw new AuthenticationException(sprintf('Token with provider key "%s" did not originate from any of the guard authenticators of provider "%s".', $token->getGuardProviderKey(), $this->providerKey)); } - // no matching authenticator found - but there will be multiple GuardAuthenticationProvider - // instances that will be checked if you have multiple firewalls. + return $this->authenticateViaGuard($guardAuthenticator, $token); } private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token) @@ -108,18 +103,11 @@ private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenti $user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider); if (null === $user) { - throw new UsernameNotFoundException(sprintf( - 'Null returned from %s::getUser()', - get_class($guardAuthenticator) - )); + throw new UsernameNotFoundException(sprintf('Null returned from %s::getUser()', get_class($guardAuthenticator))); } if (!$user instanceof UserInterface) { - throw new \UnexpectedValueException(sprintf( - 'The %s::getUser() method must return a UserInterface. You returned %s.', - get_class($guardAuthenticator), - is_object($user) ? get_class($user) : gettype($user) - )); + throw new \UnexpectedValueException(sprintf('The %s::getUser() method must return a UserInterface. You returned %s.', get_class($guardAuthenticator), is_object($user) ? get_class($user) : gettype($user))); } $this->userChecker->checkPreAuth($user); @@ -131,18 +119,37 @@ private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenti // turn the UserInterface into a TokenInterface $authenticatedToken = $guardAuthenticator->createAuthenticatedToken($user, $this->providerKey); if (!$authenticatedToken instanceof TokenInterface) { - throw new \UnexpectedValueException(sprintf( - 'The %s::createAuthenticatedToken() method must return a TokenInterface. You returned %s.', - get_class($guardAuthenticator), - is_object($authenticatedToken) ? get_class($authenticatedToken) : gettype($authenticatedToken) - )); + throw new \UnexpectedValueException(sprintf('The %s::createAuthenticatedToken() method must return a TokenInterface. You returned %s.', get_class($guardAuthenticator), is_object($authenticatedToken) ? get_class($authenticatedToken) : gettype($authenticatedToken))); } return $authenticatedToken; } + private function findOriginatingAuthenticator(PreAuthenticationGuardToken $token) + { + // find the *one* GuardAuthenticator that this token originated from + foreach ($this->guardAuthenticators as $key => $guardAuthenticator) { + // get a key that's unique to *this* guard authenticator + // this MUST be the same as GuardAuthenticationListener + $uniqueGuardKey = $this->providerKey.'_'.$key; + + if ($uniqueGuardKey === $token->getGuardProviderKey()) { + return $guardAuthenticator; + } + } + + // no matching authenticator found - but there will be multiple GuardAuthenticationProvider + // instances that will be checked if you have multiple firewalls. + + return null; + } + public function supports(TokenInterface $token) { + if ($token instanceof PreAuthenticationGuardToken) { + return null !== $this->findOriginatingAuthenticator($token); + } + return $token instanceof GuardTokenInterface; } } diff --git a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php index ed3920533fe92..847947110d993 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; +use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; /** * @author Ryan Weaver @@ -133,6 +134,40 @@ public function testGuardWithNoLongerAuthenticatedTriggersLogout() $actualToken = $provider->authenticate($token); } + public function testSupportsChecksGuardAuthenticatorsTokenOrigin() + { + $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticators = array($authenticatorA, $authenticatorB); + + $mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + $provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, 'first_firewall', $this->userChecker); + + $token = new PreAuthenticationGuardToken($mockedUser, 'first_firewall_1'); + $supports = $provider->supports($token); + $this->assertTrue($supports); + + $token = new PreAuthenticationGuardToken($mockedUser, 'second_firewall_0'); + $supports = $provider->supports($token); + $this->assertFalse($supports); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException + * @expectedExceptionMessageRegExp /second_firewall_0/ + */ + public function testAuthenticateFailsOnNonOriginatingToken() + { + $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticators = array($authenticatorA); + + $mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + $provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, 'first_firewall', $this->userChecker); + + $token = new PreAuthenticationGuardToken($mockedUser, 'second_firewall_0'); + $provider->authenticate($token); + } + protected function setUp() { $this->userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); From 4e527aa790f41e18a82cb9c53e782549fb564802 Mon Sep 17 00:00:00 2001 From: Chris McCafferty Date: Sat, 10 Feb 2018 19:57:41 -0500 Subject: [PATCH 53/75] bug #25844 [HttpKernel] Catch HttpExceptions when templating is not installed --- .../FrameworkBundle/Resources/config/web.xml | 9 +++++++++ .../EventListener/ExceptionListener.php | 14 +++++++++++--- .../EventListener/ExceptionListenerTest.php | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 0622c4196c104..565aef68fd45c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -67,6 +67,15 @@ + + + + null + + %kernel.debug% + %kernel.charset% + + diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php index f18e42c7d3693..3dfa4cd8ea79a 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php @@ -12,9 +12,11 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -33,12 +35,14 @@ class ExceptionListener implements EventSubscriberInterface protected $controller; protected $logger; protected $debug; + private $charset; - public function __construct($controller, LoggerInterface $logger = null, $debug = false) + public function __construct($controller, LoggerInterface $logger = null, $debug = false, $charset = null) { $this->controller = $controller; $this->logger = $logger; $this->debug = $debug; + $this->charset = $charset; } public function onKernelException(GetResponseForExceptionEvent $event) @@ -117,8 +121,12 @@ protected function logException(\Exception $exception, $message) protected function duplicateRequest(\Exception $exception, Request $request) { $attributes = array( - '_controller' => $this->controller, - 'exception' => FlattenException::create($exception), + 'exception' => $exception = FlattenException::create($exception), + '_controller' => $this->controller ?: function () use ($exception) { + $handler = new ExceptionHandler($this->debug, $this->charset); + + return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders()); + }, 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, ); $request = $request->duplicate(null, null, $attributes); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php index 3cb0b298bb07a..b607bf900ae91 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php @@ -151,6 +151,23 @@ public function testCSPHeaderIsRemoved() $this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed'); $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed'); } + + public function testNullController() + { + $listener = new ExceptionListener(null); + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { + $controller = $request->attributes->get('_controller'); + + return $controller(); + })); + $request = Request::create('/'); + $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); + + $listener->onKernelException($event); + + $this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent()); + } } class TestLogger extends Logger implements DebugLoggerInterface From 36f384984272fd720e6e6bb4c8deac7edbcabeed Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 25 Apr 2018 18:20:53 +0200 Subject: [PATCH 54/75] fix merge --- .../Tests/Provider/GuardAuthenticationProviderTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php index 17ea596d15ba7..04c16dfd4d142 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php @@ -156,7 +156,7 @@ public function testCheckCredentialsReturningNonTrueFailsAuthentication() { $providerKey = 'my_uncool_firewall'; - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); // make sure the authenticator is used $this->preAuthenticationToken->expects($this->any()) @@ -201,8 +201,8 @@ public function testGuardWithNoLongerAuthenticatedTriggersLogout() public function testSupportsChecksGuardAuthenticatorsTokenOrigin() { - $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticatorB = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); $authenticators = array($authenticatorA, $authenticatorB); $mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); @@ -223,7 +223,7 @@ public function testSupportsChecksGuardAuthenticatorsTokenOrigin() */ public function testAuthenticateFailsOnNonOriginatingToken() { - $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); $authenticators = array($authenticatorA); $mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); From a8e284f986a9a4d2244d054e6999dc9ffa586033 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 26 Apr 2018 11:45:21 +0200 Subject: [PATCH 55/75] [PhpUnitBridge] silence wget --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index a549cd7da4fb7..a824eae8f2ab4 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -72,7 +72,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ stream_copy_to_stream($remoteZipStream, fopen("$PHPUNIT_VERSION.zip", 'wb')); } else { @unlink("$PHPUNIT_VERSION.zip"); - passthru("wget https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); + passthru("wget -q https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); } if (!class_exists('ZipArchive')) { throw new \Exception('simple-phpunit requires the "zip" PHP extension to be installed and enabled in order to uncompress the downloaded PHPUnit packages.'); From 9afad9decd0d30e87e2fc760fe26ddfd1b27e813 Mon Sep 17 00:00:00 2001 From: Leo Feyer Date: Thu, 26 Apr 2018 12:21:35 +0200 Subject: [PATCH 56/75] Make the simple auth provider the same as in Symfony 2.7. --- .../Provider/SimpleAuthenticationProvider.php | 17 +------ .../SimpleAuthenticationProviderTest.php | 49 ------------------- 2 files changed, 1 insertion(+), 65 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index 22f3c4da859de..b4bdbf40c097d 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Security\Core\Authentication\Provider; -use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserChecker; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -50,20 +48,7 @@ public function authenticate(TokenInterface $token) $user = $authToken->getUser(); if (!$user instanceof UserInterface) { - try { - $user = $this->userProvider->loadUserByUsername($user); - - if (!$user instanceof UserInterface) { - return $authToken; - } - } catch (UsernameNotFoundException $e) { - $e->setUsername($user); - throw $e; - } catch (\Exception $e) { - $e = new AuthenticationServiceException($e->getMessage(), 0, $e); - $e->setToken($token); - throw $e; - } + return $authToken; } $this->userChecker->checkPreAuth($user); diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php index 752c9d2aa478b..3694d996feda6 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php @@ -15,7 +15,6 @@ use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider; use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Exception\LockedException; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserChecker; class SimpleAuthenticationProviderTest extends TestCase @@ -74,54 +73,6 @@ public function testAuthenticateWhenPostChecksFails() $provider->authenticate($token); } - public function testAuthenticateFromString() - { - $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - - $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - $token->expects($this->any()) - ->method('getUser') - ->will($this->returnValue('foo')); - - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); - $authenticator->expects($this->once()) - ->method('authenticateToken') - ->will($this->returnValue($token)); - - $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); - $userProvider->expects($this->once()) - ->method('loadUserByUsername') - ->willReturn($this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock()); - $provider = $this->getProvider($authenticator, $userProvider); - - $this->assertSame($token, $provider->authenticate($token)); - } - - /** - * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException - */ - public function testUsernameNotFound() - { - $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - - $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - $token->expects($this->any()) - ->method('getUser') - ->will($this->returnValue('foo')); - - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); - $authenticator->expects($this->once()) - ->method('authenticateToken') - ->will($this->returnValue($token)); - - $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); - $userProvider->expects($this->once()) - ->method('loadUserByUsername') - ->willThrowException(new UsernameNotFoundException()); - - $this->getProvider($authenticator, $userProvider)->authenticate($token); - } - public function testAuthenticateSkipsUserChecksForNonUserInterfaceObjects() { $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); From 229430fdbde34bc158049e74f5615fc843460b21 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 26 Apr 2018 14:40:54 +0200 Subject: [PATCH 57/75] [VarDumper] Fix HtmlDumper classes match --- .../Component/VarDumper/Dumper/HtmlDumper.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index c1263026b8c63..2ba7ebf57090a 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -310,6 +310,9 @@ function xpathString(str) { return "concat(" + parts.join(",") + ", '')"; } + function xpathHasClass(className) { + return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; + } addEventListener(root, 'mouseover', function (e) { if ('' != refStyle.innerHTML) { refStyle.innerHTML = ''; @@ -516,7 +519,15 @@ function showCurrent(state) return; } - var xpathResult = doc.evaluate('//pre[@id="' + root.id + '"]//span[@class="sf-dump-str" or @class="sf-dump-key" or @class="sf-dump-public" or @class="sf-dump-protected" or @class="sf-dump-private"][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); + var classMatches = [ + "sf-dump-str", + "sf-dump-key", + "sf-dump-public", + "sf-dump-protected", + "sf-dump-private", + ].map(xpathHasClass).join(' or '); + + var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); while (node = xpathResult.iterateNext()) state.nodes.push(node); From be8dbc36603d9aefc5d5f662df727819f010bbc9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 26 Apr 2018 13:28:24 +0200 Subject: [PATCH 58/75] [HttpKernel] Don't clean legacy containers that are still loaded --- src/Symfony/Component/HttpKernel/Kernel.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0d68c4f7ff044..247bea208af8e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -670,9 +670,11 @@ protected function initializeContainer() // Because concurrent requests might still be using them, // old container files are not removed immediately, // but on a next dump of the container. + static $legacyContainers = array(); $oldContainerDir = dirname($oldContainer->getFileName()); - foreach (glob(dirname($oldContainerDir).'/*.legacy') as $legacyContainer) { - if ($oldContainerDir.'.legacy' !== $legacyContainer && @unlink($legacyContainer)) { + $legacyContainers[$oldContainerDir.'.legacy'] = true; + foreach (glob(dirname($oldContainerDir).DIRECTORY_SEPARATOR.'*.legacy') as $legacyContainer) { + if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { (new Filesystem())->remove(substr($legacyContainer, 0, -7)); } } From 43e733f8fe289b58a9e71b0b7a94c69925ad4356 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 26 Apr 2018 17:59:35 +0200 Subject: [PATCH 59/75] [appveyor] use PHP 7.1 to run composer --- appveyor.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cc1de26c5f8ef..bd35af195d13e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,8 +18,8 @@ install: - mkdir c:\php && cd c:\php - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-5.5.9-nts-Win32-VC11-x86.zip - - 7z x php-5.5.9-nts-Win32-VC11-x86.zip -y >nul - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip + - 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul - cd ext - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-4.0.10-5.5-nts-vc11-x86.zip - 7z x php_apcu-4.0.10-5.5-nts-vc11-x86.zip -y >nul @@ -45,19 +45,21 @@ install: - echo extension=php_pdo_sqlite.dll >> php.ini-max - echo extension=php_curl.dll >> php.ini-max - echo curl.cainfo=c:\php\cacert.pem >> php.ini-max - - copy /Y php.ini-max php.ini + - copy /Y php.ini-min php.ini + - echo extension=php_openssl.dll >> php.ini - cd c:\projects\symfony - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.3.0/composer.phar) - php composer.phar self-update - copy /Y .composer\* %APPDATA%\Composer\ - php .github/build-packages.php "HEAD^" src\Symfony\Bridge\PhpUnit - IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev) - - php -dmemory_limit=-1 composer.phar update --no-progress --no-suggest --ansi + - php composer.phar config platform.php 5.5.9 + - php composer.phar update --no-progress --no-suggest --ansi - php phpunit install test_script: - SET X=0 - - cd c:\php && 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul && copy /Y php.ini-min php.ini + - cd c:\php && copy /Y php.ini-min php.ini - cd c:\projects\symfony - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - cd c:\php && 7z x php-5.5.9-nts-Win32-VC11-x86.zip -y >nul && copy /Y php.ini-min php.ini From 79ffd31af818c1ad5584e5a7aef920b25d9dab49 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 27 Apr 2018 07:41:13 +0200 Subject: [PATCH 60/75] updated CHANGELOG for 2.7.46 --- CHANGELOG-2.7.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 6c8ff11ea85cb..2f6ece9b92809 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,19 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.46 (2018-04-27) + + * bug #26831 [Bridge/Doctrine] count(): Parameter must be an array or an object that implements Countable (gpenverne) + * bug #27044 [Security] Skip user checks if not implementing UserInterface (chalasr) + * bug #26910 Use new PHP7.2 functions in hasColorSupport (johnstevenson) + * bug #26999 [VarDumper] Fix dumping of SplObjectStorage (corphi) + * bug #26886 Don't assume that file binary exists on *nix OS (teohhanhui) + * bug #26643 Fix that ESI/SSI processing can turn a "private" response "public" (mpdude) + * bug #26932 [Form] Fixed trimming choice values (HeahDude) + * bug #26875 [Console] Don't go past exact matches when autocompleting (nicolas-grekas) + * bug #26823 [Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't existing class (Pascal Montoya, pmontoya) + * bug #26834 [Yaml] Throw parse error on unfinished inline map (nicolas-grekas) + * 2.7.45 (2018-04-06) * bug #26763 [Finder] Remove duplicate slashes in filenames (helhum) From 029b182a5d611d7a07588ec3cf422d763e1f4d51 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 27 Apr 2018 07:41:29 +0200 Subject: [PATCH 61/75] update CONTRIBUTORS for 2.7.46 --- CONTRIBUTORS.md | 68 +++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 57bd22e5c521d..bc4ebf6f78139 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -13,8 +13,8 @@ Symfony is the result of the work of many people who made the code better - Jordi Boggiano (seldaek) - Victor Berchet (victor) - Kévin Dunglas (dunglas) - - Johannes S (johannes) - Robin Chalas (chalas_r) + - Johannes S (johannes) - Jakub Zalas (jakubzalas) - Kris Wallsmith (kriswallsmith) - Ryan Weaver (weaverryan) @@ -26,8 +26,8 @@ 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) - - Joseph Bielawski (stloyd) - Roland Franssen (ro0) + - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) @@ -39,32 +39,32 @@ Symfony is the result of the work of many people who made the code better - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - Sarah Khalil (saro0h) + - Samuel ROZE (sroze) - Jonathan Wage (jwage) - Hamza Amrouche (simperfit) - Diego Saint Esteben (dosten) + - Yonel Ceruto (yonelceruto) - Alexandre Salomé (alexandresalome) + - Iltar van der Berg (kjarli) - William Durand (couac) - ornicar - Francis Besset (francisbesset) - - Iltar van der Berg (kjarli) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - - Samuel ROZE (sroze) - - Yonel Ceruto (yonelceruto) - Bulat Shakirzyanov (avalanche123) - Peter Rehm (rpet) - - Saša Stamenković (umpirsky) - Matthias Pigulla (mpdude) + - Saša Stamenković (umpirsky) - Pierre du Plessis (pierredup) - Henrik Bjørnskov (henrikbjorn) - Dany Maillard (maidmaid) - Miha Vrhovnik - Tobias Nyholm (tobias) - Diego Saint Esteben (dii3g0) - - Konstantin Kudryashov (everzet) - Kevin Bond (kbond) - - Bilal Amarni (bamarni) + - Konstantin Kudryashov (everzet) - Alexander M. Turek (derrabus) + - Bilal Amarni (bamarni) - Jérémy DERUSSÉ (jderusse) - Florin Patan (florinpatan) - Mathieu Piot (mpiot) @@ -88,28 +88,28 @@ Symfony is the result of the work of many people who made the code better - Luis Cordova (cordoval) - Graham Campbell (graham) - Daniel Holmes (dholmes) + - David Maicher (dmaicher) - Dariusz Ruminski - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - Jérôme Tamarelle (gromnan) - John Wards (johnwards) - - David Maicher (dmaicher) - Fran Moreno (franmomu) + - Vladimir Reznichenko (kalessil) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - - Vladimir Reznichenko (kalessil) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - Brice BERNARD (brikou) - Baptiste Clavié (talus) + - Grégoire Paris (greg0ire) - marc.weistroff - lenar - Alexander Schwenn (xelaris) - Włodzimierz Gajda (gajdaw) - - Grégoire Paris (greg0ire) - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) - Colin Frei @@ -122,17 +122,17 @@ Symfony is the result of the work of many people who made the code better - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) + - Lars Strojny (lstrojny) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) + - Javier Spagnoletti (phansys) - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - Sebastiaan Stok (sstok) - Stefano Sala (stefano.sala) - Evgeniy (ewgraf) - - Lars Strojny (lstrojny) - Alex Pott - - Javier Spagnoletti (phansys) - Vincent AUBERT (vincent) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) @@ -150,6 +150,7 @@ Symfony is the result of the work of many people who made the code better - Arnaud Kleinpeter (nanocom) - gadelat (gadelat) - jwdeitch + - Teoh Han Hui (teohhanhui) - Mikael Pajunen - Joel Wurtz (brouznouf) - Valentin Udaltsov (vudaltsov) @@ -160,7 +161,6 @@ Symfony is the result of the work of many people who made the code better - Richard Shank (iampersistent) - Thomas Rabaix (rande) - Rouven Weßling (realityking) - - Teoh Han Hui (teohhanhui) - Clemens Tolboom - Helmer Aaviksoo - Hiromi Hishida (77web) @@ -186,6 +186,7 @@ Symfony is the result of the work of many people who made the code better - Gabriel Ostrolucký - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) + - DQNEO - SpacePossum - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) @@ -223,6 +224,7 @@ Symfony is the result of the work of many people who made the code better - Niels Keurentjes (curry684) - Eugene Wissner - Julien Brochet (mewt) + - Leo Feyer - Tristan Darricau (nicofuma) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) @@ -269,7 +271,6 @@ Symfony is the result of the work of many people who made the code better - Ray - Tyson Andre - Nikolay Labinskiy (e-moe) - - Leo Feyer - Chekote - Thomas Adam - Albert Casademont (acasademont) @@ -277,7 +278,6 @@ Symfony is the result of the work of many people who made the code better - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - Andreas Schempp (aschempp) - - DQNEO - jdhoek - Pavel Batanov (scaytrase) - Bob den Otter (bopp) @@ -300,6 +300,7 @@ Symfony is the result of the work of many people who made the code better - Michael Holm (hollo) - Marc Weistroff (futurecat) - Christian Schmidt + - Maxime Veber (nek-) - Edi Modrić (emodric) - Chad Sikorra (chadsikorra) - Chris Smith (cs278) @@ -327,6 +328,7 @@ Symfony is the result of the work of many people who made the code better - John Bafford (jbafford) - Adrian Rudnik (kreischweide) - Francesc Rosàs (frosas) + - Romain Pierre (romain-pierre) - Massimiliano Arione (garak) - Julien Galenski (ruian) - Bongiraud Dominique @@ -357,8 +359,8 @@ Symfony is the result of the work of many people who made the code better - Damien Alexandre (damienalexandre) - Felix Labrecque - Yaroslav Kiliba - - Maxime Veber (nek-) - Terje Bråten + - Mathieu Lechat - Robbert Klarenbeek (robbertkl) - JhonnyL - David Badura (davidbadura) @@ -372,6 +374,7 @@ Symfony is the result of the work of many people who made the code better - Philipp Kräutli (pkraeutli) - Kirill chEbba Chebunin (chebba) - Greg Thornton (xdissent) + - Gary PEGEOT (gary-p) - Costin Bereveanu (schniper) - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) @@ -421,9 +424,11 @@ Symfony is the result of the work of many people who made the code better - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) - Jan Schumann + - Christian Schmidt - Niklas Fiekas - Markus Bachmann (baachi) - lancergr + - Zan Baldwin - Mihai Stancu - Olivier Dolbeau (odolbeau) - Jan Rosier (rosier) @@ -438,6 +443,7 @@ Symfony is the result of the work of many people who made the code better - Andreas Braun - Boris Vujicic (boris.vujicic) - Chris Sedlmayr (catchamonkey) + - Mateusz Sip (mateusz_sip) - Seb Koelen - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) @@ -458,6 +464,7 @@ Symfony is the result of the work of many people who made the code better - Adam Harvey - Anton Bakai - Alex Bakhturin + - insekticid - Alexander Obuhovich (aik099) - boombatower - Fabrice Bernhard (fabriceb) @@ -503,7 +510,6 @@ Symfony is the result of the work of many people who made the code better - alexpods - Arjen van der Meijden - Dariusz Ruminski - - Mathieu Lechat - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) - Almog Baku (almogbaku) @@ -552,7 +558,6 @@ Symfony is the result of the work of many people who made the code better - Disquedur - Michiel Boeckaert (milio) - Geoffrey Tran (geoff) - - Romain Pierre (romain-pierre) - David Prévot - Jan Behrens - Mantas Var (mvar) @@ -566,7 +571,6 @@ Symfony is the result of the work of many people who made the code better - aubx - Marvin Butkereit - Ricky Su (ricky) - - Zan Baldwin - Gildas Quéméner (gquemener) - Charles-Henri Bruyand - Max Rath (drak3) @@ -579,6 +583,7 @@ Symfony is the result of the work of many people who made the code better - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) + - Christophe Villeger (seragan) - Stefan Gehrig (sgehrig) - Hany el-Kerdany - Wang Jingyu @@ -590,13 +595,13 @@ Symfony is the result of the work of many people who made the code better - Javier López (loalf) - Reinier Kip - Geoffrey Brier (geoffrey-brier) + - Vladimir Tsykun - Dustin Dobervich (dustin10) - dantleech - Anne-Sophie Bachelard (annesophie) - Sebastian Marek (proofek) - Erkhembayar Gantulga (erheme318) - Michal Trojanowski - - Mateusz Sip - David Fuhr - Kamil Kokot (pamil) - Aurimas Niekis (gcds) @@ -673,7 +678,6 @@ Symfony is the result of the work of many people who made the code better - twifty - Indra Gunawan (guind) - Peter Ward - - insekticid - Julien DIDIER (juliendidier) - Dominik Ritter (dritter) - Sebastian Grodzicki (sgrodzicki) @@ -880,6 +884,7 @@ Symfony is the result of the work of many people who made the code better - Sander Marechal - Radosław Benkel - jean pasqualini (darkilliant) + - Ross Motley (rossmotley) - ttomor - Mei Gwilym (meigwilym) - Michael H. Arieli (excelwebzone) @@ -899,6 +904,7 @@ Symfony is the result of the work of many people who made the code better - Zachary Tong (polyfractal) - Ashura - Hryhorii Hrebiniuk + - johnstevenson - Dennis Fridrich (dfridrich) - hamza - dantleech @@ -942,6 +948,7 @@ Symfony is the result of the work of many people who made the code better - mlazovla - Max Beutel - Antanas Arvasevicius + - Thomas - Maximilian Berghoff (electricmaxxx) - nacho - Piotr Antosik (antek88) @@ -1085,6 +1092,7 @@ Symfony is the result of the work of many people who made the code better - Tobias Stöckler - Mario Young - Ilia (aliance) + - Grégoire Penverne (gpenverne) - Mo Di (modi) - Pablo Schläpfer - Jelte Steijaert (jelte) @@ -1105,6 +1113,7 @@ Symfony is the result of the work of many people who made the code better - Lars Ambrosius Wallenborn (larsborn) - Oriol Mangas Abellan (oriolman) - Sebastian Göttschkes (sgoettschkes) + - Sergey (upyx) - Tatsuya Tsuruoka - Ross Tuck - Kévin Gomez (kevin) @@ -1128,6 +1137,7 @@ Symfony is the result of the work of many people who made the code better - Grzegorz Zdanowski (kiler129) - sl_toto (sl_toto) - Walter Dal Mut (wdalmut) + - abluchet - Matthieu - Albin Kerouaton - Sébastien HOUZÉ @@ -1144,6 +1154,7 @@ Symfony is the result of the work of many people who made the code better - Andy Raines - Anthony Ferrara - Klaas Cuvelier (kcuvelier) + - Mathieu TUDISCO (mathieutu) - markusu49 - Steve Frécinaux - Jules Lamur @@ -1186,6 +1197,7 @@ Symfony is the result of the work of many people who made the code better - Tadcka - Beth Binkovitz - Gonzalo Míguez + - Philipp Cordes - Pierre Rineau - Romain Geissler - Adrien Moiruad @@ -1198,6 +1210,7 @@ Symfony is the result of the work of many people who made the code better - Jay Severson - René Kerner - Nathaniel Catchpole + - - Adrien Samson (adriensamson) - Samuel Gordalina (gordalina) - Max Romanovsky (maxromanovsky) @@ -1246,6 +1259,7 @@ Symfony is the result of the work of many people who made the code better - Simon Neidhold - Valentin VALCIU - Jeremiah VALERIE + - Julien Menth - Kevin Dew - James Cowgill - 1ma (jautenim) @@ -1302,7 +1316,6 @@ Symfony is the result of the work of many people who made the code better - ryunosuke - zenmate - victoria - - Christian Schmidt - Francisco Facioni (fran6co) - Iwan van Staveren (istaveren) - Povilas S. (povilas) @@ -1379,10 +1392,13 @@ Symfony is the result of the work of many people who made the code better - Oleksii Zhurbytskyi - Andy Stanberry - Felix Marezki + - Normunds - Luiz “Felds” Liscia - Thomas Rothe - nietonfir - alefranz + - David Barratt + - Pavel.Batanov - avi123 - alsar - Aarón Nieves Fernández @@ -1612,6 +1628,7 @@ Symfony is the result of the work of many people who made the code better - Gabriel Moreira - Alexey Popkov - ChS + - Alexis MARQUIS - Joseph Deray - Damian Sromek - Ben @@ -1654,12 +1671,12 @@ Symfony is the result of the work of many people who made the code better - jc - BenjaminBeck - Aurelijus Rožėnas - - Vladimir Tsykun - Jordan Hoff - znerol - Christian Eikermann - Kai Eichinger - Antonio Angelino + - Pascal Montoya - Matt Fields - Niklas Keller - Vladimir Sazhin @@ -1814,6 +1831,7 @@ Symfony is the result of the work of many people who made the code better - Arash Tabriziyan (ghost098) - ibasaw (ibasaw) - Vladislav Krupenkin (ideea) + - Peter Orosz (ill_logical) - Imangazaliev Muhammad (imangazaliev) - j0k (j0k) - joris de wit (jdewit) @@ -1862,7 +1880,6 @@ Symfony is the result of the work of many people who made the code better - scourgen hung (scourgen) - Sébastien Alfaiate (seb33300) - Sebastian Busch (sebu) - - Christophe Villeger (seragan) - André Filipe Gonçalves Neves (seven) - Bruno Ziegler (sfcoder) - Andrea Giuliano (shark) @@ -1908,6 +1925,7 @@ Symfony is the result of the work of many people who made the code better - Zander Baldwin - Philipp Scheit - max + - Ahmad Mayahi (ahmadmayahi) - Mohamed Karnichi (amiral) - Andrew Carter (andrewcarteruk) - Adam Elsodaney (archfizz) From 436fd79a205d35a0a78e0f9886ddb43f2ef2184d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 27 Apr 2018 07:41:32 +0200 Subject: [PATCH 62/75] updated VERSION for 2.7.46 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 1b8abba1474dc..43a441fbe25d5 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.46-DEV'; + const VERSION = '2.7.46'; const VERSION_ID = 20746; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 46; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 212c469ebfbbd2d38981eef123b75cb7e4159cc5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 22 Apr 2018 21:20:57 +0200 Subject: [PATCH 63/75] [Cache] TagAwareAdapterInterface::invalidateTags() should commit deferred items --- .../Cache/Adapter/TagAwareAdapter.php | 123 ++++++++++++------ .../Tests/Adapter/TagAwareAdapterTest.php | 16 +++ 2 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index a71b903d734f6..67f9477ae3632 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -33,11 +33,14 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R private $getTagsByKey; private $invalidateTags; private $tags; + private $knownTagVersions = array(); + private $knownTagVersionsTtl; - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null) + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, $knownTagVersionsTtl = 0.15) { $this->pool = $itemsPool; $this->tags = $tagsPool ?: $itemsPool; + $this->knownTagVersionsTtl = $knownTagVersionsTtl; $this->createCacheItem = \Closure::bind( function ($key, $value, CacheItem $protoItem) { $item = new CacheItem(); @@ -87,8 +90,7 @@ function ($deferred) { ); $this->invalidateTags = \Closure::bind( function (AdapterInterface $tagsAdapter, array $tags) { - foreach ($tagsAdapter->getItems($tags) as $v) { - $v->set(1 + (int) $v->get()); + foreach ($tags as $v) { $v->defaultLifetime = 0; $v->expiry = null; $tagsAdapter->saveDeferred($v); @@ -106,14 +108,42 @@ function (AdapterInterface $tagsAdapter, array $tags) { */ public function invalidateTags(array $tags) { - foreach ($tags as $k => $tag) { - if ('' !== $tag && \is_string($tag)) { - $tags[$k] = $tag.static::TAGS_PREFIX; + $ok = true; + $tagsByKey = array(); + $invalidatedTags = array(); + foreach ($tags as $tag) { + CacheItem::validateKey($tag); + $invalidatedTags[$tag] = 0; + } + + if ($this->deferred) { + $items = $this->deferred; + foreach ($items as $key => $item) { + if (!$this->pool->saveDeferred($item)) { + unset($this->deferred[$key]); + $ok = false; + } } + + $f = $this->getTagsByKey; + $tagsByKey = $f($items); + $this->deferred = array(); + } + + $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags); + $f = $this->createCacheItem; + + foreach ($tagsByKey as $key => $tags) { + $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); + } + $ok = $this->pool->commit() && $ok; + + if ($invalidatedTags) { + $f = $this->invalidateTags; + $ok = $f($this->tags, $invalidatedTags) && $ok; } - $f = $this->invalidateTags; - return $f($this->tags, $tags); + return $ok; } /** @@ -132,7 +162,7 @@ public function hasItem($key) } foreach ($this->getTagVersions(array($itemTags)) as $tag => $version) { - if ($itemTags[$tag] !== $version) { + if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) { return false; } } @@ -241,29 +271,7 @@ public function saveDeferred(CacheItemInterface $item) */ public function commit() { - $ok = true; - - if ($this->deferred) { - $items = $this->deferred; - foreach ($items as $key => $item) { - if (!$this->pool->saveDeferred($item)) { - unset($this->deferred[$key]); - $ok = false; - } - } - - $f = $this->getTagsByKey; - $tagsByKey = $f($items); - $this->deferred = array(); - $tagVersions = $this->getTagVersions($tagsByKey); - $f = $this->createCacheItem; - - foreach ($tagsByKey as $key => $tags) { - $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); - } - } - - return $this->pool->commit() && $ok; + return $this->invalidateTags(array()); } public function __destruct() @@ -294,7 +302,7 @@ private function generateItems($items, array $tagKeys) foreach ($itemTags as $key => $tags) { foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version) { + if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) { unset($itemTags[$key]); continue 2; } @@ -310,23 +318,54 @@ private function generateItems($items, array $tagKeys) } } - private function getTagVersions(array $tagsByKey) + private function getTagVersions(array $tagsByKey, array &$invalidatedTags = array()) { - $tagVersions = array(); + $tagVersions = $invalidatedTags; foreach ($tagsByKey as $tags) { $tagVersions += $tags; } - if ($tagVersions) { - $tags = array(); - foreach ($tagVersions as $tag => $version) { - $tagVersions[$tag] = $tag.static::TAGS_PREFIX; - $tags[$tag.static::TAGS_PREFIX] = $tag; + if (!$tagVersions) { + return array(); + } + + if (!$fetchTagVersions = 1 !== \func_num_args()) { + foreach ($tagsByKey as $tags) { + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] > $version) { + $tagVersions[$tag] = $version; + } + } + } + } + + $now = microtime(true); + $tags = array(); + foreach ($tagVersions as $tag => $version) { + $tags[$tag.static::TAGS_PREFIX] = $tag; + if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) { + continue; + } + $version -= $this->knownTagVersions[$tag][1]; + if ((0 !== $version && 1 !== $version) || $this->knownTagVersionsTtl > $now - $this->knownTagVersions[$tag][0]) { + // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises + $fetchTagVersions = true; + } else { + $this->knownTagVersions[$tag][1] += $version; } - foreach ($this->tags->getItems($tagVersions) as $tag => $version) { - $tagVersions[$tags[$tag]] = $version->get() ?: 0; + } + + if (!$fetchTagVersions) { + return $tagVersions; + } + + foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { + $tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0; + if (isset($invalidatedTags[$tag])) { + $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]); } + $this->knownTagVersions[$tag] = array($now, $tagVersions[$tag]); } return $tagVersions; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php index 0e4e07a16d51b..094fa9558bfd5 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php @@ -71,6 +71,22 @@ public function testInvalidateTags() $this->assertTrue($pool->getItem('foo')->isHit()); } + public function testInvalidateCommits() + { + $pool1 = $this->createCachePool(); + + $foo = $pool1->getItem('foo'); + $foo->tag('tag'); + + $pool1->saveDeferred($foo->set('foo')); + $pool1->invalidateTags(array('tag')); + + $pool2 = $this->createCachePool(); + $foo = $pool2->getItem('foo'); + + $this->assertTrue($foo->isHit()); + } + public function testTagsAreCleanedOnSave() { $pool = $this->createCachePool(); From 64a0f23affd4646983aca7e96daf44ef236df8d7 Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Thu, 26 Apr 2018 17:44:59 +0300 Subject: [PATCH 64/75] Fix #27011: Session ini_set bug --- .../Session/Storage/NativeSessionStorage.php | 6 +++--- .../Storage/NativeSessionStorageTest.php | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index f03cdf343024d..34d94c55bcc9f 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -340,7 +340,7 @@ public function setOptions(array $options) } $validOptions = array_flip(array( - 'cache_limiter', 'cookie_domain', 'cookie_httponly', + 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', @@ -348,13 +348,13 @@ public function setOptions(array $options) 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { - ini_set('session.'.$key, $value); + ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 3501f74784a9e..529583c01aade 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -183,6 +183,23 @@ public function testCookieOptions() $this->assertEquals($options, $gco); } + public function testSessionOptions() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM is not handled in this test case.'); + } + + $options = array( + 'url_rewriter.tags' => 'a=href', + 'cache_expire' => '200', + ); + + $this->getStorage($options); + + $this->assertSame('a=href', ini_get('url_rewriter.tags')); + $this->assertSame('200', ini_get('session.cache_expire')); + } + /** * @expectedException \InvalidArgumentException */ From aa05f055262afa8531b1261ce9ae7a3fc5c5a73c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 27 Apr 2018 11:17:42 +0200 Subject: [PATCH 65/75] bumped Symfony version to 2.7.47 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 43a441fbe25d5..33bbddabc9eff 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.46'; - const VERSION_ID = 20746; + const VERSION = '2.7.47-DEV'; + const VERSION_ID = 20747; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 46; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 47; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From fc693078652aad47c5fb12c585789a0eaf11a806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sun, 29 Apr 2018 10:04:33 +0200 Subject: [PATCH 66/75] Add an implementation just for php 7.0 php 7 does not have the void return type. --- .../Bridge/PhpUnit/Legacy/TestRunnerForV6.php | 2 +- .../Bridge/PhpUnit/Legacy/TestRunnerForV7.php | 49 +++++++++++++++++++ .../Bridge/PhpUnit/TextUI/TestRunner.php | 4 +- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV7.php diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php index d709b873874fd..6da7c65448532 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV6.php @@ -24,7 +24,7 @@ class TestRunnerForV6 extends BaseRunner /** * {@inheritdoc} */ - protected function handleConfiguration(array &$arguments): void + protected function handleConfiguration(array &$arguments) { $listener = new SymfonyTestsListener(); diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV7.php new file mode 100644 index 0000000000000..a175fb65d7f5a --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunnerForV7.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * {@inheritdoc} + * + * @internal + */ +class TestRunnerForV7 extends BaseRunner +{ + /** + * {@inheritdoc} + */ + protected function handleConfiguration(array &$arguments): void + { + $listener = new SymfonyTestsListener(); + + parent::handleConfiguration($arguments); + + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + $registeredLocally = false; + + foreach ($arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (!$registeredLocally) { + $arguments['listeners'][] = $listener; + } + } +} diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php index af1abd3866787..7b8d162e53361 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php @@ -13,8 +13,10 @@ if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV5', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); -} else { +} elseif (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '7.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV6', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); +} else { + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV7', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); } if (false) { From 309da927e3aaa5ae7c50ed48f3bc3cc2a68af0e6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 29 Apr 2018 10:04:08 -0400 Subject: [PATCH 67/75] Avoiding an error when an unused service has a missing base class This mirrors what was already done in AutowirePass --- .../Compiler/ResolveBindingsPass.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index 63f2a470bac6f..024523e15585c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\DependencyInjection\Reference; @@ -88,8 +89,14 @@ protected function processValue($value, $isRoot = false) $calls = $value->getMethodCalls(); - if ($constructor = $this->getConstructor($value, false)) { - $calls[] = array($constructor, $value->getArguments()); + try { + if ($constructor = $this->getConstructor($value, false)) { + $calls[] = array($constructor, $value->getArguments()); + } + } catch (RuntimeException $e) { + $this->container->getDefinition($this->currentId)->addError($e->getMessage()); + + return parent::processValue($value, $isRoot); } foreach ($calls as $i => $call) { From 93a9bd39b2b8cb19b9d2b4985207f87c93de3462 Mon Sep 17 00:00:00 2001 From: Philipp Cordes Date: Sun, 29 Apr 2018 16:44:26 +0200 Subject: [PATCH 68/75] PhpDoc: There is no attempt to create the directory --- src/Symfony/Component/Lock/Store/FlockStore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Lock/Store/FlockStore.php b/src/Symfony/Component/Lock/Store/FlockStore.php index 5babc7f610bce..287d6fb583160 100644 --- a/src/Symfony/Component/Lock/Store/FlockStore.php +++ b/src/Symfony/Component/Lock/Store/FlockStore.php @@ -34,7 +34,7 @@ class FlockStore implements StoreInterface /** * @param string|null $lockPath the directory to store the lock, defaults to the system's temporary directory * - * @throws LockStorageException If the lock directory could not be created or is not writable + * @throws LockStorageException If the lock directory doesn’t exist or is not writable */ public function __construct($lockPath = null) { From f0affb72926bcd20aab28bf4b444c2d69e67a143 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 29 Apr 2018 18:19:41 -0700 Subject: [PATCH 69/75] Fix suggest.psr/*-implementation in composer.json files --- src/Symfony/Component/Console/composer.json | 2 +- src/Symfony/Component/Templating/composer.json | 2 +- src/Symfony/Component/Translation/composer.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index c4fb8c192a401..9f63559861811 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -27,7 +27,7 @@ "suggest": { "symfony/event-dispatcher": "", "symfony/process": "", - "psr/log": "For using the console logger" + "psr/log-implementation": "For using the console logger" }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, diff --git a/src/Symfony/Component/Templating/composer.json b/src/Symfony/Component/Templating/composer.json index 74f4412623328..334909c1a3a67 100644 --- a/src/Symfony/Component/Templating/composer.json +++ b/src/Symfony/Component/Templating/composer.json @@ -22,7 +22,7 @@ "psr/log": "~1.0" }, "suggest": { - "psr/log": "For using debug logging in loaders" + "psr/log-implementation": "For using debug logging in loaders" }, "autoload": { "psr-4": { "Symfony\\Component\\Templating\\": "" }, diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 3ba1a64367895..128f37f0d7f5d 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -30,7 +30,7 @@ "suggest": { "symfony/config": "", "symfony/yaml": "", - "psr/log": "To use logging capability in translator" + "psr/log-implementation": "To use logging capability in translator" }, "autoload": { "psr-4": { "Symfony\\Component\\Translation\\": "" }, From bcbd3a2902b4fc4aae1d99872d482381fc353619 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 30 Apr 2018 08:25:36 -0700 Subject: [PATCH 70/75] [PhpUnitBridge] Fix --- src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php index 7b8d162e53361..1464557619cbb 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php @@ -13,7 +13,7 @@ if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV5', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); -} elseif (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '7.0.0', '<')) { +} elseif (version_compare(\PHPUnit_Runner_Version::id(), '7.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV6', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); } else { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV7', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); From b1fb985ebc7c6dbdf032af34a6f6d37fc4583adb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 30 Apr 2018 08:36:51 -0700 Subject: [PATCH 71/75] [PhpUnitBridge] Fix --- src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php index 1464557619cbb..cda59209790d5 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php @@ -13,7 +13,7 @@ if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV5', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); -} elseif (version_compare(\PHPUnit_Runner_Version::id(), '7.0.0', '<')) { +} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV6', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); } else { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV7', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); From 620f90d200e1836a6602317615c33bd529d6042c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 30 Apr 2018 14:25:22 +0200 Subject: [PATCH 72/75] [Debug] Fixed the formatPath when a custom fileLinkFormat is defined --- .../Component/Debug/ExceptionHandler.php | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 97470cb6b4d01..f22b70f6e8c6f 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -40,7 +40,7 @@ public function __construct($debug = true, $charset = null, $fileLinkFormat = nu { $this->debug = $debug; $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; } /** @@ -355,13 +355,29 @@ private function formatClass($class) private function formatPath($path, $line) { $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); - $fmt = $this->fileLinkFormat; + $fmt = $this->fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + + if (!$fmt) { + return sprintf('in %s%s', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : ''); + } + + if (\is_string($fmt)) { + $i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f); + $fmt = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); + + for ($i = 1; isset($fmt[$i]); ++$i) { + if (0 === strpos($path, $k = $fmt[$i++])) { + $path = substr_replace($path, $fmt[$i], 0, strlen($k)); + break; + } + } - if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) { - return sprintf('in %s (line %d)', $this->escapeHtml($link), $file, $line); + $link = strtr($fmt[0], array('%f' => $path, '%l' => $line)); + } else { + $link = $fmt->format($path, $line); } - return sprintf('in %s (line %d)', $this->escapeHtml($path), $file, $line); + return sprintf('in %s%s', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : ''); } /** From a4a1645d4475f08e08c54bec91184d8d1e061c2f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 27 Apr 2018 12:57:32 +0200 Subject: [PATCH 73/75] [Debug][WebProfilerBundle] Fix setting file link format --- src/Symfony/Bridge/Twig/Extension/CodeExtension.php | 4 +++- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 3 +++ .../WebProfilerBundle/Controller/ExceptionController.php | 8 +++++--- .../WebProfilerBundle/Resources/config/profiler.xml | 1 + .../Resources/views/Profiler/open.html.twig | 2 +- .../DependencyInjection/WebProfilerExtensionTest.php | 1 + 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index f37d8100fbb44..c8b48fc6663ff 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -181,7 +181,9 @@ public function formatFile($file, $line, $text = null) } } - $text = "$text at line $line"; + if (0 < $line) { + $text .= ' at line '.$line; + } if (false !== $link = $this->getFileLink($file, $line)) { return sprintf('%s', htmlspecialchars($link, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset), $text); diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 2a62d391a7b22..17c12686dad23 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -61,6 +61,9 @@ class FrameworkBundle extends Bundle { public function boot() { + if (!ini_get('xdebug.file_link_format') && !get_cfg_var('xdebug.file_link_format')) { + ini_set('xdebug.file_link_format', $this->container->getParameter('debug.file_link_format')); + } ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true); if ($this->container->hasParameter('kernel.trusted_proxies')) { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php index 3f9d873e1d40f..f008b0b5284fc 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Controller; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -30,11 +31,12 @@ class ExceptionController protected $debug; protected $profiler; - public function __construct(Profiler $profiler = null, Environment $twig, $debug) + public function __construct(Profiler $profiler = null, Environment $twig, $debug, FileLinkFormatter $fileLinkFormat = null) { $this->profiler = $profiler; $this->twig = $twig; $this->debug = $debug; + $this->fileLinkFormat = $fileLinkFormat; } /** @@ -58,7 +60,7 @@ public function showAction($token) $template = $this->getTemplate(); if (!$this->twig->getLoader()->exists($template)) { - $handler = new ExceptionHandler($this->debug, $this->twig->getCharset()); + $handler = new ExceptionHandler($this->debug, $this->twig->getCharset(), $this->fileLinkFormat); return new Response($handler->getContent($exception), 200, array('Content-Type' => 'text/html')); } @@ -98,7 +100,7 @@ public function cssAction($token) $template = $this->getTemplate(); if (!$this->templateExists($template)) { - $handler = new ExceptionHandler($this->debug, $this->twig->getCharset()); + $handler = new ExceptionHandler($this->debug, $this->twig->getCharset(), $this->fileLinkFormat); return new Response($handler->getStylesheet($exception), 200, array('Content-Type' => 'text/css')); } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml index 7854bc199cb2e..4eb44972e72d1 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml @@ -27,6 +27,7 @@ %kernel.debug% + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.html.twig index 9b482f1f0aa96..58e1fe355621f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.html.twig @@ -8,7 +8,7 @@ {% block body %}
-

{{ file }} line {{ line }}

+

{{ file }}{% if 0 < line %} line {{ line }}{% endif %}

Open in your IDE?
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index 316bd13f2f6ed..c055d46f2ebf4 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -31,6 +31,7 @@ class WebProfilerExtensionTest extends TestCase public static function assertSaneContainer(Container $container, $message = '', $knownPrivates = array()) { $errors = array(); + $knownPrivates[] = 'debug.file_link_formatter.url_format'; foreach ($container->getServiceIds() as $id) { if (in_array($id, $knownPrivates, true)) { // to be removed in 4.0 continue; From fb98ef384be5db94390baab0024365d438cfff90 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Apr 2018 21:45:53 +0200 Subject: [PATCH 74/75] updated CHANGELOG for 4.0.9 --- CHANGELOG-4.0.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md index cbd0ed892c1db..9abb4a61a6634 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG-4.0.md @@ -7,6 +7,41 @@ in 4.0 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.0.0...v4.0.1 +* 4.0.9 (2018-04-30) + + * bug #27074 [Debug][WebProfilerBundle] Fix setting file link format (lyrixx, nicolas-grekas) + * bug #27088 ResolveBindingsPass: Don't throw error for unused service, missing parent class (weaverryan) + * bug #27086 [PHPUnitBridge] Add an implementation just for php 7.0 (greg0ire) + * bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen) + * bug #27007 [Cache] TagAwareAdapterInterface::invalidateTags() should commit deferred items (nicolas-grekas) + * bug #27067 [HttpFoundation] Fix setting session-related ini settings (e-moe) + * bug #27061 [HttpKernel] Don't clean legacy containers that are still loaded (nicolas-grekas) + * bug #27064 [VarDumper] Fix HtmlDumper classes match (ogizanagi) + * bug #27016 [Security][Guard] GuardAuthenticationProvider::authenticate cannot return null (biomedia-thomas) + * bug #26831 [Bridge/Doctrine] count(): Parameter must be an array or an object that implements Countable (gpenverne) + * bug #27044 [Security] Skip user checks if not implementing UserInterface (chalasr) + * bug #27025 [DI] Add check of internal type to ContainerBuilder::getReflectionClass (upyx) + * bug #26994 [PhpUnitBridge] Add type hints (greg0ire) + * bug #26014 [Security] Fixed being logged out on failed attempt in guard (iltar) + * bug #25348 [HttpFoundation] Send cookies using header() to fix "SameSite" ones (nicolas-grekas, cvilleger) + * bug #26910 Use new PHP7.2 functions in hasColorSupport (johnstevenson) + * bug #26999 [VarDumper] Fix dumping of SplObjectStorage (corphi) + * bug #25841 [DoctrineBridge] Fix bug when indexBy is meta key in PropertyInfo\DoctrineExtractor (insekticid) + * bug #26983 [TwigBridge] [Bootstrap 4] Fix PercentType error rendering. (alexismarquis) + * bug #26980 [TwigBundle] fix formatting arguments in plaintext format (xabbuh) + * bug #26886 Don't assume that file binary exists on *nix OS (teohhanhui) + * bug #26959 [Console] Fix PSR exception context key (scaytrase) + * bug #26899 [Routing] Fix loading multiple class annotations for invokable classes (1ed) + * bug #26643 Fix that ESI/SSI processing can turn a "private" response "public" (mpdude) + * bug #26932 [Form] Fixed trimming choice values (HeahDude) + * bug #26922 [TwigBundle] fix rendering exception stack traces (xabbuh) + * bug #26773 [HttpKernel] Make ServiceValueResolver work if controller namespace starts with a backslash in routing (mathieutu) + * bug #26870 Add d-block to bootstrap 4 alerts (Normunds) + * bug #26857 [HttpKernel] Dont create mock cookie for new sessions in tests (nicolas-grekas) + * bug #26875 [Console] Don't go past exact matches when autocompleting (nicolas-grekas) + * bug #26823 [Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't existing class (Pascal Montoya, pmontoya) + * bug #26834 [Yaml] Throw parse error on unfinished inline map (nicolas-grekas) + * 4.0.8 (2018-04-06) * bug #26802 [Security] register custom providers on ExpressionLanguage directly (dmaicher) From 2e856cda07c30ce2c2b57f82db58c76be9c14618 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Apr 2018 21:45:57 +0200 Subject: [PATCH 75/75] updated VERSION for 4.0.9 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 5ca41c8502d28..24cce648ef443 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -63,12 +63,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.0.9-DEV'; + const VERSION = '4.0.9'; const VERSION_ID = 40009; const MAJOR_VERSION = 4; const MINOR_VERSION = 0; const RELEASE_VERSION = 9; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2018'; const END_OF_LIFE = '01/2019';