From dfa7f5020e1274870ee815bb536d37b0e61d8046 Mon Sep 17 00:00:00 2001 From: Vincent Composieux Date: Mon, 29 Aug 2016 20:28:05 +0200 Subject: [PATCH 01/80] [Security] Fixed roles serialization on token from user object --- .../Core/Authentication/Token/AbstractToken.php | 2 +- .../Provider/UserAuthenticationProviderTest.php | 2 +- .../Authentication/Token/AbstractTokenTest.php | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 7538648b1329..48a4e52a48be 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -150,7 +150,7 @@ public function serialize() array( is_object($this->user) ? clone $this->user : $this->user, $this->authenticated, - $this->roles, + array_map(function ($role) { return clone $role; }, $this->roles), $this->attributes, ) ); diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php index 05030543e641..6b6a6615161b 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php @@ -220,7 +220,7 @@ public function testAuthenticateWithPreservingRoleSwitchUserRole() $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken); $this->assertSame($user, $authToken->getUser()); $this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false); - $this->assertContains($switchUserRole, $authToken->getRoles()); + $this->assertContains($switchUserRole, $authToken->getRoles(), '', false, false); $this->assertEquals('foo', $authToken->getCredentials()); $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes'); } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php index 1a786d7c4543..2eff28e009b5 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\SwitchUserRole; +use Symfony\Component\Security\Core\User\User; class TestUser { @@ -87,7 +88,7 @@ public function testEraseCredentials() public function testSerialize() { - $token = $this->getToken(array('ROLE_FOO')); + $token = $this->getToken(array('ROLE_FOO', new Role('ROLE_BAR'))); $token->setAttributes(array('foo' => 'bar')); $uToken = unserialize(serialize($token)); @@ -96,6 +97,19 @@ public function testSerialize() $this->assertEquals($token->getAttributes(), $uToken->getAttributes()); } + public function testSerializeWithRoleObjects() + { + $user = new User('name', 'password', array(new Role('ROLE_FOO'), new Role('ROLE_BAR'))); + $token = new ConcreteToken($user, $user->getRoles()); + + $serialized = serialize($token); + $unserialized = unserialize($serialized); + + $roles = $unserialized->getRoles(); + + $this->assertEquals($roles, $user->getRoles()); + } + public function testSerializeParent() { $user = new TestUser('fabien'); From 9a2b2de64fffdf70220de58509d0999555c7ba77 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 3 Mar 2017 11:02:41 +0100 Subject: [PATCH 02/80] [HttpFoundation] Fix Request::getHost() when having several hosts in X_FORWARDED_HOST --- src/Symfony/Component/HttpFoundation/Request.php | 6 +++--- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 697bc6c3c3e1..f549f8019eea 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -962,7 +962,7 @@ public function getPort() { if ($this->isFromTrustedProxy()) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { - return $port; + return (int) $port; } if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) { @@ -1211,9 +1211,9 @@ public function isSecure() public function getHost() { if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { - $elements = explode(',', $host); + $elements = explode(',', $host, 2); - $host = $elements[count($elements) - 1]; + $host = $elements[0]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 9000eb622b11..f23a5b439b5e 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1631,7 +1631,7 @@ public function testTrustedProxies() $request = Request::create('http://example.com/'); $request->server->set('REMOTE_ADDR', '3.3.3.3'); $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); - $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080'); + $request->headers->set('X_FORWARDED_HOST', 'foo.example.com:1234, real.example.com:8080'); $request->headers->set('X_FORWARDED_PROTO', 'https'); $request->headers->set('X_FORWARDED_PORT', 443); $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4'); @@ -1662,7 +1662,7 @@ public function testTrustedProxies() // trusted proxy via setTrustedProxies() Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); $this->assertEquals('1.1.1.1', $request->getClientIp()); - $this->assertEquals('real.example.com', $request->getHost()); + $this->assertEquals('foo.example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); From 0fb09293fd365a4a7912f9c37bb4e84734980b1a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 4 Mar 2017 12:27:34 +0100 Subject: [PATCH 03/80] context listener: hardening user provider handling --- .../Http/Firewall/ContextListener.php | 8 +- .../Tests/Firewall/ContextListenerTest.php | 104 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 9ac37cdf6d41..b443fa14881a 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -150,6 +150,8 @@ protected function refreshUser(TokenInterface $token) return $token; } + $userNotFoundByProvider = false; + foreach ($this->userProviders as $provider) { try { $refreshedUser = $provider->refreshUser($user); @@ -167,10 +169,14 @@ protected function refreshUser(TokenInterface $token) $this->logger->warning('Username could not be found in the selected user provider.', array('username' => $e->getUsername(), 'provider' => get_class($provider))); } - return; + $userNotFoundByProvider = true; } } + if ($userNotFoundByProvider) { + return; + } + throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user))); } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 15bc8bda692b..ba8edc3b1740 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -17,10 +17,17 @@ use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Exception\UnsupportedUserException; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\User\User; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Firewall\ContextListener; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -238,6 +245,40 @@ public function testHandleRemovesTokenIfNoPreviousSessionWasFound() $listener->handle($event); } + public function testTryAllUserProvidersUntilASupportingUserProviderIsFound() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + + public function testNextSupportingUserProviderIsTriedIfPreviousSupportingUserProviderDidNotLoadTheUser() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new SupportingUserProvider(), new SupportingUserProvider($refreshedUser))); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + + public function testTokenIsSetToNullIfNoUserWasLoadedByTheRegisteredUserProviders() + { + $tokenStorage = new TokenStorage(); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider())); + + $this->assertNull($tokenStorage->getToken()); + } + + /** + * @expectedException \RuntimeException + */ + public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegistered() + { + $this->handleEventWithPreviousSession(new TokenStorage(), array(new NotSupportingUserProvider(), new NotSupportingUserProvider())); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); @@ -265,4 +306,67 @@ protected function runSessionOnKernelResponse($newToken, $original = null) return $session; } + + private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, array $userProviders) + { + $session = new Session(new MockArraySessionStorage()); + $session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key'))); + + $request = new Request(); + $request->setSession($session); + $request->cookies->set('MOCKSESSID', true); + + $listener = new ContextListener($tokenStorage, $userProviders, 'context_key'); + $listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); + } +} + +class NotSupportingUserProvider implements UserProviderInterface +{ + public function loadUserByUsername($username) + { + throw new UsernameNotFoundException(); + } + + public function refreshUser(UserInterface $user) + { + throw new UnsupportedUserException(); + } + + public function supportsClass($class) + { + return false; + } +} + +class SupportingUserProvider implements UserProviderInterface +{ + private $refreshedUser; + + public function __construct(User $refreshedUser = null) + { + $this->refreshedUser = $refreshedUser; + } + + public function loadUserByUsername($username) + { + } + + public function refreshUser(UserInterface $user) + { + if (!$user instanceof User) { + throw new UnsupportedUserException(); + } + + if (null === $this->refreshedUser) { + throw new UsernameNotFoundException(); + } + + return $this->refreshedUser; + } + + public function supportsClass($class) + { + return 'Symfony\Component\Security\Core\User\User' === $class; + } } From f244eb84144c676460717020c334340d921ba9cc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 14:37:48 -0800 Subject: [PATCH 04/80] [HttpKernel] fixed Kernel name when stored in a directory starting with a number --- src/Symfony/Component/HttpKernel/Kernel.php | 3 ++ .../Tests/Fixtures/123/Kernel123.php | 37 +++++++++++++++++++ .../Component/HttpKernel/Tests/KernelTest.php | 8 ++++ 3 files changed, 48 insertions(+) create mode 100644 src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 97938af759be..06658930be2f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -302,6 +302,9 @@ public function getName() { if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); + if (ctype_digit($this->name[0])) { + $this->name = '_'.$this->name; + } } return $this->name; diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php new file mode 100644 index 000000000000..b6cf1cba20e7 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\_123; + +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Config\Loader\LoaderInterface; + +class Kernel123 extends Kernel +{ + public function registerBundles() + { + return array(); + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } + + public function getCacheDir() + { + return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/cache/'.$this->environment; + } + + public function getLogDir() + { + return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/logs'; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 8d4ebd7215db..dad52401daf3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -762,6 +762,14 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface() $kernel->terminate(Request::create('/'), new Response()); } + public function testKernelRootDirNameStartingWithANumber() + { + $dir = __DIR__.'/Fixtures/123'; + require_once $dir.'/Kernel123.php'; + $kernel = new \Symfony\Component\HttpKernel\Tests\Fixtures\_123\Kernel123('dev', true); + $this->assertEquals('_123', $kernel->getName()); + } + /** * Returns a mock for the BundleInterface. * From f90c78efe191e1d7011d84a6628fb403fe1d0ec1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 17:33:13 -0800 Subject: [PATCH 05/80] updated CHANGELOG for 2.7.25 --- CHANGELOG-2.7.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 776653657ee0..5e137e4366aa 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,34 @@ 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.25 (2017-03-06) + + * bug #21671 [Serializer] Xml encoder throws exception for valid data (gr1ev0us) + * bug #21805 Provide less state in getRequestFormat (dawehner) + * bug #21832 [Routing] Ignore hidden directories when loading routes from annotations (jakzal) + * bug #21769 [Form] Improve rounding precision (foaly-nr1) + * bug #21267 [Form] Fix ChoiceType to ensure submitted data is not nested unnecessarily (issei-m) + * bug #21731 Fix emacs link (rubenrua) + * bug #21800 Fix issues reported by static analyze (romainneutron) + * bug #21798 Revert "bug #21791 [SecurityBundle] only pass relevant user provider (xabbuh)" (xabbuh) + * bug #21791 [SecurityBundle] only pass relevant user provider (xabbuh) + * bug #21756 [Yaml] Stop replacing NULLs when merging (gadelat) + * bug #21722 [ExpressionLanguage] Registering functions after calling evaluate(), compile() or parse() is not supported (maidmaid) + * bug #21679 [SecurityBundle] fix priority ordering of security voters (xabbuh) + * bug #21115 [Validator] do not guess getter method names (xabbuh) + * bug #21661 Fix Composer constraints (fabpot) + * bug #21582 [HttpCache] purge both http and https from http cache (dbu) + * bug #21637 [FrameworkBundle] remove translation data collector when not usable (xabbuh) + * bug #21634 [VarDumper] Added missing persistent stream cast (lyrixx) + * bug #21436 [DependencyInjection] check for circular refs caused by method calls (xabbuh) + * bug #21400 [Serializer] fix upper camel case conversion (see #21399) (markusu49) + * bug #21599 [Console][Table] fixed render when using multiple rowspans. (aitboudad) + * bug #21613 [Process] Permit empty suffix on Windows (Bilge) + * bug #21057 [DI] Auto register extension configuration classes as a resource (ro0NL) + * bug #21592 [Validator] property constraints can be added in child classes (angelk, xabbuh) + * bug #21458 [Config] Early return for DirectoryResource (robfrawley) + * bug #21562 [DoctrineBridge] make sure that null can be the invalid value (xabbuh) + * 2.7.24 (2017-02-06) * bug #21063 [Form] Fixed DateType format option for single text widget (HeahDude) From 48c19f67e1630c0999caae131657509fe9a7fafb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 17:33:23 -0800 Subject: [PATCH 06/80] update CONTRIBUTORS for 2.7.25 --- CONTRIBUTORS.md | 76 ++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index dd5f4d109583..73387b9f7bb1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -29,34 +29,34 @@ Symfony is the result of the work of many people who made the code better - Grégoire Pineau (lyrixx) - Martin Hasoň (hason) - Jeremy Mikola (jmikola) + - Maxime Steinhausser (ogizanagi) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Maxime Steinhausser (ogizanagi) - - Eriksen Costa (eriksencosta) - Robin Chalas (chalas_r) + - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) - Alexandre Salomé (alexandresalome) - William Durand (couac) + - Guilhem Niot (energetick) - ornicar - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) - - Ener-Getick (energetick) + - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) + - Roland Franssen (ro0) - Miha Vrhovnik + - Iltar van der Berg (kjarli) - Diego Saint Esteben (dii3g0) - - Roland Franssen (ro0) - Konstantin Kudryashov (everzet) - - Iltar van der Berg (kjarli) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Peter Rehm (rpet) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) @@ -69,15 +69,15 @@ 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) - Titouan Galopin (tgalopin) + - Douglas Greenshields (shieldo) + - Pierre du Plessis (pierredup) - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - Graham Campbell (graham) - Daniel Holmes (dholmes) - - Pierre du Plessis (pierredup) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) @@ -91,14 +91,15 @@ Symfony is the result of the work of many people who made the code better - Jérôme Tamarelle (gromnan) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - Maxime STEINHAUSSER + - Issei Murasawa (issei_m) - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - marc.weistroff - - Issei Murasawa (issei_m) - lenar - Włodzimierz Gajda (gajdaw) - Baptiste Clavié (talus) - - Maxime STEINHAUSSER + - Vladimir Reznichenko (kalessil) - Alexander Schwenn (xelaris) - Florian Voutzinos (florianv) - Colin Frei @@ -106,20 +107,21 @@ Symfony is the result of the work of many people who made the code better - Adrien Brault (adrienbrault) - Joshua Thijssen - Peter Kokot (maastermedia) + - David Buchmann (dbu) - excelwebzone - Jacob Dreesen (jdreesen) - - Vladimir Reznichenko (kalessil) + - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) - - David Buchmann (dbu) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - - Tobias Nyholm (tobias) - Eric GELOEN (gelo) + - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - Stefano Sala (stefano.sala) + - Yonel Ceruto González (yonelceruto) - Evgeniy (ewgraf) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) @@ -127,7 +129,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Sebastiaan Stok (sstok) - - Yonel Ceruto González (yonelceruto) - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) @@ -155,10 +156,11 @@ Symfony is the result of the work of many people who made the code better - Jonathan Ingram (jonathaningram) - Artur Kotyrba - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) + - James Halsall (jaitsu) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Daniel Wehner + - Grégoire Paris (greg0ire) - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) @@ -171,6 +173,7 @@ Symfony is the result of the work of many people who made the code better - Lars Strojny (lstrojny) - Stepan Anchugov (kix) - bronze1man + - Daniel Espendiller - sun (sun) - Larry Garfield (crell) - Martin Schuhfuß (usefulthink) @@ -186,15 +189,14 @@ Symfony is the result of the work of many people who made the code better - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) - - James Halsall (jaitsu) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Chris Wilkinson (thewilkybarkid) + - Christian Schmidt - Michele Orselli (orso) - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Rui Marinho (ruimarinho) - - Daniel Espendiller - SpacePossum - Dawid Nowak - Eugene Wissner @@ -217,8 +219,9 @@ Symfony is the result of the work of many people who made the code better - Manuel Reinhard (sprain) - Danny Berger (dpb587) - Jérôme Vasseur + - Ruben Gonzalez (rubenrua) + - Adam Prager (padam87) - Roman Marintšenko (inori) - - Christian Schmidt - Xavier Montaña Carreras (xmontana) - Mickaël Andrieu (mickaelandrieu) - Xavier Perez @@ -233,12 +236,12 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto + - Julien Falque (julienfalque) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon - Jan Sorgalla (jsor) - Ray - - Grégoire Paris (greg0ire) - Leo Feyer - Chekote - Thomas Adam @@ -255,22 +258,20 @@ Symfony is the result of the work of many people who made the code better - Beau Simensen (simensen) - Michael Hirschler (mvhirsch) - Robert Kiss (kepten) - - Ruben Gonzalez (rubenrua) + - David Maicher (dmaicher) - Roumen Damianoff (roumen) - - Adam Prager (padam87) - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) - Wouter Van Hecke - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Marc Weistroff (futurecat) + - Christian Schmidt - Hidde Wieringa (hiddewie) - Chris Smith (cs278) - Florian Klein (docteurklein) - - Julien Falque (julienfalque) - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - - Daniel Wehner - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) @@ -310,10 +311,10 @@ Symfony is the result of the work of many people who made the code better - Magnus Nordlander (magnusnordlander) - alquerci - Francesco Levorato + - Rob Frawley 2nd (robfrawley) - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) - - David Maicher (dmaicher) - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Tomasz Kowalczyk (thunderer) @@ -341,6 +342,7 @@ Symfony is the result of the work of many people who made the code better - Vyacheslav Salakhutdinov (megazoll) - Jerzy Zawadzki (jzawadzki) - Hassan Amouhzi + - gadelat (gadelat) - Tamas Szijarto - Pavel Volokitin (pvolok) - François Pluchino (francoispluchino) @@ -396,13 +398,13 @@ Symfony is the result of the work of many people who made the code better - Asier Illarramendi (doup) - Chris Sedlmayr (catchamonkey) - Seb Koelen + - Dany Maillard (maidmaid) - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Dirk Pahl (dirkaholic) - cedric lombardot (cedriclombardot) - Jonas Flodén (flojon) - - Christian Schmidt - Amrouche Hamza - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) @@ -526,7 +528,6 @@ Symfony is the result of the work of many people who made the code better - Konstantin S. M. Möllers (ksmmoellers) - Sinan Eldem - Alexandre Dupuy (satchette) - - Rob Frawley 2nd - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) @@ -566,6 +567,7 @@ Symfony is the result of the work of many people who made the code better - Miquel Rodríguez Telep (mrtorrent) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski + - Denis Brumann (dbrumann) - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Ulumuddin Yunus (joenoez) @@ -684,6 +686,7 @@ Symfony is the result of the work of many people who made the code better - Abhoryo - Fabian Vogler (fabian) - Korvin Szanto + - Arjan Keeman - Alaattin Kahramanlar (alaattin) - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) @@ -779,6 +782,7 @@ Symfony is the result of the work of many people who made the code better - Phan Thanh Ha (haphan) - Chris Jones (leek) - Colin O'Dell (colinodell) + - Frank de Jonge (frenkynet) - xaav - Mahmoud Mostafa (mahmoud) - Alessandro Lai @@ -807,6 +811,7 @@ Symfony is the result of the work of many people who made the code better - mcfedr (mcfedr) - hamza - dantleech + - Bastien DURAND (deamon) - Xavier Leune - Tero Alén (tero) - DerManoMann @@ -832,7 +837,7 @@ Symfony is the result of the work of many people who made the code better - Nicolas Macherey - Lin Clark - Jeremy David (jeremy.david) - - Denis Brumann (dbrumann) + - Robin Lehrmann (robinlehrmann) - Troy McCabe - Ville Mattila - ilyes kooli @@ -845,6 +850,7 @@ Symfony is the result of the work of many people who made the code better - Sergey Novikov (s12v) - Marcos Quesada (marcos_quesada) - Matthew Vickery (mattvick) + - Angel Koilov (po_taka) - Dan Finnie - Ken Marfilla (marfillaster) - benatespina (benatespina) @@ -936,12 +942,14 @@ Symfony is the result of the work of many people who made the code better - Christian Sciberras - Clement Herreman (clemherreman) - Dan Ionut Dumitriu (danionut90) + - Vladislav Rastrusny (fractalizer) - Nyro (nyro) - Marco - Marc Torres - Alberto Aldegheri - heccjj - Alexandre Melard + - Jay Klehr - Sergey Yuferev - Tobias Stöckler - Mario Young @@ -999,6 +1007,7 @@ Symfony is the result of the work of many people who made the code better - Andy Raines - Anthony Ferrara - Klaas Cuvelier (kcuvelier) + - markusu49 - Steve Frécinaux - ShiraNai7 - Vašek Purchart (vasek-purchart) @@ -1024,6 +1033,7 @@ Symfony is the result of the work of many people who made the code better - Tom Corrigan (tomcorrigan) - Luis Galeas - Martin Pärtel + - George Mponos (gmponos) - Noah Heck (myesain) - Patrick Daley (padrig) - Xavier Briand (xavierbriand) @@ -1131,10 +1141,9 @@ Symfony is the result of the work of many people who made the code better - Leonid Terentyev (li0n) - ryunosuke - victoria - - Arjan Keeman - Francisco Facioni (fran6co) - Iwan van Staveren (istaveren) - - Dany Maillard (maidmaid) + - Thierry Thuon (lepiaf) - Povilas S. (povilas) - pborreli - Eric Caron @@ -1177,6 +1186,7 @@ Symfony is the result of the work of many people who made the code better - Dennis Væversted - nuncanada - flack + - izzyp - František Bereň - Christoph Nissle (derstoffel) - Ionel Scutelnicu (ionelscutelnicu) @@ -1243,6 +1253,7 @@ Symfony is the result of the work of many people who made the code better - Yannick Warnier (ywarnier) - Kevin Decherf - Jason Woods + - klemens - dened - Dmitry Korotovsky - Michael van Tricht @@ -1296,6 +1307,7 @@ Symfony is the result of the work of many people who made the code better - John Nickell (jrnickell) - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) + - Jonny Schmid (schmidjon) - Götz Gottwald - Veres Lajos - Michael Babker @@ -1361,10 +1373,12 @@ Symfony is the result of the work of many people who made the code better - Jelle Bekker (jbekker) - Ian Jenkins (jenkoian) - Jorge Martin (jorgemartind) + - Joeri Verdeyen (jverdeyen) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - Muriel (metalmumu) - Michael Pohlers (mick_the_big) + - mlpo (mlpo) - Cayetano Soriano Gallego (neoshadybeat) - Ondrej Machulda (ondram) - Pablo Monterde Perez (plebs) @@ -1424,6 +1438,7 @@ Symfony is the result of the work of many people who made the code better - Christian Eikermann - Antonio Angelino - Shawn Iwinski + - Niklas Keller - Vladimir Sazhin - lol768 - jamogon @@ -1512,6 +1527,7 @@ Symfony is the result of the work of many people who made the code better - Lin Lu - arduanov - sualko + - Bilge - Nicolas Roudaire - Alfonso (afgar) - Andreas Forsblom (aforsblo) @@ -1527,6 +1543,7 @@ Symfony is the result of the work of many people who made the code better - Choong Wei Tjeng (choonge) - Kousuke Ebihara (co3k) - Loïc Vernet (coil) + - Christian Gripp (core23) - Christoph Schaefer (cvschaefer) - Damon Jones (damon__jones) - Łukasz Giza (destroyer) @@ -1582,6 +1599,7 @@ Symfony is the result of the work of many people who made the code better - Bart Ruysseveldt (ruyss) - Sascha Dens (saschadens) - scourgen hung (scourgen) + - Sébastien Alfaiate (seb33300) - Sebastian Busch (sebu) - André Filipe Gonçalves Neves (seven) - Bruno Ziegler (sfcoder) From cb24ce3b526b0c65e592c6473c704626a8406881 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 17:33:35 -0800 Subject: [PATCH 07/80] updated VERSION for 2.7.25 --- 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 97938af759be..9e86920815d7 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.25-DEV'; + const VERSION = '2.7.25'; const VERSION_ID = 20725; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 25; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 7311ef36e9e7fdfe316f99aa16a5f538194ace72 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 18:34:03 -0800 Subject: [PATCH 08/80] bumped Symfony version to 2.7.26 --- 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 9e86920815d7..bd99b3bb4b4d 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.25'; - const VERSION_ID = 20725; + const VERSION = '2.7.26-DEV'; + const VERSION_ID = 20726; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 25; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 26; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 07dfac3bc2bda881928412f68fa35de6013d98c3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 5 Mar 2017 22:36:37 -0800 Subject: [PATCH 09/80] bumped Symfony version to 2.8.19 --- 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 b9c351a366b0..e75eea5a81c8 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.18'; - const VERSION_ID = 20818; + const VERSION = '2.8.19-DEV'; + const VERSION_ID = 20819; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 18; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 19; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 4013e7b9984eeabc0704853dc1df94066ef17442 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Mon, 6 Mar 2017 09:20:15 +0200 Subject: [PATCH 10/80] Add validate method to mockec validator in form TypeTestCase --- .../Form/Tests/Extension/Validator/Type/TypeTestCase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php index 663cdd03395d..cb6000aa8fb8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php @@ -23,6 +23,7 @@ protected function setUp() $this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $this->validator->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); + $this->validator->expects($this->any())->method('validate')->will($this->returnValue(array())); parent::setUp(); } From 040a9abdbfae6c4c068d7d4a202ccf2f87139e04 Mon Sep 17 00:00:00 2001 From: ChS Date: Wed, 1 Mar 2017 19:26:18 +0100 Subject: [PATCH 11/80] dumpFile(), preserve existing file permissions --- src/Symfony/Component/Filesystem/Filesystem.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index a1ff41e892b7..16d83dc2e5fe 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -516,7 +516,10 @@ public function dumpFile($filename, $content, $mode = 0666) } $this->chmod($tmpFile, $mode); + } else { + @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); } + $this->rename($tmpFile, $filename, true); } From 3a7cd08fe7bc628b4b896f40fd572b59af631d73 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 6 Mar 2017 19:56:39 +0100 Subject: [PATCH 12/80] respect the umask argument in dumpFile() --- src/Symfony/Component/Filesystem/Filesystem.php | 4 ++-- .../Component/Filesystem/Tests/FilesystemTest.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 16d83dc2e5fe..3a5e332b9ece 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -516,8 +516,8 @@ public function dumpFile($filename, $content, $mode = 0666) } $this->chmod($tmpFile, $mode); - } else { - @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); + } elseif (file_exists($filename)) { + @chmod($tmpFile, fileperms($filename)); } $this->rename($tmpFile, $filename, true); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 4f7457898b27..f879e641701e 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1050,6 +1050,19 @@ public function testDumpFileOverwritesAnExistingFile() $this->assertSame('bar', file_get_contents($filename)); } + public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile() + { + $this->markAsSkippedIfChmodIsMissing(); + + $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt'; + file_put_contents($filename, 'FOO BAR'); + chmod($filename, 0745); + + $this->filesystem->dumpFile($filename, 'bar', null); + + $this->assertFilePermissions(745, $filename); + } + public function testCopyShouldKeepExecutionPermission() { $this->markAsSkippedIfChmodIsMissing(); From cb452ee154fb144d73b70990e98d759dd19b87b8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Mar 2017 18:30:37 +0100 Subject: [PATCH 13/80] [github] Add a reminder about CHANGELOG.md files --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c9c3b7534055..d35bbdeb69e2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,10 @@ | Q | A | ------------- | --- -| Branch? | master / 2.7, 2.8 or 3.2 +| Branch? | master / 2.7, 2.8 or 3.2 | Bug fix? | yes/no -| New feature? | yes/no +| New feature? | yes/no | BC breaks? | yes/no -| Deprecations? | yes/no +| Deprecations? | yes/no | Tests pass? | yes/no | Fixed tickets | #... | License | MIT From 5107b94baf5ed50d84f0f7b3323283d585c4da41 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Mon, 6 Mar 2017 21:37:41 +0100 Subject: [PATCH 14/80] [Yaml] Fix the tests --- .../Component/Yaml/Tests/DumperTest.php | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index c27ac5cc5c70..6a1b3ac3d605 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -210,23 +210,25 @@ public function testEscapedEscapeSequencesInQuotedScalar($input, $expected) public function getEscapeSequences() { return array( - 'null' => array("\t\\0", '"\t\\\\0"'), - 'bell' => array("\t\\a", '"\t\\\\a"'), - 'backspace' => array("\t\\b", '"\t\\\\b"'), - 'horizontal-tab' => array("\t\\t", '"\t\\\\t"'), - 'line-feed' => array("\t\\n", '"\t\\\\n"'), - 'vertical-tab' => array("\t\\v", '"\t\\\\v"'), - 'form-feed' => array("\t\\f", '"\t\\\\f"'), - 'carriage-return' => array("\t\\r", '"\t\\\\r"'), - 'escape' => array("\t\\e", '"\t\\\\e"'), - 'space' => array("\t\\ ", '"\t\\\\ "'), - 'double-quote' => array("\t\\\"", '"\t\\\\\\""'), - 'slash' => array("\t\\/", '"\t\\\\/"'), - 'backslash' => array("\t\\\\", '"\t\\\\\\\\"'), - 'next-line' => array("\t\\N", '"\t\\\\N"'), - 'non-breaking-space' => array("\t\\�", '"\t\\\\�"'), - 'line-separator' => array("\t\\L", '"\t\\\\L"'), - 'paragraph-separator' => array("\t\\P", '"\t\\\\P"'), + 'empty string' => array('', "''"), + 'null' => array("\x0", '"\\0"'), + 'bell' => array("\x7", '"\\a"'), + 'backspace' => array("\x8", '"\\b"'), + 'horizontal-tab' => array("\t", '"\\t"'), + 'line-feed' => array("\n", '"\\n"'), + 'vertical-tab' => array("\v", '"\\v"'), + 'form-feed' => array("\xC", '"\\f"'), + 'carriage-return' => array("\r", '"\\r"'), + 'escape' => array("\x1B", '"\\e"'), + 'space' => array(' ', "' '"), + 'double-quote' => array('"', "'\"'"), + 'slash' => array('/', '/'), + 'backslash' => array('\\', '\\'), + 'next-line' => array("\xC2\x85", '"\\N"'), + 'non-breaking-space' => array("\xc2\xa0", '"\\_"'), + 'line-separator' => array("\xE2\x80\xA8", '"\\L"'), + 'paragraph-separator' => array("\xE2\x80\xA9", '"\\P"'), + 'colon' => array(':', "':'"), ); } From 069163906379792883b13312802444622a626bbd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 7 Mar 2017 19:22:12 +0100 Subject: [PATCH 15/80] [travis] Disable HHVM JIT - makes tests twice as fast --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 93ec75cd0a4e..473ef21ccfa1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,6 +50,8 @@ before_install: - if [[ ! $skip ]]; then echo date.timezone = Europe/Paris >> $INI_FILE; fi - if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi - if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi + - if [[ ! $skip ]]; then echo opcache.enable_cli = 1 >> $INI_FILE; fi + - if [[ ! $skip ]]; then echo hhvm.jit = 0 >> $INI_FILE; fi - if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi - if [[ ! $skip && $PHP = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi - if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.11 && echo apc.enable_cli = 1 >> $INI_FILE); fi From 7f1f0cb630889383ee22fa2f8b0e228f28066195 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 8 Mar 2017 10:04:21 +0100 Subject: [PATCH 16/80] [travis] Test with hhvm 3.18 --- .travis.yml | 2 +- .../Bundle/SecurityBundle/Tests/Functional/WebTestCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 473ef21ccfa1..088de9fec465 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ env: matrix: include: # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version - - php: hhvm-3.15 + - php: hhvm-3.18 sudo: required dist: trusty group: edge diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php index 33da9028a3da..da07116ae066 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php @@ -25,7 +25,7 @@ public static function assertRedirect($response, $location) protected static function deleteTmpDir($testCase) { - if (!file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) { + if (defined('HHVM_VERSION_ID') || !file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) { return; } From e3ac705b69585969f6eff6d977ab46ac40d9777e Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Wed, 8 Mar 2017 09:48:13 +0300 Subject: [PATCH 17/80] Rename StackOverflow to Stack Overflow --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36a466f2c8f0..1ec5983c5ca2 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Community --------- * [Join the Symfony Community][11] and meet other members at the [Symfony events][12]. -* [Get Symfony support][13] on StackOverflow, Slack, IRC, etc. +* [Get Symfony support][13] on Stack Overflow, Slack, IRC, etc. * Follow us on [GitHub][14], [Twitter][15] and [Facebook][16]. Contributing From ed211e9c74e50ec4eb3d7a78718563c06b59b17e Mon Sep 17 00:00:00 2001 From: Fred Cox Date: Thu, 9 Mar 2017 22:37:49 +0200 Subject: [PATCH 18/80] [Form] Choice type int values (BC Fix) --- .../Form/Extension/Core/Type/ChoiceType.php | 4 ++-- .../Tests/Extension/Core/Type/ChoiceTypeTest.php | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index b4b820ef263e..1392c81a59f9 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -171,8 +171,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) } foreach ($data as $v) { - if (null !== $v && !is_string($v)) { - throw new TransformationFailedException('All choices submitted must be NULL or strings.'); + if (null !== $v && !is_string($v) && !is_int($v)) { + throw new TransformationFailedException('All choices submitted must be NULL, strings or ints.'); } } }, 256); 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 b9097afdb61b..983397b09d62 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1689,6 +1689,19 @@ public function testSubmitMultipleExpandedNumericChoices() $this->assertNull($form[4]->getViewData()); } + public function testSubmitMultipleChoicesInts() + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'multiple' => true, + 'choices' => array_flip($this->numericChoicesFlipped), + 'choices_as_values' => true, + )); + + $form->submit(array(1, 2)); + + $this->assertTrue($form->isSynchronized()); + } + public function testSingleSelectedObjectChoices() { $view = $this->factory->create(static::TESTED_TYPE, $this->objectChoices[3], array( @@ -2306,7 +2319,7 @@ public function testSubmitInvalidNestedValue($multiple, $expanded, $submissionDa $form->submit($submissionData); $this->assertFalse($form->isSynchronized()); - $this->assertEquals('All choices submitted must be NULL or strings.', $form->getTransformationFailure()->getMessage()); + $this->assertEquals('All choices submitted must be NULL, strings or ints.', $form->getTransformationFailure()->getMessage()); } public function invalidNestedValueTestMatrix() From 870c26f39b757f8c5c6d332e4aa53a74b722bcbd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Mar 2017 23:26:11 +0100 Subject: [PATCH 19/80] [VarDumper] Add missing isset() checks in some casters --- .../VarDumper/Caster/ExceptionCaster.php | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index 25635399f7bd..b4fc87a275e2 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -67,11 +67,13 @@ public static function castThrowingCasterException(ThrowingCasterException $e, a if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace'])) { $b = (array) $a[$xPrefix.'previous']; - array_unshift($b[$xPrefix.'trace'], array( - 'function' => 'new '.get_class($a[$xPrefix.'previous']), - 'file' => $b[$prefix.'file'], - 'line' => $b[$prefix.'line'], - )); + if (isset($a[$prefix.'file'], $a[$prefix.'line'])) { + array_unshift($b[$xPrefix.'trace'], array( + 'function' => 'new '.get_class($a[$xPrefix.'previous']), + 'file' => $b[$prefix.'file'], + 'line' => $b[$prefix.'line'], + )); + } $a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -1 - count($a[$xPrefix.'trace']->value)); } @@ -234,11 +236,13 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte } if (!($filter & Caster::EXCLUDE_VERBOSE)) { - array_unshift($trace, array( - 'function' => $xClass ? 'new '.$xClass : null, - 'file' => $a[Caster::PREFIX_PROTECTED.'file'], - 'line' => $a[Caster::PREFIX_PROTECTED.'line'], - )); + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + array_unshift($trace, array( + 'function' => $xClass ? 'new '.$xClass : null, + 'file' => $a[Caster::PREFIX_PROTECTED.'file'], + 'line' => $a[Caster::PREFIX_PROTECTED.'line'], + )); + } $a[$xPrefix.'trace'] = new TraceStub($trace, self::$traceArgs); } if (empty($a[$xPrefix.'previous'])) { From 6831b984e114333bdee74357a293c89e1e279c28 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Mar 2017 17:00:52 +0100 Subject: [PATCH 20/80] [VarDumper] ExceptionCaster robustness fix --- src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index 8452590d63da..b6c0c28f50eb 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -64,7 +64,7 @@ public static function castThrowingCasterException(ThrowingCasterException $e, a $prefix = Caster::PREFIX_PROTECTED; $xPrefix = "\0Exception\0"; - if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace'][0])) { + if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace'][0]) && $a[$xPrefix.'previous'] instanceof \Exception) { $b = (array) $a[$xPrefix.'previous']; $b[$xPrefix.'trace'][0] += array( 'file' => $b[$prefix.'file'], From 33946e69c0a322fa1aa721aed26488bf2c5098c8 Mon Sep 17 00:00:00 2001 From: Julien Falque Date: Sun, 12 Mar 2017 23:37:52 +0100 Subject: [PATCH 21/80] Use proper line endings --- src/Symfony/Component/Console/Output/BufferedOutput.php | 2 +- src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Output/BufferedOutput.php b/src/Symfony/Component/Console/Output/BufferedOutput.php index 5682fc2404f7..205b02f5fd5d 100644 --- a/src/Symfony/Component/Console/Output/BufferedOutput.php +++ b/src/Symfony/Component/Console/Output/BufferedOutput.php @@ -42,7 +42,7 @@ protected function doWrite($message, $newline) $this->buffer .= $message; if ($newline) { - $this->buffer .= "\n"; + $this->buffer .= PHP_EOL; } } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php b/src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php index 0070c0a48676..866e21437177 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php +++ b/src/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php @@ -26,7 +26,7 @@ class DummyOutput extends BufferedOutput public function getLogs() { $logs = array(); - foreach (explode("\n", trim($this->fetch())) as $message) { + foreach (explode(PHP_EOL, trim($this->fetch())) as $message) { preg_match('/^\[(.*)\] (.*)/', $message, $matches); $logs[] = sprintf('%s %s', $matches[1], $matches[2]); } From 4842c86324a64d12a903dd2d712977eb132b2718 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Mar 2017 23:00:00 +0100 Subject: [PATCH 22/80] [FrameworkBundle] Fix cleaning of test dirs --- .../Tests/Functional/SessionTest.php | 14 ----------- .../Tests/Functional/WebTestCase.php | 23 +++++++++++++++---- .../Tests/Functional/app/AppKernel.php | 12 ++++++---- .../Tests/Functional/CsrfFormLoginTest.php | 10 -------- .../Functional/FirewallEntryPointTest.php | 10 -------- .../Tests/Functional/FormLoginTest.php | 10 -------- .../Functional/LocalizedRoutesAsPathTest.php | 10 -------- .../SecurityRoutingIntegrationTest.php | 10 -------- .../Tests/Functional/SetAclCommandTest.php | 14 ----------- .../Tests/Functional/SwitchUserTest.php | 10 -------- .../Tests/Functional/WebTestCase.php | 23 +++++++++++++++---- .../Tests/Functional/app/AppKernel.php | 14 ++++++----- 12 files changed, 53 insertions(+), 107 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php index 415e031189c3..166d8a33919d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php @@ -134,18 +134,4 @@ public function getConfigs() array('config.yml', false), ); } - - protected function setUp() - { - parent::setUp(); - - $this->deleteTmpDir('SessionTest'); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->deleteTmpDir('SessionTest'); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php index 50d4cfa4db26..2861297fe025 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php @@ -13,7 +13,6 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\HttpKernel\Kernel; class WebTestCase extends BaseWebTestCase { @@ -23,9 +22,19 @@ public static function assertRedirect($response, $location) self::assertEquals('http://localhost'.$location, $response->headers->get('Location')); } - protected function deleteTmpDir($testCase) + public static function setUpBeforeClass() { - if (!file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) { + static::deleteTmpDir(); + } + + public static function tearDownAfterClass() + { + static::deleteTmpDir(); + } + + protected static function deleteTmpDir() + { + if (!file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) { return; } @@ -49,10 +58,16 @@ protected static function createKernel(array $options = array()) } return new $class( + static::getVarDir(), $options['test_case'], isset($options['root_config']) ? $options['root_config'] : 'config.yml', - isset($options['environment']) ? $options['environment'] : 'frameworkbundletest'.strtolower($options['test_case']), + isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']), isset($options['debug']) ? $options['debug'] : true ); } + + protected static function getVarDir() + { + return substr(strrchr(get_called_class(), '\\'), 1); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php index b07d44fe22be..8e14b53a7472 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php @@ -46,14 +46,16 @@ */ class AppKernel extends Kernel { + private $varDir; private $testCase; private $rootConfig; - public function __construct($testCase, $rootConfig, $environment, $debug) + public function __construct($varDir, $testCase, $rootConfig, $environment, $debug) { if (!is_dir(__DIR__.'/'.$testCase)) { throw new \InvalidArgumentException(sprintf('The test case "%s" does not exist.', $testCase)); } + $this->varDir = $varDir; $this->testCase = $testCase; $fs = new Filesystem(); @@ -81,12 +83,12 @@ public function getRootDir() public function getCacheDir() { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/cache/'.$this->environment; + return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/cache/'.$this->environment; } public function getLogDir() { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/logs'; + return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/logs'; } public function registerContainerConfiguration(LoaderInterface $loader) @@ -96,13 +98,13 @@ public function registerContainerConfiguration(LoaderInterface $loader) public function serialize() { - return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug())); + return serialize(array($this->varDir, $this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug())); } public function unserialize($str) { $a = unserialize($str); - $this->__construct($a[0], $a[1], $a[2], $a[3]); + $this->__construct($a[0], $a[1], $a[2], $a[3], $a[4]); } protected function getKernelParameters() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php index 80211f5251b0..2d95d3506513 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php @@ -108,14 +108,4 @@ public function getConfigs() array('routes_as_path.yml'), ); } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('CsrfFormLogin'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('CsrfFormLogin'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php index 30d0935ffddd..8179c2e942a6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php @@ -43,14 +43,4 @@ public function testItUsesTheConfiguredEntryPointFromTheExceptionListenerWithFor "Custom entry point wasn't started" ); } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('FirewallEntryPoint'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('FirewallEntryPoint'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php index 2f19f3f8a1a9..c2e766e9acca 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php @@ -113,14 +113,4 @@ public function getConfigs() array('routes_as_path.yml'), ); } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php index 14c317966e21..cb600764eaf4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php @@ -76,14 +76,4 @@ public function getLocales() { return array(array('en'), array('de')); } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php index c7db437819a1..3abfd9585f15 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php @@ -116,14 +116,4 @@ public function getConfigs() { return array(array('config.yml'), array('routes_as_path.yml')); } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index db4c51c5f064..039a5b325bad 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -40,20 +40,6 @@ class SetAclCommandTest extends WebTestCase const OBJECT_CLASS = 'Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\Entity\Car'; const SECURITY_CLASS = 'Symfony\Component\Security\Core\User\User'; - protected function setUp() - { - parent::setUp(); - - $this->deleteTmpDir('Acl'); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->deleteTmpDir('Acl'); - } - public function testSetAclUser() { $objectId = 1; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index e5079c3283aa..f12e95671be2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -70,14 +70,4 @@ protected function createAuthenticatedClient($username) return $client; } - - public static function setUpBeforeClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } - - public static function tearDownAfterClass() - { - parent::deleteTmpDir('StandardFormLogin'); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php index da07116ae066..8bace799a37a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php @@ -13,7 +13,6 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\HttpKernel\Kernel; class WebTestCase extends BaseWebTestCase { @@ -23,9 +22,19 @@ public static function assertRedirect($response, $location) self::assertEquals('http://localhost'.$location, $response->headers->get('Location')); } - protected static function deleteTmpDir($testCase) + public static function setUpBeforeClass() { - if (defined('HHVM_VERSION_ID') || !file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) { + static::deleteTmpDir(); + } + + public static function tearDownAfterClass() + { + static::deleteTmpDir(); + } + + protected static function deleteTmpDir() + { + if (!file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) { return; } @@ -49,10 +58,16 @@ protected static function createKernel(array $options = array()) } return new $class( + static::getVarDir(), $options['test_case'], isset($options['root_config']) ? $options['root_config'] : 'config.yml', - isset($options['environment']) ? $options['environment'] : 'securitybundletest'.strtolower($options['test_case']), + isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']), isset($options['debug']) ? $options['debug'] : true ); } + + protected static function getVarDir() + { + return substr(strrchr(get_called_class(), '\\'), 1); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php index b828c5acfd91..c448b7c172d6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php @@ -46,14 +46,16 @@ */ class AppKernel extends Kernel { + private $varDir; private $testCase; private $rootConfig; - public function __construct($testCase, $rootConfig, $environment, $debug) + public function __construct($varDir, $testCase, $rootConfig, $environment, $debug) { if (!is_dir(__DIR__.'/'.$testCase)) { throw new \InvalidArgumentException(sprintf('The test case "%s" does not exist.', $testCase)); } + $this->varDir = $varDir; $this->testCase = $testCase; $fs = new Filesystem(); @@ -71,7 +73,7 @@ public function __construct($testCase, $rootConfig, $environment, $debug) public function getName() { if (null === $this->name) { - $this->name = parent::getName().md5($this->rootConfig); + $this->name = parent::getName().substr(md5($this->rootConfig), -16); } return $this->name; @@ -93,12 +95,12 @@ public function getRootDir() public function getCacheDir() { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/cache/'.$this->environment; + return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/cache/'.$this->environment; } public function getLogDir() { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/logs'; + return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/logs'; } public function registerContainerConfiguration(LoaderInterface $loader) @@ -108,13 +110,13 @@ public function registerContainerConfiguration(LoaderInterface $loader) public function serialize() { - return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug())); + return serialize(array($this->varDir, $this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug())); } public function unserialize($str) { $a = unserialize($str); - $this->__construct($a[0], $a[1], $a[2], $a[3]); + $this->__construct($a[0], $a[1], $a[2], $a[3], $a[4]); } protected function getKernelParameters() From 86e8afaea0fc3361b7da12d82ce6b62596ca6a2b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 14 Mar 2017 09:04:19 +0100 Subject: [PATCH 23/80] [Validator] revert wrong Phpdoc change --- src/Symfony/Component/Validator/Mapping/ClassMetadata.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index fe5e6e51e2ec..f895ad40402d 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -299,9 +299,8 @@ public function addPropertyConstraints($property, array $constraints) * The name of the getter is assumed to be the name of the property with an * uppercased first letter and either the prefix "get" or "is". * - * @param string $property The name of the property - * @param Constraint $constraint The constraint - * @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection) + * @param string $property The name of the property + * @param Constraint $constraint The constraint * * @return $this */ From 405bd4cc81effce9fd24b9c81e8383c4b5337c5a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 14 Mar 2017 12:32:10 +0100 Subject: [PATCH 24/80] Use PHP functions as array_map callbacks when possible --- .../Tests/DependencyInjection/FrameworkExtensionTest.php | 2 +- .../Tests/DependencyInjection/CompleteConfigurationTest.php | 2 +- src/Symfony/Component/Finder/Tests/FinderTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index bc1eac93e6da..a782a3f0748b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -224,7 +224,7 @@ public function testTranslator() $this->assertEquals('translator.default', (string) $container->getAlias('translator'), '->registerTranslatorConfiguration() redefines translator service from identity to real translator'); $options = $container->getDefinition('translator.default')->getArgument(3); - $files = array_map(function ($resource) { return realpath($resource); }, $options['resource_files']['en']); + $files = array_map('realpath', $options['resource_files']['en']); $ref = new \ReflectionClass('Symfony\Component\Validator\Validation'); $this->assertContains( strtr(dirname($ref->getFileName()).'/Resources/translations/validators.en.xlf', '/', DIRECTORY_SEPARATOR), diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index ebb22fddac83..d273fb05942b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -73,7 +73,7 @@ public function testFirewalls() foreach (array_keys($arguments[1]) as $contextId) { $contextDef = $container->getDefinition($contextId); $arguments = $contextDef->getArguments(); - $listeners[] = array_map(function ($ref) { return (string) $ref; }, $arguments['index_0']); + $listeners[] = array_map('strval', $arguments['index_0']); } $this->assertEquals(array( diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 28bb4dbdbb69..f445c79c5ef2 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -317,7 +317,7 @@ public function testGetIterator() $finder = $this->buildFinder(); $a = iterator_to_array($finder->directories()->in(self::$tmpDir)); - $a = array_values(array_map(function ($a) { return (string) $a; }, $a)); + $a = array_values(array_map('strval', $a)); sort($a); $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface'); } From 9d9d4efb88539b32413d6ac51e9639a0295502cc Mon Sep 17 00:00:00 2001 From: David Maicher Date: Tue, 14 Mar 2017 21:52:39 +0100 Subject: [PATCH 25/80] [Doctrine Bridge] fix priority for doctrine event listeners --- ...gisterEventListenersAndSubscribersPass.php | 168 ++++++++++-------- ...erEventListenersAndSubscribersPassTest.php | 156 ++++++++++++---- 2 files changed, 210 insertions(+), 114 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index 94f72fd8c8c0..1ec3ba323b78 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -11,27 +11,30 @@ namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Registers event listeners and subscribers to the available doctrine connections. * * @author Jeremy Mikola * @author Alexander + * @author David Maicher */ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface { + /** + * @var string|string[] + */ private $connections; - private $container; private $eventManagers; private $managerTemplate; private $tagPrefix; /** - * Constructor. - * * @param string $connections Parameter ID for connections * @param string $managerTemplate sprintf() template for generating the event * manager's service ID for a connection name @@ -53,105 +56,112 @@ public function process(ContainerBuilder $container) return; } - $taggedSubscribers = $container->findTaggedServiceIds($this->tagPrefix.'.event_subscriber'); - $taggedListeners = $container->findTaggedServiceIds($this->tagPrefix.'.event_listener'); - - if (empty($taggedSubscribers) && empty($taggedListeners)) { - return; - } - - $this->container = $container; $this->connections = $container->getParameter($this->connections); - $sortFunc = function ($a, $b) { - $a = isset($a['priority']) ? $a['priority'] : 0; - $b = isset($b['priority']) ? $b['priority'] : 0; - - return $a > $b ? -1 : 1; - }; + $this->addTaggedSubscribers($container); + $this->addTaggedListeners($container); + } - if (!empty($taggedSubscribers)) { - $subscribersPerCon = $this->groupByConnection($taggedSubscribers); - foreach ($subscribersPerCon as $con => $subscribers) { - $em = $this->getEventManager($con); + private function addTaggedSubscribers(ContainerBuilder $container) + { + $subscriberTag = $this->tagPrefix.'.event_subscriber'; + $taggedSubscribers = $this->findAndSortTags($subscriberTag, $container); - uasort($subscribers, $sortFunc); - foreach ($subscribers as $id => $instance) { - if ($container->getDefinition($id)->isAbstract()) { - throw new \InvalidArgumentException(sprintf('The abstract service "%s" cannot be tagged as a doctrine event subscriber.', $id)); - } + foreach ($taggedSubscribers as $taggedSubscriber) { + $id = $taggedSubscriber[0]; + $taggedSubscriberDef = $container->getDefinition($id); - $em->addMethodCall('addEventSubscriber', array(new Reference($id))); - } + if ($taggedSubscriberDef->isAbstract()) { + throw new InvalidArgumentException(sprintf('The abstract service "%s" cannot be tagged as a doctrine event subscriber.', $id)); } - } - if (!empty($taggedListeners)) { - $listenersPerCon = $this->groupByConnection($taggedListeners, true); - foreach ($listenersPerCon as $con => $listeners) { - $em = $this->getEventManager($con); - - uasort($listeners, $sortFunc); - foreach ($listeners as $id => $instance) { - if ($container->getDefinition($id)->isAbstract()) { - throw new \InvalidArgumentException(sprintf('The abstract service "%s" cannot be tagged as a doctrine event listener.', $id)); - } - - $em->addMethodCall('addEventListener', array( - array_unique($instance['event']), - isset($instance['lazy']) && $instance['lazy'] ? $id : new Reference($id), - )); + $tag = $taggedSubscriber[1]; + $connections = isset($tag['connection']) ? array($tag['connection']) : array_keys($this->connections); + foreach ($connections as $con) { + if (!isset($this->connections[$con])) { + throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $taggedSubscriber, implode(', ', array_keys($this->connections)))); } + + $this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', array(new Reference($id))); } } } - private function groupByConnection(array $services, $isListener = false) + private function addTaggedListeners(ContainerBuilder $container) { - $grouped = array(); - foreach ($allCons = array_keys($this->connections) as $con) { - $grouped[$con] = array(); - } + $listenerTag = $this->tagPrefix.'.event_listener'; + $taggedListeners = $this->findAndSortTags($listenerTag, $container); + + foreach ($taggedListeners as $taggedListener) { + $id = $taggedListener[0]; + $taggedListenerDef = $container->getDefinition($taggedListener[0]); + if ($taggedListenerDef->isAbstract()) { + throw new InvalidArgumentException(sprintf('The abstract service "%s" cannot be tagged as a doctrine event listener.', $id)); + } - foreach ($services as $id => $instances) { - foreach ($instances as $instance) { - if ($isListener) { - if (!isset($instance['event'])) { - throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); - } - $instance['event'] = array($instance['event']); - - if (isset($instance['lazy']) && $instance['lazy']) { - $this->container->getDefinition($id)->setPublic(true); - } + $tag = $taggedListener[1]; + if (!isset($tag['event'])) { + throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); + } + + $connections = isset($tag['connection']) ? array($tag['connection']) : array_keys($this->connections); + foreach ($connections as $con) { + if (!isset($this->connections[$con])) { + throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); } - $cons = isset($instance['connection']) ? array($instance['connection']) : $allCons; - foreach ($cons as $con) { - if (!isset($grouped[$con])) { - throw new \RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); - } - - if ($isListener && isset($grouped[$con][$id])) { - $grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']); - } else { - $grouped[$con][$id] = $instance; - } + if ($lazy = isset($tag['lazy']) && $tag['lazy']) { + $taggedListenerDef->setPublic(true); } + + // we add one call per event per service so we have the correct order + $this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array( + $tag['event'], + $lazy ? $id : new Reference($id), + )); } } + } - return $grouped; + private function getEventManagerDef(ContainerBuilder $container, $name) + { + if (!isset($this->eventManagers[$name])) { + $this->eventManagers[$name] = $container->getDefinition(sprintf($this->managerTemplate, $name)); + } + + return $this->eventManagers[$name]; } - private function getEventManager($name) + /** + * Finds and orders all service tags with the given name by their priority. + * + * The order of additions must be respected for services having the same priority, + * and knowing that the \SplPriorityQueue class does not respect the FIFO method, + * we should not use this class. + * + * @see https://bugs.php.net/bug.php?id=53710 + * @see https://bugs.php.net/bug.php?id=60926 + * + * @param string $tagName + * @param ContainerBuilder $container + * + * @return array + */ + private function findAndSortTags($tagName, ContainerBuilder $container) { - if (null === $this->eventManagers) { - $this->eventManagers = array(); - foreach ($this->connections as $n => $id) { - $this->eventManagers[$n] = $this->container->getDefinition(sprintf($this->managerTemplate, $n)); + $sortedTags = array(); + + foreach ($container->findTaggedServiceIds($tagName) as $serviceId => $tags) { + foreach ($tags as $attributes) { + $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; + $sortedTags[$priority][] = array($serviceId, $attributes); } } - return $this->eventManagers[$name]; + if ($sortedTags) { + krsort($sortedTags); + $sortedTags = call_user_func_array('array_merge', $sortedTags); + } + + return $sortedTags; } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php index ba73678541e7..4f196f2ca6a2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php @@ -14,6 +14,7 @@ use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_TestCase { @@ -55,12 +56,18 @@ public function testProcessEventListenersWithPriorities() $container ->register('a', 'stdClass') + ->setPublic(false) + ->addTag('doctrine.event_listener', array( + 'event' => 'bar', + )) ->addTag('doctrine.event_listener', array( 'event' => 'foo', 'priority' => -5, )) ->addTag('doctrine.event_listener', array( - 'event' => 'bar', + 'event' => 'foo_bar', + 'priority' => 3, + 'lazy' => true, )) ; $container @@ -69,12 +76,34 @@ public function testProcessEventListenersWithPriorities() 'event' => 'foo', )) ; + $container + ->register('c', 'stdClass') + ->addTag('doctrine.event_listener', array( + 'event' => 'foo_bar', + 'priority' => 4, + )) + ; $this->process($container); - $this->assertEquals(array('b', 'a'), $this->getServiceOrder($container, 'addEventListener')); - - $calls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls(); - $this->assertEquals(array('foo', 'bar'), $calls[1][1][0]); + $methodCalls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls(); + + $this->assertEquals( + array( + array('addEventListener', array('foo_bar', new Reference('c'))), + array('addEventListener', array('foo_bar', new Reference('a'))), + array('addEventListener', array('bar', new Reference('a'))), + array('addEventListener', array('foo', new Reference('b'))), + array('addEventListener', array('foo', new Reference('a'))), + ), + $methodCalls + ); + + // not lazy so must be reference + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $methodCalls[0][1][1]); + + // lazy so id instead of reference and must mark service public + $this->assertSame('a', $methodCalls[1][1][1]); + $this->assertTrue($container->getDefinition('a')->isPublic()); } public function testProcessEventListenersWithMultipleConnections() @@ -87,15 +116,86 @@ public function testProcessEventListenersWithMultipleConnections() 'event' => 'onFlush', )) ; + + $container + ->register('b', 'stdClass') + ->addTag('doctrine.event_listener', array( + 'event' => 'onFlush', + 'connection' => 'default', + )) + ; + + $container + ->register('c', 'stdClass') + ->addTag('doctrine.event_listener', array( + 'event' => 'onFlush', + 'connection' => 'second', + )) + ; + $this->process($container); - $callsDefault = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls(); + $this->assertEquals( + array( + array('addEventListener', array('onFlush', new Reference('a'))), + array('addEventListener', array('onFlush', new Reference('b'))), + ), + $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() + ); + + $this->assertEquals( + array( + array('addEventListener', array('onFlush', new Reference('a'))), + array('addEventListener', array('onFlush', new Reference('c'))), + ), + $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls() + ); + } - $this->assertEquals('addEventListener', $callsDefault[0][0]); - $this->assertEquals(array('onFlush'), $callsDefault[0][1][0]); + public function testProcessEventSubscribersWithMultipleConnections() + { + $container = $this->createBuilder(true); - $callsSecond = $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls(); - $this->assertEquals($callsDefault, $callsSecond); + $container + ->register('a', 'stdClass') + ->addTag('doctrine.event_subscriber', array( + 'event' => 'onFlush', + )) + ; + + $container + ->register('b', 'stdClass') + ->addTag('doctrine.event_subscriber', array( + 'event' => 'onFlush', + 'connection' => 'default', + )) + ; + + $container + ->register('c', 'stdClass') + ->addTag('doctrine.event_subscriber', array( + 'event' => 'onFlush', + 'connection' => 'second', + )) + ; + + $this->process($container); + + $this->assertEquals( + array( + array('addEventSubscriber', array(new Reference('a'))), + array('addEventSubscriber', array(new Reference('b'))), + ), + $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() + ); + + $this->assertEquals( + array( + array('addEventSubscriber', array(new Reference('a'))), + array('addEventSubscriber', array(new Reference('c'))), + ), + $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls() + ); } public function testProcessEventSubscribersWithPriorities() @@ -132,11 +232,17 @@ public function testProcessEventSubscribersWithPriorities() ; $this->process($container); - $serviceOrder = $this->getServiceOrder($container, 'addEventSubscriber'); - $unordered = array_splice($serviceOrder, 0, 3); - sort($unordered); - $this->assertEquals(array('c', 'd', 'e'), $unordered); - $this->assertEquals(array('b', 'a'), $serviceOrder); + + $this->assertEquals( + array( + array('addEventSubscriber', array(new Reference('c'))), + array('addEventSubscriber', array(new Reference('d'))), + array('addEventSubscriber', array(new Reference('e'))), + array('addEventSubscriber', array(new Reference('b'))), + array('addEventSubscriber', array(new Reference('a'))), + ), + $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() + ); } public function testProcessNoTaggedServices() @@ -156,26 +262,6 @@ private function process(ContainerBuilder $container) $pass->process($container); } - private function getServiceOrder(ContainerBuilder $container, $method) - { - $order = array(); - foreach ($container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() as $call) { - list($name, $arguments) = $call; - if ($method !== $name) { - continue; - } - - if ('addEventListener' === $name) { - $order[] = (string) $arguments[1]; - continue; - } - - $order[] = (string) $arguments[0]; - } - - return $order; - } - private function createBuilder($multipleConnections = false) { $container = new ContainerBuilder(); From 522ec3ef0c71707a98c46e0ae7d56d8fb0f88427 Mon Sep 17 00:00:00 2001 From: Dmytro Boiko Date: Thu, 16 Mar 2017 00:00:25 +0200 Subject: [PATCH 26/80] [Security] Added option to return true in the method isRememberMeRequested --- .../Security/Http/RememberMe/AbstractRememberMeServices.php | 2 +- .../Http/Tests/RememberMe/AbstractRememberMeServicesTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index cd8640d03a13..4ab3465c6626 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -318,6 +318,6 @@ protected function isRememberMeRequested(Request $request) $this->logger->debug('Did not send remember-me cookie.', array('parameter' => $this->options['remember_me_parameter'])); } - return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes'; + return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes' || $parameter === true; } } diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php index 386927e3d50b..1850d093dd4f 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php @@ -251,6 +251,7 @@ public function getPositiveRememberMeParameterValues() array('1'), array('on'), array('yes'), + array(true), ); } From 5af47c40dc6767f19185f1340037bc1c65e724c5 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 16 Mar 2017 17:10:10 +0100 Subject: [PATCH 27/80] Revert "bug #21841 [Console] Do not squash input changes made from console.command event (chalasr)" This reverts commit b8b6774634512e66b45e33f5f598cf14865701e4, reversing changes made to 82790559de7b53b1e11814a964733ccb68a736d1. --- src/Symfony/Component/Console/Application.php | 4 --- .../Component/Console/Command/Command.php | 21 ++++------------ .../Console/Tests/ApplicationTest.php | 25 ------------------- 3 files changed, 5 insertions(+), 45 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index d069da03bc06..bd340d3078f7 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -859,10 +859,6 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition } - // don't bind the input again as it would override any input argument/option set from the command event in - // addition to being useless - $command->setInputBound(true); - $event = new ConsoleCommandEvent($command, $input, $output); $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index fd0376c22d02..39a1f6e8444b 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -42,7 +42,6 @@ class Command private $ignoreValidationErrors = false; private $applicationDefinitionMerged = false; private $applicationDefinitionMergedWithArgs = false; - private $inputBound = false; private $code; private $synopsis = array(); private $usages = array(); @@ -219,13 +218,11 @@ public function run(InputInterface $input, OutputInterface $output) $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options - if (!$this->inputBound) { - try { - $input->bind($this->definition); - } catch (ExceptionInterface $e) { - if (!$this->ignoreValidationErrors) { - throw $e; - } + try { + $input->bind($this->definition); + } catch (ExceptionInterface $e) { + if (!$this->ignoreValidationErrors) { + throw $e; } } @@ -681,14 +678,6 @@ public function asXml($asDom = false) return $output->fetch(); } - /** - * @internal - */ - public function setInputBound($inputBound) - { - $this->inputBound = $inputBound; - } - /** * Validates a command name. * diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 3cec084e6973..cd52617a5ac5 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1113,31 +1113,6 @@ public function testRunWithDispatcherAddingInputOptions() $this->assertEquals('some test value', $extraValue); } - public function testUpdateInputFromConsoleCommandEvent() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) { - $event->getInput()->setOption('extra', 'overriden'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application - ->register('foo') - ->addOption('extra', null, InputOption::VALUE_REQUIRED) - ->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }) - ; - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo', '--extra' => 'original')); - - $this->assertEquals('overriden', $tester->getInput()->getOption('extra')); - } - public function testTerminalDimensions() { $application = new Application(); From c9a1c091829e5791c743ee2ec05f8272fd95bfed Mon Sep 17 00:00:00 2001 From: Richard Bradley Date: Fri, 3 Feb 2017 16:27:28 +0000 Subject: [PATCH 28/80] #20411 fix Yaml parsing for very long quoted strings --- src/Symfony/Component/Yaml/Inline.php | 16 ++-- src/Symfony/Component/Yaml/Parser.php | 88 ++++++++++++------- .../Component/Yaml/Tests/ParserTest.php | 12 +++ 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index aa1833745a95..2255379a974c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -149,8 +149,8 @@ public static function dump($value, $exceptionOnInvalidType = false, $objectSupp case Escaper::requiresDoubleQuoting($value): return Escaper::escapeWithDoubleQuotes($value); case Escaper::requiresSingleQuoting($value): - case preg_match(self::getHexRegex(), $value): - case preg_match(self::getTimestampRegex(), $value): + case Parser::preg_match(self::getHexRegex(), $value): + case Parser::preg_match(self::getTimestampRegex(), $value): return Escaper::escapeWithSingleQuotes($value); default: return $value; @@ -242,10 +242,10 @@ public static function parseScalar($scalar, $delimiters = null, $stringDelimiter $i += strlen($output); // remove comments - if (preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { + if (Parser::preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { $output = substr($output, 0, $match[0][1]); } - } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { + } elseif (Parser::preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += strlen($output); } else { @@ -272,7 +272,7 @@ public static function parseScalar($scalar, $delimiters = null, $stringDelimiter */ private static function parseQuotedScalar($scalar, &$i) { - if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { + if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i))); } @@ -520,16 +520,16 @@ private static function evaluateScalar($scalar, $references = array()) return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw === (string) $cast) ? $cast : $raw); case is_numeric($scalar): - case preg_match(self::getHexRegex(), $scalar): + case Parser::preg_match(self::getHexRegex(), $scalar): return '0x' === $scalar[0].$scalar[1] ? hexdec($scalar) : (float) $scalar; case '.inf' === $scalarLower: case '.nan' === $scalarLower: return -log(0); case '-.inf' === $scalarLower: return log(0); - case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): + case Parser::preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): return (float) str_replace(',', '', $scalar); - case preg_match(self::getTimestampRegex(), $scalar): + case Parser::preg_match(self::getTimestampRegex(), $scalar): $timeZone = date_default_timezone_get(); date_default_timezone_set('UTC'); $time = strtotime($scalar); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index f3528ba24fae..c4f5144468fa 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -61,7 +61,7 @@ public function __construct($offset = 0, $totalNumberOfLines = null, array $skip */ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false) { - if (!preg_match('//u', $value)) { + if (false === preg_match('//u', $value)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } $this->currentLineNb = -1; @@ -92,13 +92,13 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = } $isRef = $mergeNode = false; - if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) { + if (self::preg_match('#^\-((?P\s+)(?P.+))?$#u', rtrim($this->currentLine), $values)) { if ($context && 'mapping' == $context) { throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine); } $context = 'sequence'; - if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { + if (isset($values['value']) && self::preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } @@ -108,7 +108,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap); } else { if (isset($values['leadspaces']) - && preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+?))?\s*$#u', $values['value'], $matches) + && self::preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+))?$#u', rtrim($values['value']), $matches) ) { // this is a compact notation element, add to next block and parse $block = $values['value']; @@ -124,7 +124,10 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = if ($isRef) { $this->refs[$isRef] = end($data); } - } elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) { + } elseif ( + self::preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+))?$#u', rtrim($this->currentLine), $values) + && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'"))) + ) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine); } @@ -203,7 +206,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = } } } - } elseif (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { + } elseif (isset($values['value']) && self::preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } @@ -266,27 +269,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = return $value; } - switch (preg_last_error()) { - case PREG_INTERNAL_ERROR: - $error = 'Internal PCRE error.'; - break; - case PREG_BACKTRACK_LIMIT_ERROR: - $error = 'pcre.backtrack_limit reached.'; - break; - case PREG_RECURSION_LIMIT_ERROR: - $error = 'pcre.recursion_limit reached.'; - break; - case PREG_BAD_UTF8_ERROR: - $error = 'Malformed UTF-8 data.'; - break; - case PREG_BAD_UTF8_OFFSET_ERROR: - $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; - break; - default: - $error = 'Unable to parse.'; - } - - throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('Unable to parse', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } @@ -520,7 +503,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob return $this->refs[$value]; } - if (preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { + if (self::preg_match('/^'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); @@ -566,7 +549,7 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0) // determine indentation if not specified if (0 === $indentation) { - if (preg_match('/^ +/', $this->currentLine, $matches)) { + if (self::preg_match('/^ +/', $this->currentLine, $matches)) { $indentation = strlen($matches[0]); } } @@ -577,7 +560,7 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0) while ( $notEOF && ( $isCurrentLineBlank || - preg_match($pattern, $this->currentLine, $matches) + self::preg_match($pattern, $this->currentLine, $matches) ) ) { if ($isCurrentLineBlank && strlen($this->currentLine) > $indentation) { @@ -800,6 +783,49 @@ private function isStringUnIndentedCollectionItem() */ private function isBlockScalarHeader() { - return (bool) preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); + return (bool) self::preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); + } + + /** + * A local wrapper for `preg_match` which will throw a ParseException if there + * is an internal error in the PCRE engine. + * + * This avoids us needing to check for "false" every time PCRE is used + * in the YAML engine + * + * @throws ParseException on a PCRE internal error + * + * @see preg_last_error() + * + * @internal + */ + public static function preg_match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + $ret = preg_match($pattern, $subject, $matches, $flags, $offset); + if ($ret === false) { + switch (preg_last_error()) { + case PREG_INTERNAL_ERROR: + $error = 'Internal PCRE error.'; + break; + case PREG_BACKTRACK_LIMIT_ERROR: + $error = 'pcre.backtrack_limit reached.'; + break; + case PREG_RECURSION_LIMIT_ERROR: + $error = 'pcre.recursion_limit reached.'; + break; + case PREG_BAD_UTF8_ERROR: + $error = 'Malformed UTF-8 data.'; + break; + case PREG_BAD_UTF8_OFFSET_ERROR: + $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; + break; + default: + $error = 'Error.'; + } + + throw new ParseException($error); + } + + return $ret; } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index e1e0d5a61419..d7634556f3a3 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -16,6 +16,7 @@ class ParserTest extends \PHPUnit_Framework_TestCase { + /** @var Parser */ protected $parser; protected function setUp() @@ -1143,6 +1144,17 @@ public function parserThrowsExceptionWithCorrectLineNumberProvider() ), ); } + + public function testCanParseVeryLongValue() + { + $longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000); + $trickyVal = array('x' => $longStringWithSpaces); + + $yamlString = Yaml::dump($trickyVal); + $arrayFromYaml = $this->parser->parse($yamlString); + + $this->assertEquals($trickyVal, $arrayFromYaml); + } } class B From 923bbdbf9f50975adf5a351d2bd39c787c89aa3b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 17 Mar 2017 23:14:15 +0100 Subject: [PATCH 29/80] [Security] simplify the SwitchUserListenerTest --- .../Tests/Firewall/SwitchUserListenerTest.php | 201 +++++------------- 1 file changed, 53 insertions(+), 148 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index 2c05ef75cab2..43013520c36b 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -12,6 +12,13 @@ namespace Symfony\Component\Security\Http\Tests\Firewall; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Role\SwitchUserRole; +use Symfony\Component\Security\Core\User\User; use Symfony\Component\Security\Http\Event\SwitchUserEvent; use Symfony\Component\Security\Http\Firewall\SwitchUserListener; use Symfony\Component\Security\Http\SecurityEvents; @@ -32,14 +39,12 @@ class SwitchUserListenerTest extends TestCase protected function setUp() { - $this->tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(); + $this->tokenStorage = new TokenStorage(); $this->userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); $this->userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); $this->accessDecisionManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')->getMock(); - $this->request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $this->request->query = $this->getMockBuilder('Symfony\Component\HttpFoundation\ParameterBag')->getMock(); - $this->request->server = $this->getMockBuilder('Symfony\Component\HttpFoundation\ServerBag')->getMock(); - $this->event = $this->getEvent($this->request); + $this->request = new Request(); + $this->event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $this->request, HttpKernelInterface::MASTER_REQUEST); } /** @@ -53,13 +58,11 @@ public function testProviderKeyIsRequired() public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() { - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue(null)); - - $this->event->expects($this->never())->method('setResponse'); - $this->tokenStorage->expects($this->never())->method('setToken'); - $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); + + $this->assertNull($this->event->getResponse()); + $this->assertNull($this->tokenStorage->getToken()); } /** @@ -67,10 +70,10 @@ public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() */ public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBeFound() { - $token = $this->getToken(array($this->getMockBuilder('Symfony\Component\Security\Core\Role\RoleInterface')->getMock())); + $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); - $this->tokenStorage->expects($this->any())->method('getToken')->will($this->returnValue($token)); - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); + $this->tokenStorage->setToken($token); + $this->request->query->set('_switch_user', '_exit'); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); @@ -78,29 +81,19 @@ public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBe public function testExitUserUpdatesToken() { - $originalToken = $this->getToken(); - $role = $this->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole') - ->disableOriginalConstructor() - ->getMock(); - $role->expects($this->any())->method('getSource')->will($this->returnValue($originalToken)); - - $this->tokenStorage->expects($this->any()) - ->method('getToken') - ->will($this->returnValue($this->getToken(array($role)))); - - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); - $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); - $this->request->query->expects($this->once())->method('remove', '_switch_user'); - $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array())); - $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); - - $this->tokenStorage->expects($this->once()) - ->method('setToken')->with($originalToken); - $this->event->expects($this->once()) - ->method('setResponse')->with($this->isInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse')); + $originalToken = new UsernamePasswordToken('username', '', 'key', array()); + $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); + + $this->request->query->set('_switch_user', '_exit'); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); + + $this->assertSame(array(), $this->request->query->all()); + $this->assertSame('', $this->request->server->get('QUERY_STRING')); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $this->event->getResponse()); + $this->assertSame($this->request->getUri(), $this->event->getResponse()->getTargetUrl()); + $this->assertSame($originalToken, $this->tokenStorage->getToken()); } public function testExitUserDispatchesEventWithRefreshedUser() @@ -113,38 +106,9 @@ public function testExitUserDispatchesEventWithRefreshedUser() ->method('refreshUser') ->with($originalUser) ->willReturn($refreshedUser); - $originalToken = $this->getToken(); - $originalToken - ->expects($this->any()) - ->method('getUser') - ->willReturn($originalUser); - $role = $this - ->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole') - ->disableOriginalConstructor() - ->getMock(); - $role->expects($this->any())->method('getSource')->willReturn($originalToken); - $this - ->tokenStorage - ->expects($this->any()) - ->method('getToken') - ->willReturn($this->getToken(array($role))); - $this - ->request - ->expects($this->any()) - ->method('get') - ->with('_switch_user') - ->willReturn('_exit'); - $this - ->request - ->expects($this->any()) - ->method('getUri') - ->willReturn('/'); - $this - ->request - ->query - ->expects($this->any()) - ->method('all') - ->will($this->returnValue(array())); + $originalToken = new UsernamePasswordToken($originalUser, '', 'key'); + $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); + $this->request->query->set('_switch_user', '_exit'); $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $dispatcher @@ -166,41 +130,9 @@ public function testExitUserDoesNotDispatchEventWithStringUser() ->userProvider ->expects($this->never()) ->method('refreshUser'); - $originalToken = $this->getToken(); - $originalToken - ->expects($this->any()) - ->method('getUser') - ->willReturn($originalUser); - $role = $this - ->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole') - ->disableOriginalConstructor() - ->getMock(); - $role - ->expects($this->any()) - ->method('getSource') - ->willReturn($originalToken); - $this - ->tokenStorage - ->expects($this->any()) - ->method('getToken') - ->willReturn($this->getToken(array($role))); - $this - ->request - ->expects($this->any()) - ->method('get') - ->with('_switch_user') - ->willReturn('_exit'); - $this - ->request - ->query - ->expects($this->any()) - ->method('all') - ->will($this->returnValue(array())); - $this - ->request - ->expects($this->any()) - ->method('getUri') - ->willReturn('/'); + $originalToken = new UsernamePasswordToken($originalUser, '', 'key'); + $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); + $this->request->query->set('_switch_user', '_exit'); $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $dispatcher @@ -217,10 +149,10 @@ public function testExitUserDoesNotDispatchEventWithStringUser() */ public function testSwitchUserIsDisallowed() { - $token = $this->getToken(array($this->getMockBuilder('Symfony\Component\Security\Core\Role\RoleInterface')->getMock())); + $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); - $this->tokenStorage->expects($this->any())->method('getToken')->will($this->returnValue($token)); - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); + $this->tokenStorage->setToken($token); + $this->request->query->set('_switch_user', 'kuba'); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) @@ -232,17 +164,11 @@ public function testSwitchUserIsDisallowed() public function testSwitchUser() { - $token = $this->getToken(array($this->getMockBuilder('Symfony\Component\Security\Core\Role\RoleInterface')->getMock())); - $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - $user->expects($this->any())->method('getRoles')->will($this->returnValue(array())); + $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); + $user = new User('username', 'password', array()); - $this->tokenStorage->expects($this->any())->method('getToken')->will($this->returnValue($token)); - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); - $this->request->query->expects($this->once())->method('remove', '_switch_user'); - $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array())); - - $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); - $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); + $this->tokenStorage->setToken($token); + $this->request->query->set('_switch_user', 'kuba'); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) @@ -253,25 +179,26 @@ public function testSwitchUser() ->will($this->returnValue($user)); $this->userChecker->expects($this->once()) ->method('checkPostAuth')->with($user); - $this->tokenStorage->expects($this->once()) - ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); + + $this->assertSame(array(), $this->request->query->all()); + $this->assertSame('', $this->request->server->get('QUERY_STRING')); + $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); } public function testSwitchUserKeepsOtherQueryStringParameters() { - $token = $this->getToken(array($this->getMockBuilder('Symfony\Component\Security\Core\Role\RoleInterface')->getMock())); - $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - $user->expects($this->any())->method('getRoles')->will($this->returnValue(array())); + $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); + $user = new User('username', 'password', array()); - $this->tokenStorage->expects($this->any())->method('getToken')->will($this->returnValue($token)); - $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); - $this->request->query->expects($this->once())->method('remove', '_switch_user'); - $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array('page' => 3, 'section' => 2))); - $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); - $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', 'page=3§ion=2'); + $this->tokenStorage->setToken($token); + $this->request->query->replace(array( + '_switch_user' => 'kuba', + 'page' => 3, + 'section' => 2, + )); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) @@ -282,33 +209,11 @@ public function testSwitchUserKeepsOtherQueryStringParameters() ->will($this->returnValue($user)); $this->userChecker->expects($this->once()) ->method('checkPostAuth')->with($user); - $this->tokenStorage->expects($this->once()) - ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); - } - - private function getEvent($request) - { - $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') - ->disableOriginalConstructor() - ->getMock(); - - $event->expects($this->any()) - ->method('getRequest') - ->will($this->returnValue($request)); - - return $event; - } - - private function getToken(array $roles = array()) - { - $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - $token->expects($this->any()) - ->method('getRoles') - ->will($this->returnValue($roles)); - return $token; + $this->assertSame('page=3§ion=2', $this->request->server->get('QUERY_STRING')); + $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); } } From 58b3ee7616f14473841b257eda776bbee712a960 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 20 Mar 2017 09:19:13 +0100 Subject: [PATCH 30/80] [DI] Fix PhpDumper generated doc block --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 2 +- .../DependencyInjection/Tests/Fixtures/php/services24.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index da9ab4315673..888e1443944e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -628,7 +628,7 @@ private function addService($id, Definition $definition) } if ($definition->isAutowired()) { - $doc = << Date: Mon, 20 Mar 2017 10:41:03 +0100 Subject: [PATCH 31/80] [Yaml] CS --- src/Symfony/Component/Yaml/Parser.php | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 7f5c9baef148..345bcbdac173 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -257,7 +257,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = return $value; } - throw new ParseException('Unable to parse', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } @@ -636,10 +636,7 @@ private function isNextLineIndented() return false; } - $ret = false; - if ($this->getCurrentLineIndentation() > $currentIndentation) { - $ret = true; - } + $ret = $this->getCurrentLineIndentation() > $currentIndentation; $this->moveToPreviousLine(); @@ -740,14 +737,7 @@ private function isNextLineUnIndentedCollection() return false; } - $ret = false; - if ( - $this->getCurrentLineIndentation() == $currentIndentation - && - $this->isStringUnIndentedCollectionItem() - ) { - $ret = true; - } + $ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem(); $this->moveToPreviousLine(); @@ -789,8 +779,7 @@ private function isBlockScalarHeader() */ public static function preg_match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) { - $ret = preg_match($pattern, $subject, $matches, $flags, $offset); - if ($ret === false) { + if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) { switch (preg_last_error()) { case PREG_INTERNAL_ERROR: $error = 'Internal PCRE error.'; From 1c2ea9758544e9839d0f85904c7d6339f37f902b Mon Sep 17 00:00:00 2001 From: Jordan Samouh Date: Wed, 15 Mar 2017 18:00:14 +0100 Subject: [PATCH 32/80] [DI] [YamlFileLoader] change error message of a non existing file --- .../Loader/YamlFileLoader.php | 2 +- .../Tests/Loader/YamlFileLoaderTest.php | 47 +++++++++---------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index fef1426d03a2..d93891e9c8c5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -319,7 +319,7 @@ protected function loadFile($file) } if (!file_exists($file)) { - throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); + throw new InvalidArgumentException(sprintf('The file "%s" does not exist.', $file)); } if (null === $this->yamlParser) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 85a52ad1c245..644c8711b78b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -33,40 +33,33 @@ public static function setUpBeforeClass() require_once self::$fixturesPath.'/includes/ProjectExtension.php'; } - public function testLoadFile() + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessageRegExp /The file ".+" does not exist./ + */ + public function testLoadUnExistFile() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); $r = new \ReflectionObject($loader); $m = $r->getMethod('loadFile'); $m->setAccessible(true); - try { - $m->invoke($loader, 'foo.yml'); - $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); - $this->assertEquals('The service file "foo.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); - } - - try { - $m->invoke($loader, 'parameters.ini'); - $this->fail('->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); - $this->assertEquals('The service file "parameters.ini" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); - } + $m->invoke($loader, 'foo.yml'); + } - $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessageRegExp /The file ".+" does not contain valid YAML./ + */ + public function testLoadInvalidYamlFile() + { + $path = self::$fixturesPath.'/ini'; + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator($path)); + $r = new \ReflectionObject($loader); + $m = $r->getMethod('loadFile'); + $m->setAccessible(true); - foreach (array('nonvalid1', 'nonvalid2') as $fixture) { - try { - $m->invoke($loader, $fixture.'.yml'); - $this->fail('->load() throws an InvalidArgumentException if the loaded file does not validate'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not validate'); - $this->assertStringMatchesFormat('The service file "nonvalid%d.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not validate'); - } - } + $m->invoke($loader, $path.'/parameters.ini'); } /** @@ -90,6 +83,8 @@ public function provideInvalidFiles() array('bad_service'), array('bad_calls'), array('bad_format'), + array('nonvalid1'), + array('nonvalid2'), ); } From abf1787dcc3a8ecbad31b07792f4bec1a8fed4c8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 18 Mar 2017 10:10:35 +0100 Subject: [PATCH 33/80] fix some risky tests --- .../HttpFoundation/DbalSessionHandlerTest.php | 2 + ...xtensionBootstrap3HorizontalLayoutTest.php | 14 ++--- .../FormExtensionBootstrap3LayoutTest.php | 14 ++--- .../Extension/FormExtensionDivLayoutTest.php | 20 ++++--- .../FormExtensionTableLayoutTest.php | 14 ++--- .../Helper/FormHelperDivLayoutTest.php | 14 ++--- .../Helper/FormHelperTableLayoutTest.php | 14 ++--- .../Templating/Helper/StopwatchHelperTest.php | 9 ++-- .../Tests/Templating/TemplateTest.php | 16 +----- .../Console/Tests/ApplicationTest.php | 4 ++ .../Console/Tests/Helper/TableTest.php | 8 +-- .../CheckCircularReferencesPassTest.php | 2 + .../CheckDefinitionValidityPassTest.php | 4 ++ ...tionOnInvalidReferenceBehaviorPassTest.php | 4 ++ .../CheckReferenceValidityPassTest.php | 8 +++ .../Tests/Dumper/PhpDumperTest.php | 4 ++ .../Tests/Dumper/XmlDumperTest.php | 2 + .../Debug/TraceableEventDispatcherTest.php | 6 +++ .../Filesystem/Tests/FilesystemTest.php | 40 +++++++++++--- .../Form/Tests/AbstractLayoutTest.php | 2 + .../Tests/Resources/TranslationFilesTest.php | 2 + .../Fragment/InlineFragmentRendererTest.php | 52 +++++++++++-------- .../Tests/LegacyOptionsResolverTest.php | 4 +- .../Tests/OptionsResolver2Dot6Test.php | 10 ++-- .../PropertyAccess/Tests/PropertyPathTest.php | 4 +- .../Tests/Resources/TranslationFilesTest.php | 2 + .../Tests/Resources/TranslationFilesTest.php | 2 + .../Tests/Encoder/XmlEncoderTest.php | 20 ++----- .../Tests/PluralizationRulesTest.php | 2 - .../Translation/Tests/TranslatorTest.php | 3 ++ .../Validator/Tests/ConstraintTest.php | 8 ++- .../Constraints/CallbackValidatorTest.php | 4 +- .../Tests/Constraints/GroupSequenceTest.php | 2 + .../Tests/Mapping/ClassMetadataTest.php | 12 +++-- .../LazyLoadingMetadataFactoryTest.php | 4 ++ .../Tests/Resources/TranslationFilesTest.php | 2 + 36 files changed, 206 insertions(+), 128 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php index 89ac999f2030..1c9c82bc129e 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php @@ -25,5 +25,7 @@ public function testConstruct() { $connection = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock(); $handler = new DbalSessionHandler($connection); + + $this->assertInstanceOf('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler', $handler); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index 2951e4471f73..8abcc8cd5677 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -118,36 +118,36 @@ protected function setTheme(FormView $view, array $themes) public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index d26714530c95..0236dd76e1e4 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -118,36 +118,36 @@ protected function setTheme(FormView $view, array $themes) public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index 7e4c55e984b4..d07e585a8923 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -105,7 +105,11 @@ public function testThemeBlockInheritanceUsingDynamicExtend() $renderer = $this->extension->renderer; $renderer->setTheme($view, array('page_dynamic_extends.html.twig')); - $renderer->searchAndRenderBlock($view, 'row'); + + $this->assertMatchesXpath( + $renderer->searchAndRenderBlock($view, 'row'), + '/div/label[text()="child"]' + ); } public function isSelectedChoiceProvider() @@ -211,36 +215,36 @@ public static function themeInheritanceProvider() public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 6509c405e7bc..9c95db6d5fd9 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -119,36 +119,36 @@ protected function setTheme(FormView $view, array $themes) public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php index 217fd5e50e23..c745818b1e72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @@ -131,36 +131,36 @@ public static function themeInheritanceProvider() public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php index 99bfba0c4e7c..3448a56fa4d2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @@ -118,36 +118,36 @@ protected function setTheme(FormView $view, array $themes) public function testRange() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testRangeWithMinMaxValues() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testLabelWithoutTranslationOnButton() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testButtonlabelWithoutTranslation() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() { - // No-op for forward compatibility with AbstractLayoutTest 2.8 + $this->markTestIncomplete('No-op for forward compatibility with AbstractLayoutTest 2.8'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php index cf7b627a499a..686c655aac8f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php @@ -30,11 +30,10 @@ public function testDevEnvironment() public function testProdEnvironment() { $helper = new StopwatchHelper(null); + $helper->start('foo'); - try { - $helper->start('foo'); - } catch (\BadMethodCallException $e) { - $this->fail('Assumed stopwatch is not called when not provided'); - } + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php index c49010bfdc35..1f6f51dd3351 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php @@ -19,21 +19,9 @@ class TemplateTest extends TestCase /** * @dataProvider getTemplateToPathProvider */ - public function testGetPathForTemplatesInABundle($template, $path) + public function testGetPathForTemplate($template, $path) { - if ($template->get('bundle')) { - $this->assertEquals($template->getPath(), $path); - } - } - - /** - * @dataProvider getTemplateToPathProvider - */ - public function testGetPathForTemplatesOutOfABundle($template, $path) - { - if (!$template->get('bundle')) { - $this->assertEquals($template->getPath(), $path); - } + $this->assertSame($template->getPath(), $path); } public function getTemplateToPathProvider() diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 223a68bfc8e2..895fdb926142 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -704,8 +704,12 @@ public function testVerboseValueNotBreakArguments() $input = new ArgvInput(array('cli.php', '-v', 'foo:bar')); $application->run($input, $output); + $this->addToAssertionCount(1); + $input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar')); $application->run($input, $output); + + $this->addToAssertionCount(1); } public function testRunReturnsIntegerExitCode() diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 2ff581e83ef8..5fe6b645602f 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -34,7 +34,7 @@ protected function tearDown() } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ public function testRender($headers, $rows, $style, $expected, $decorated = false) { @@ -50,7 +50,7 @@ public function testRender($headers, $rows, $style, $expected, $decorated = fals } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ public function testRenderAddRows($headers, $rows, $style, $expected, $decorated = false) { @@ -66,7 +66,7 @@ public function testRenderAddRows($headers, $rows, $style, $expected, $decorated } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected, $decorated = false) { @@ -83,7 +83,7 @@ public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected, $d $this->assertEquals($expected, $this->getOutputContent($output)); } - public function testRenderProvider() + public function renderProvider() { $books = array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php index d894f7ab6f6d..220348f4fecf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php @@ -114,6 +114,8 @@ public function testProcessIgnoresMethodCalls() $container->register('b')->addMethodCall('setA', array(new Reference('a'))); $this->process($container); + + $this->addToAssertionCount(1); } protected function process(ContainerBuilder $container) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php index 60f44c3f0224..f7889e94967b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php @@ -72,6 +72,8 @@ public function testProcess() $container->register('d', 'class')->setSynthetic(true); $this->process($container); + + $this->addToAssertionCount(1); } public function testValidTags() @@ -83,6 +85,8 @@ public function testValidTags() $container->register('d', 'class')->addTag('foo', array('bar' => 1.1)); $this->process($container); + + $this->addToAssertionCount(1); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php index c5f4ec7f9569..65a782a4a83f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php @@ -28,6 +28,10 @@ public function testProcess() ->addArgument(new Reference('b')) ; $container->register('b', '\stdClass'); + + $this->process($container); + + $this->addToAssertionCount(1); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php index d7e15df9e43a..303787bea19b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php @@ -27,6 +27,8 @@ public function testProcessIgnoresScopeWideningIfNonStrictReference() $container->register('b')->setScope('prototype'); $this->process($container); + + $this->addToAssertionCount(1); } /** @@ -39,6 +41,8 @@ public function testProcessDetectsScopeWidening() $container->register('b')->setScope('prototype'); $this->process($container); + + $this->addToAssertionCount(1); } public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict() @@ -51,6 +55,8 @@ public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict() $container->register('b')->setScope('b'); $this->process($container); + + $this->addToAssertionCount(1); } /** @@ -88,6 +94,8 @@ public function testProcess() $container->register('b'); $this->process($container); + + $this->addToAssertionCount(1); } protected function process(ContainerBuilder $container) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 7d660fb2f02e..41b6c375d8aa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -297,6 +297,8 @@ public function testCircularReferenceAllowanceForLazyServices() $dumper = new PhpDumper($container); $dumper->dump(); + + $this->addToAssertionCount(1); } public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServices() @@ -334,5 +336,7 @@ public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServic $dumper->setProxyDumper(new DummyProxyDumper()); $dumper->dump(); + + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php index 9f96f33e9dec..72ae5897204f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -162,6 +162,8 @@ public function testCompiledContainerCanBeDumped($containerFile) $container->compile(); $dumper = new XmlDumper($container); $dumper->dump(); + + $this->addToAssertionCount(1); } public function provideCompiledContainerData() diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php index 9ee85bb0ac25..9317ea945722 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -151,14 +151,20 @@ public function testDispatchNested() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $loop = 1; + $dispatchedEvents = 0; $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) { ++$loop; if (2 == $loop) { $dispatcher->dispatch('foo'); } }); + $dispatcher->addListener('foo', function () use (&$dispatchedEvents) { + ++$dispatchedEvents; + }); $dispatcher->dispatch('foo'); + + $this->assertSame(2, $dispatchedEvents); } public function testDispatchReusedEventNested() diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index f879e641701e..be47a2d0ce72 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -442,14 +442,22 @@ public function testChmodChangesFileMode() $this->assertFilePermissions(400, $file); } - public function testChmodWrongMod() + public function testChmodWithWrongModLeavesPreviousPermissionsUntouched() { $this->markAsSkippedIfChmodIsMissing(); + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM'); + } + $dir = $this->workspace.DIRECTORY_SEPARATOR.'file'; touch($dir); + $permissions = fileperms($dir); + $this->filesystem->chmod($dir, 'Wrongmode'); + + $this->assertSame($permissions, fileperms($dir)); } public function testChmodRecursive() @@ -536,7 +544,10 @@ public function testChown() $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir'; mkdir($dir); - $this->filesystem->chown($dir, $this->getFileOwner($dir)); + $owner = $this->getFileOwner($dir); + $this->filesystem->chown($dir, $owner); + + $this->assertSame($owner, $this->getFileOwner($dir)); } public function testChownRecursive() @@ -548,7 +559,10 @@ public function testChownRecursive() $file = $dir.DIRECTORY_SEPARATOR.'file'; touch($file); - $this->filesystem->chown($dir, $this->getFileOwner($dir), true); + $owner = $this->getFileOwner($dir); + $this->filesystem->chown($dir, $owner, true); + + $this->assertSame($owner, $this->getFileOwner($file)); } public function testChownSymlink() @@ -562,7 +576,10 @@ public function testChownSymlink() $this->filesystem->symlink($file, $link); - $this->filesystem->chown($link, $this->getFileOwner($link)); + $owner = $this->getFileOwner($link); + $this->filesystem->chown($link, $owner); + + $this->assertSame($owner, $this->getFileOwner($link)); } /** @@ -602,7 +619,10 @@ public function testChgrp() $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir'; mkdir($dir); - $this->filesystem->chgrp($dir, $this->getFileGroup($dir)); + $group = $this->getFileGroup($dir); + $this->filesystem->chgrp($dir, $group); + + $this->assertSame($group, $this->getFileGroup($dir)); } public function testChgrpRecursive() @@ -614,7 +634,10 @@ public function testChgrpRecursive() $file = $dir.DIRECTORY_SEPARATOR.'file'; touch($file); - $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true); + $group = $this->getFileGroup($dir); + $this->filesystem->chgrp($dir, $group, true); + + $this->assertSame($group, $this->getFileGroup($file)); } public function testChgrpSymlink() @@ -628,7 +651,10 @@ public function testChgrpSymlink() $this->filesystem->symlink($file, $link); - $this->filesystem->chgrp($link, $this->getFileGroup($link)); + $group = $this->getFileGroup($link); + $this->filesystem->chgrp($link, $group); + + $this->assertSame($group, $this->getFileGroup($link)); } /** diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 3873fb4cd4dc..411a8196cc73 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -83,6 +83,8 @@ protected function assertMatchesXpath($html, $expression, $count = 1) // strip away and substr($dom->saveHTML(), 6, -8) )); + } else { + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php index 052821c39dfe..ba19a6215a7b 100644 --- a/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Form/Tests/Resources/TranslationFilesTest.php @@ -25,6 +25,8 @@ public function testTranslationFileIsValid($filePath) } else { \PHPUnit\Util\XML::loadfile($filePath, false, false, true); } + + $this->addToAssertionCount(1); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index f85fd5ed26fd..4c1d6a00c44c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -22,6 +22,18 @@ class InlineFragmentRendererTest extends TestCase { + private $originalTrustedHeaderName; + + protected function setUp() + { + $this->originalTrustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP); + } + + protected function tearDown() + { + Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $this->originalTrustedHeaderName); + } + public function testRender() { $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo')))); @@ -47,7 +59,7 @@ public function testRenderWithObjectsAsAttributes() $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($subRequest)); - $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/')); + $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'))->getContent()); } public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController() @@ -70,14 +82,10 @@ public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController( public function testRenderWithTrustedHeaderDisabled() { - $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, ''); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/'))); - $strategy->render('/', Request::create('/')); - - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName); + $this->assertSame('foo', $strategy->render('/', Request::create('/'))->getContent()); } /** @@ -125,22 +133,6 @@ private function getKernel($returnValue) return $kernel; } - /** - * Creates a Kernel expecting a request equals to $request - * Allows delta in comparison in case REQUEST_TIME changed by 1 second. - */ - private function getKernelExpectingRequest(Request $request) - { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); - $kernel - ->expects($this->any()) - ->method('handle') - ->with($this->equalTo($request, 1)) - ; - - return $kernel; - } - public function testExceptionInSubRequestsDoesNotMangleOutputBuffers() { $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock(); @@ -211,6 +203,22 @@ public function testHeadersPossiblyResultingIn304AreNotAssignedToSubrequest() $request = Request::create('/', 'GET', array(), array(), array(), array('HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*')); $strategy->render('/', $request); } + + /** + * Creates a Kernel expecting a request equals to $request + * Allows delta in comparison in case REQUEST_TIME changed by 1 second. + */ + private function getKernelExpectingRequest(Request $request, $strict = false) + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel + ->expects($this->once()) + ->method('handle') + ->with($this->equalTo($request, 1)) + ->willReturn(new Response('foo')); + + return $kernel; + } } class Bar diff --git a/src/Symfony/Component/OptionsResolver/Tests/LegacyOptionsResolverTest.php b/src/Symfony/Component/OptionsResolver/Tests/LegacyOptionsResolverTest.php index c277425c4d7f..44e07b7726c9 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/LegacyOptionsResolverTest.php +++ b/src/Symfony/Component/OptionsResolver/Tests/LegacyOptionsResolverTest.php @@ -89,9 +89,9 @@ public function testTypeAliasesForAllowedTypes() 'force' => 'boolean', )); - $this->resolver->resolve(array( + $this->assertSame(array('force' => true), $this->resolver->resolve(array( 'force' => true, - )); + ))); } public function testResolveLazyDependencyOnOptional() diff --git a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolver2Dot6Test.php b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolver2Dot6Test.php index 109454e56ff6..c548f16ba6d9 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolver2Dot6Test.php +++ b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolver2Dot6Test.php @@ -1102,7 +1102,7 @@ public function testFailIfCyclicDependencyBetweenNormalizerAndLazyOption() $this->resolver->resolve(); } - public function testCatchedExceptionFromNormalizerDoesNotCrashOptionResolver() + public function testCaughtExceptionFromNormalizerDoesNotCrashOptionResolver() { $throw = true; @@ -1116,7 +1116,7 @@ public function testCatchedExceptionFromNormalizerDoesNotCrashOptionResolver() } }); - $this->resolver->setNormalizer('thrower', function (Options $options) use (&$throw) { + $this->resolver->setNormalizer('thrower', function () use (&$throw) { if ($throw) { $throw = false; throw new \UnexpectedValueException('throwing'); @@ -1125,10 +1125,10 @@ public function testCatchedExceptionFromNormalizerDoesNotCrashOptionResolver() return true; }); - $this->resolver->resolve(); + $this->assertSame(array('catcher' => false, 'thrower' => true), $this->resolver->resolve()); } - public function testCatchedExceptionFromLazyDoesNotCrashOptionResolver() + public function testCaughtExceptionFromLazyDoesNotCrashOptionResolver() { $throw = true; @@ -1149,7 +1149,7 @@ public function testCatchedExceptionFromLazyDoesNotCrashOptionResolver() return true; }); - $this->resolver->resolve(); + $this->assertSame(array('catcher' => false, 'thrower' => true), $this->resolver->resolve()); } public function testInvokeEachNormalizerOnlyOnce() diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php index 5e3a06a4b4d8..6c5c6b22a2b0 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php @@ -87,7 +87,9 @@ public function testPathCannotBeFalse() public function testZeroIsValidPropertyPath() { - new PropertyPath('0'); + $propertyPath = new PropertyPath('0'); + + $this->assertSame('0', (string) $propertyPath); } public function testGetParentWithDot() diff --git a/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php index 6588c32fdfa3..96a1307ed056 100644 --- a/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php @@ -25,6 +25,8 @@ public function testTranslationFileIsValid($filePath) } else { \PHPUnit\Util\XML::loadfile($filePath, false, false, true); } + + $this->addToAssertionCount(1); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/Security/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Security/Tests/Resources/TranslationFilesTest.php index 5e959b30d4fb..30b9aed6ec87 100644 --- a/src/Symfony/Component/Security/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Security/Tests/Resources/TranslationFilesTest.php @@ -25,6 +25,8 @@ public function testTranslationFileIsValid($filePath) } else { \PHPUnit\Util\XML::loadfile($filePath, false, false, true); } + + $this->addToAssertionCount(1); } public function provideTranslationFiles() diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index 4e83f3464f20..751afe2bd3e8 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -17,7 +17,6 @@ use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\CustomNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -435,23 +434,12 @@ public function testDecodeInvalidXml() $this->encoder->decode('', 'xml'); } + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ public function testPreventsComplexExternalEntities() { - $oldCwd = getcwd(); - chdir(__DIR__); - - try { - $this->encoder->decode(']>&test;', 'xml'); - chdir($oldCwd); - - $this->fail('No exception was thrown.'); - } catch (\Exception $e) { - chdir($oldCwd); - - if (!$e instanceof UnexpectedValueException) { - $this->fail('Expected UnexpectedValueException'); - } - } + $this->encoder->decode(']>&test;', 'xml'); } public function testDecodeEmptyXml() diff --git a/src/Symfony/Component/Translation/Tests/PluralizationRulesTest.php b/src/Symfony/Component/Translation/Tests/PluralizationRulesTest.php index 8e499fd6edac..8a6723ea9cb1 100644 --- a/src/Symfony/Component/Translation/Tests/PluralizationRulesTest.php +++ b/src/Symfony/Component/Translation/Tests/PluralizationRulesTest.php @@ -65,7 +65,6 @@ public function successLangcodes() array('2', array('nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM')), array('3', array('be', 'bs', 'cs', 'hr')), array('4', array('cy', 'mt', 'sl')), - array('5', array()), array('6', array('ar')), ); } @@ -86,7 +85,6 @@ public function failingLangcodes() array('3', array('cbs')), array('4', array('gd', 'kw')), array('5', array('ga')), - array('6', array()), ); } diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php index f02eb57b358f..960d8f4d3c54 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php @@ -156,6 +156,7 @@ public function testSetFallbackValidLocales($locale) $translator = new Translator($locale, new MessageSelector()); $translator->setFallbackLocales(array('fr', $locale)); // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); } public function testTransWithFallbackLocale() @@ -187,6 +188,7 @@ public function testAddResourceValidLocales($locale) $translator = new Translator('fr', new MessageSelector()); $translator->addResource('array', array('foo' => 'foofoo'), $locale); // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); } public function testAddResourceAfterTrans() @@ -390,6 +392,7 @@ public function testTransChoiceValidLocale($locale) $translator->transChoice('foo', 1, array(), '', $locale); // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); } public function getTransFileTests() diff --git a/src/Symfony/Component/Validator/Tests/ConstraintTest.php b/src/Symfony/Component/Validator/Tests/ConstraintTest.php index 1b1219664402..a05741490fdd 100644 --- a/src/Symfony/Component/Validator/Tests/ConstraintTest.php +++ b/src/Symfony/Component/Validator/Tests/ConstraintTest.php @@ -115,7 +115,9 @@ public function testRequiredOptionsMustBeDefined() public function testRequiredOptionsPassed() { - new ConstraintC(array('option1' => 'default')); + $constraint = new ConstraintC(array('option1' => 'default')); + + $this->assertSame('default', $constraint->option1); } public function testGroupsAreConvertedToArray() @@ -140,7 +142,9 @@ public function testAllowsSettingZeroRequiredPropertyValue() public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray() { - new ConstraintB(array()); + $constraint = new ConstraintB(array()); + + $this->assertSame(array(Constraint::PROPERTY_CONSTRAINT, Constraint::CLASS_CONSTRAINT), $constraint->getTargets()); } public function testGetTargetsCanBeString() diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php index 6bd7735f0d7d..e87c9c4752a2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php @@ -330,7 +330,9 @@ public function testConstraintGetTargets() // Should succeed. Needed when defining constraints as annotations. public function testNoConstructorArguments() { - new Callback(); + $constraint = new Callback(); + + $this->assertSame(array(Constraint::CLASS_CONSTRAINT, Constraint::PROPERTY_CONSTRAINT), $constraint->getTargets()); } public function testAnnotationInvocationSingleValued() diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GroupSequenceTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GroupSequenceTest.php index 6326d0514ba3..f298cd27e625 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GroupSequenceTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GroupSequenceTest.php @@ -94,5 +94,7 @@ public function testLegacyUnsetIgnoresNonExistingKeys() // should not fail unset($sequence[2]); + + $this->assertCount(2, $sequence); } } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index 8ca3c9fbcb60..9a23e8cf355a 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -245,19 +245,23 @@ public function testSerialize() public function testGroupSequencesWorkIfContainingDefaultGroup() { $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup())); + + $this->assertInstanceOf('Symfony\Component\Validator\Constraints\GroupSequence', $this->metadata->getGroupSequence()); } + /** + * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException + */ public function testGroupSequencesFailIfNotContainingDefaultGroup() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\GroupDefinitionException'); - $this->metadata->setGroupSequence(array('Foo', 'Bar')); } + /** + * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException + */ public function testGroupSequencesFailIfContainingDefault() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Validator\Exception\GroupDefinitionException'); - $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP)); } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index 1ebce65cc202..b5d1a9dc84d4 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -167,7 +167,11 @@ public function testMetadataCacheWithRuntimeConstraint() $metadata = $factory->getMetadataFor(self::PARENT_CLASS); $metadata->addConstraint(new Callback(function () {})); + $this->assertCount(3, $metadata->getConstraints()); + $metadata = $factory->getMetadataFor(self::CLASS_NAME); + + $this->assertCount(6, $metadata->getConstraints()); } public function testGroupsFromParent() diff --git a/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php index d33351352777..96311cfeff32 100644 --- a/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php +++ b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php @@ -25,6 +25,8 @@ public function testTranslationFileIsValid($filePath) } else { \PHPUnit\Util\XML::loadfile($filePath, false, false, true); } + + $this->addToAssertionCount(1); } public function provideTranslationFiles() From f50915066f20d1a816a559def732929cfc537dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Auswo=CC=88ger?= Date: Mon, 20 Mar 2017 20:55:39 +0100 Subject: [PATCH 34/80] [HttpKernel] Fixed bug with purging of HTTPS URLs --- .../Component/HttpKernel/HttpCache/Store.php | 9 ++++--- .../HttpKernel/Tests/HttpCache/StoreTest.php | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index f5574614b839..c4d961e68f04 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -325,10 +325,13 @@ private function getMetadata($key) */ public function purge($url) { - $http = preg_replace('#^https#', 'http', $url); - $https = preg_replace('#^http#', 'https', $url); + $http = preg_replace('#^https:#', 'http:', $url); + $https = preg_replace('#^http:#', 'https:', $url); - return $this->doPurge($http) || $this->doPurge($https); + $purgedHttp = $this->doPurge($http); + $purgedHttps = $this->doPurge($https); + + return $purgedHttp || $purgedHttps; } /** diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 8b9e52b03ea9..cef019167a4e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -236,6 +236,33 @@ public function testLocking() $this->assertFalse($this->store->isLocked($req)); } + public function testPurgeHttps() + { + $request = Request::create('https://example.com/foo'); + $this->store->write($request, new Response('foo')); + + $this->assertNotEmpty($this->getStoreMetadata($request)); + + $this->assertTrue($this->store->purge('https://example.com/foo')); + $this->assertEmpty($this->getStoreMetadata($request)); + } + + public function testPurgeHttpAndHttps() + { + $requestHttp = Request::create('https://example.com/foo'); + $this->store->write($requestHttp, new Response('foo')); + + $requestHttps = Request::create('http://example.com/foo'); + $this->store->write($requestHttps, new Response('foo')); + + $this->assertNotEmpty($this->getStoreMetadata($requestHttp)); + $this->assertNotEmpty($this->getStoreMetadata($requestHttps)); + + $this->assertTrue($this->store->purge('http://example.com/foo')); + $this->assertEmpty($this->getStoreMetadata($requestHttp)); + $this->assertEmpty($this->getStoreMetadata($requestHttps)); + } + protected function storeSimpleEntry($path = null, $headers = array()) { if (null === $path) { From 2de494f60bef82490a192bf81d10156269ac980e Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Tue, 21 Mar 2017 11:01:33 +0100 Subject: [PATCH 35/80] [WebProfilerBundle] Drop dead code --- .../Controller/ProfilerController.php | 2 +- .../views/Profiler/toolbar.html.twig | 64 +++++++++---------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 4e6f15bd01ee..67767b0a78d7 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -43,7 +43,7 @@ class ProfilerController * @param array $templates The templates * @param string $toolbarPosition The toolbar position (top, bottom, normal, or null -- use the configuration) */ - public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal') + public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'bottom') { $this->generator = $generator; $this->profiler = $profiler; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig index 99ee7172ed29..b2b77f65fa06 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig @@ -1,28 +1,26 @@ -{% if 'normal' != position %} - - -
-{% endif %} + Sfjs.setPreference('toolbar/displayState', 'block'); + "> + {{ include('@WebProfiler/Icon/symfony.svg') }} + + + +
{% for name, template in templates %} @@ -39,16 +37,14 @@ {% endif %} {% endfor %} - {% if 'normal' != position %} - - {{ include('@WebProfiler/Icon/close.svg') }} - - {% endif %} + + {{ include('@WebProfiler/Icon/close.svg') }} +
From b3f341fd908ea496dea0a77984bc4e31acc52f98 Mon Sep 17 00:00:00 2001 From: Romain Pierre Date: Tue, 21 Mar 2017 22:03:13 +0100 Subject: [PATCH 36/80] Fixes a typo in the form collector styles --- .../WebProfilerBundle/Resources/views/Collector/form.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig index eb87a8fa8abb..a59982ce8a9e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig @@ -60,7 +60,7 @@ } #tree-menu .empty { border: 0; - mmargin: 0; + margin: 0; padding: 0; } #tree-details-container { From 0c741f570434606d5d539ac37c8be76b9e09e91a Mon Sep 17 00:00:00 2001 From: Jordan Samouh Date: Fri, 17 Mar 2017 17:37:38 +0100 Subject: [PATCH 37/80] [Serializer] [XML] Ignore Process Instruction --- .../Serializer/Encoder/XmlEncoder.php | 10 ++++- .../Tests/Encoder/XmlEncoderTest.php | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index 0bd85b024796..40f61167b369 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -92,14 +92,16 @@ public function decode($data, $format, array $context = array()) throw new UnexpectedValueException($error->message); } + $rootNode = null; foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new UnexpectedValueException('Document types are not allowed.'); } + if (!$rootNode && $child->nodeType !== XML_PI_NODE) { + $rootNode = $child; + } } - $rootNode = $dom->firstChild; - // todo: throw an exception if the root node name is not correctly configured (bc) if ($rootNode->hasChildNodes()) { @@ -329,6 +331,10 @@ private function parseXmlValue(\DOMNode $node) $value = array(); foreach ($node->childNodes as $subnode) { + if ($subnode->nodeType === XML_PI_NODE) { + continue; + } + $val = $this->parseXml($subnode); if ('item' === $subnode->nodeName && isset($val['@key'])) { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index 4e83f3464f20..a3c912e7ee6c 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -371,6 +371,44 @@ public function testDecodeArray() $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } + public function testDecodeXMLWithProcessInstruction() + { + $source = <<<'XML' + + + + + + foo + + a + b + + val + val + bar + + title1 + + + + title2 + + + + Ed + + + + 1 + + ?> +XML; + $obj = $this->getObject(); + + $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml')); + } + public function testDecodeIgnoreWhiteSpace() { $source = <<<'XML' From 067ab52ba09cdb8ab29535b1f4a9885ad52a30d1 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 21 Mar 2017 18:52:14 +0100 Subject: [PATCH 38/80] HttpCache: New test for revalidating responses with an expired TTL --- .../Tests/HttpCache/HttpCacheTest.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index b6164dd6782f..985549d13df3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -809,6 +809,42 @@ public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation() $this->assertTraceNotContains('miss'); } + public function testServesResponseWhileFreshAndRevalidatesWithLastModifiedInformation() + { + $time = \DateTime::createFromFormat('U', time()); + + $this->setNextResponse(200, array(), 'Hello World', function (Request $request, Response $response) use ($time) { + $response->setSharedMaxAge(10); + $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); + }); + + // prime the cache + $this->request('GET', '/'); + + // next request before s-maxage has expired: Serve from cache + // without hitting the backend + $this->request('GET', '/'); + $this->assertHttpKernelIsNotCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('fresh'); + + sleep(15); // expire the cache + + $that = $this; + + $this->setNextResponse(304, array(), '', function (Request $request, Response $response) use ($time, $that) { + $that->assertEquals($time->format(DATE_RFC2822), $request->headers->get('IF_MODIFIED_SINCE')); + }); + + $this->request('GET', '/'); + $this->assertHttpKernelIsCalled(); + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('Hello World', $this->response->getContent()); + $this->assertTraceContains('stale'); + $this->assertTraceContains('valid'); + } + public function testReplacesCachedResponsesWhenValidationResultsInNon304Response() { $time = \DateTime::createFromFormat('U', time()); From 40a67c9e6081294478e2bc45bdff228fa74c1b72 Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 22 Mar 2017 10:39:50 +0100 Subject: [PATCH 39/80] [WebProfilerBundle] Remove uneeded directive in the form collector styles --- .../WebProfilerBundle/Resources/views/Collector/form.html.twig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig index a59982ce8a9e..fc4aada9ef3e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig @@ -60,7 +60,6 @@ } #tree-menu .empty { border: 0; - margin: 0; padding: 0; } #tree-details-container { From 4bd2c22871538fd056f57033c1284a66f0dbfecb Mon Sep 17 00:00:00 2001 From: Claudio Zizza Date: Sun, 8 Jan 2017 21:17:12 +0100 Subject: [PATCH 40/80] [Validator] Add object handling of invalid constraints in Composite --- .../Component/Validator/Constraints/Composite.php | 4 ++++ .../Validator/Tests/Constraints/CompositeTest.php | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index ab8466bcfcbc..d1391bb0724a 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -67,6 +67,10 @@ public function __construct($options = null) foreach ($nestedConstraints as $constraint) { if (!$constraint instanceof Constraint) { + if (is_object($constraint)) { + $constraint = get_class($constraint); + } + throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, get_class($this))); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php index 6a8530723fb0..df4255007c5c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php @@ -125,6 +125,17 @@ public function testFailIfNoConstraint() )); } + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + */ + public function testFailIfNoConstraintObject() + { + new ConcreteComposite(array( + new NotNull(array('groups' => 'Default')), + new \ArrayObject(), + )); + } + /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ From 04caacb757783b2169d799dd6aad8acdca1fb8cf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Feb 2017 12:31:06 +0100 Subject: [PATCH 41/80] [HttpFoundation] Fix missing handling of for/host/proto info from "Forwarded" header --- .../Component/HttpFoundation/Request.php | 123 ++++++++++-------- .../HttpFoundation/Tests/RequestTest.php | 51 +++++++- .../ValidateRequestListenerTest.php | 2 +- .../HttpKernel/Tests/HttpKernelTest.php | 2 +- 4 files changed, 120 insertions(+), 58 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 81eaf408d49a..d8bf2ad14baa 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -206,6 +206,15 @@ class Request protected static $requestFactory; + private $isForwardedValid = true; + + private static $forwardedParams = array( + self::HEADER_CLIENT_IP => 'for', + self::HEADER_CLIENT_HOST => 'host', + self::HEADER_CLIENT_PROTO => 'proto', + self::HEADER_CLIENT_PORT => 'host', + ); + /** * Constructor. * @@ -806,41 +815,13 @@ public function setSession(SessionInterface $session) */ public function getClientIps() { - $clientIps = array(); $ip = $this->server->get('REMOTE_ADDR'); if (!$this->isFromTrustedProxy()) { return array($ip); } - $hasTrustedForwardedHeader = self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED]); - $hasTrustedClientIpHeader = self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP]); - - if ($hasTrustedForwardedHeader) { - $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); - preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches); - $forwardedClientIps = $matches[3]; - - $forwardedClientIps = $this->normalizeAndFilterClientIps($forwardedClientIps, $ip); - $clientIps = $forwardedClientIps; - } - - if ($hasTrustedClientIpHeader) { - $xForwardedForClientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); - - $xForwardedForClientIps = $this->normalizeAndFilterClientIps($xForwardedForClientIps, $ip); - $clientIps = $xForwardedForClientIps; - } - - if ($hasTrustedForwardedHeader && $hasTrustedClientIpHeader && $forwardedClientIps !== $xForwardedForClientIps) { - throw new ConflictingHeadersException('The request has both a trusted Forwarded header and a trusted Client IP header, conflicting with each other with regards to the originating IP addresses of the request. This is the result of a misconfiguration. You should either configure your proxy only to send one of these headers, or configure Symfony to distrust one of them.'); - } - - if (!$hasTrustedForwardedHeader && !$hasTrustedClientIpHeader) { - return $this->normalizeAndFilterClientIps(array(), $ip); - } - - return $clientIps; + return $this->getTrustedValues(self::HEADER_CLIENT_IP, $ip) ?: array($ip); } /** @@ -966,31 +947,25 @@ public function getScheme() */ public function getPort() { - if ($this->isFromTrustedProxy()) { - if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { - return (int) $port; - } - - if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) { - return 443; - } + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_PORT)) { + $host = $host[0]; + } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + $host = $host[0]; + } elseif (!$host = $this->headers->get('HOST')) { + return $this->server->get('SERVER_PORT'); } - if ($host = $this->headers->get('HOST')) { - if ($host[0] === '[') { - $pos = strpos($host, ':', strrpos($host, ']')); - } else { - $pos = strrpos($host, ':'); - } - - if (false !== $pos) { - return (int) substr($host, $pos + 1); - } + if ($host[0] === '[') { + $pos = strpos($host, ':', strrpos($host, ']')); + } else { + $pos = strrpos($host, ':'); + } - return 'https' === $this->getScheme() ? 443 : 80; + if (false !== $pos) { + return (int) substr($host, $pos + 1); } - return $this->server->get('SERVER_PORT'); + return 'https' === $this->getScheme() ? 443 : 80; } /** @@ -1190,8 +1165,8 @@ public function getQueryString() */ public function isSecure() { - if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { - return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); + if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_CLIENT_PROTO)) { + return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true); } $https = $this->server->get('HTTPS'); @@ -1216,10 +1191,8 @@ public function isSecure() */ public function getHost() { - if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { - $elements = explode(',', $host, 2); - - $host = $elements[0]; + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); @@ -1948,8 +1921,48 @@ private function isFromTrustedProxy() return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); } + private function getTrustedValues($type, $ip = null) + { + $clientValues = array(); + $forwardedValues = array(); + + if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) { + foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { + $clientValues[] = (self::HEADER_CLIENT_PORT === $type ? '0.0.0.0:' : '').trim($v); + } + } + + if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { + $forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); + $forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array(); + } + + if (null !== $ip) { + $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); + $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); + } + + if ($forwardedValues === $clientValues || !$clientValues) { + return $forwardedValues; + } + + if (!$forwardedValues) { + return $clientValues; + } + + if (!$this->isForwardedValid) { + return null !== $ip ? array('0.0.0.0', $ip) : array(); + } + $this->isForwardedValid = false; + + throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::$trustedHeaders[self::HEADER_FORWARDED], self::$trustedHeaders[$type])); + } + private function normalizeAndFilterClientIps(array $clientIps, $ip) { + if (!$clientIps) { + return array(); + } $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from $firstTrustedIp = null; diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index ee753dc6b077..5687cc62e103 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1631,7 +1631,7 @@ private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $http return $request; } - public function testTrustedProxies() + public function testTrustedProxiesXForwardedFor() { $request = Request::create('http://example.com/'); $request->server->set('REMOTE_ADDR', '3.3.3.3'); @@ -1714,6 +1714,55 @@ public function testTrustedProxies() Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); } + public function testTrustedProxiesForwarded() + { + $request = Request::create('http://example.com/'); + $request->server->set('REMOTE_ADDR', '3.3.3.3'); + $request->headers->set('FORWARDED', 'for=1.1.1.1, host=foo.example.com:8080, proto=https, for=2.2.2.2, host=real.example.com:8080'); + + // no trusted proxies + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + // disabling proxy trusting + Request::setTrustedProxies(array()); + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + // request is forwarded by a non-trusted proxy + Request::setTrustedProxies(array('2.2.2.2')); + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + // trusted proxy via setTrustedProxies() + Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); + $this->assertEquals('1.1.1.1', $request->getClientIp()); + $this->assertEquals('foo.example.com', $request->getHost()); + $this->assertEquals(8080, $request->getPort()); + $this->assertTrue($request->isSecure()); + + // trusted proxy via setTrustedProxies() + Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2')); + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + // check various X_FORWARDED_PROTO header values + Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); + $request->headers->set('FORWARDED', 'proto=ssl'); + $this->assertTrue($request->isSecure()); + + $request->headers->set('FORWARDED', 'proto=https, proto=http'); + $this->assertTrue($request->isSecure()); + } + /** * @expectedException \InvalidArgumentException */ diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php index 8311a76e35a0..55dc59e13f71 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php @@ -32,7 +32,7 @@ public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps() $request = new Request(); $request->setTrustedProxies(array('1.1.1.1')); $request->server->set('REMOTE_ADDR', '1.1.1.1'); - $request->headers->set('FORWARDED', '2.2.2.2'); + $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); $dispatcher->addListener(KernelEvents::REQUEST, array(new ValidateRequestListener(), 'onKernelRequest')); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 6a5b2331f713..448dc10cf118 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -287,7 +287,7 @@ public function testInconsistentClientIpsOnMasterRequests() $request = new Request(); $request->setTrustedProxies(array('1.1.1.1')); $request->server->set('REMOTE_ADDR', '1.1.1.1'); - $request->headers->set('FORWARDED', '2.2.2.2'); + $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); $kernel->handle($request, $kernel::MASTER_REQUEST, false); From 43297b45dee44f888d58a3077227a993cf68b930 Mon Sep 17 00:00:00 2001 From: "Anton A. Sumin" Date: Fri, 10 Mar 2017 23:00:21 +0300 Subject: [PATCH 42/80] Fixed pathinfo calculation for requests starting with a question mark. --- .../Component/HttpFoundation/Request.php | 8 ++- .../HttpFoundation/Tests/RequestTest.php | 61 +++++++++++++++++++ .../Security/Http/Tests/HttpUtilsTest.php | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index d659d188ea40..69c47a0d540e 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1774,6 +1774,9 @@ protected function prepareBaseUrl() // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); + if ($requestUri !== '' && $requestUri[0] !== '/') { + $requestUri = '/'.$requestUri; + } if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches @@ -1846,9 +1849,12 @@ protected function preparePathInfo() } // Remove the query string from REQUEST_URI - if ($pos = strpos($requestUri, '?')) { + if (false !== $pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } + if ($requestUri !== '' && $requestUri[0] !== '/') { + $requestUri = '/'.$requestUri; + } $pathInfo = substr($requestUri, strlen($baseUrl)); if (null !== $baseUrl && (false === $pathInfo || '' === $pathInfo)) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 2b852f59565e..876f40be3b44 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1264,6 +1264,12 @@ public function testGetPathInfo() $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/path%20test/info', $request->getPathInfo()); + + $server = array(); + $server['REQUEST_URI'] = '?a=b'; + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertEquals('/', $request->getPathInfo()); } public function testGetPreferredLanguage() @@ -1992,6 +1998,61 @@ public function methodCacheableProvider() array('CONNECT', false), ); } + + public function nonstandardRequestsData() + { + return array( + array('', '', '/', 'http://host:8080/', ''), + array('/', '', '/', 'http://host:8080/', ''), + + array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), + array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), + + array('', 'a=b', '/', 'http://host:8080/?a=b'), + array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'), + array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'), + + array('x', 'a=b', '/x', 'http://host:8080/x?a=b'), + array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), + array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), + + array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), + array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), + + array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), + array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), + array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), + ); + } + + /** + * @dataProvider nonstandardRequestsData + */ + public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null) + { + if (null === $expectedBaseUrl) { + $expectedBaseUrl = $expectedBasePath; + } + + $server = array( + 'HTTP_HOST' => 'host:8080', + 'SERVER_PORT' => '8080', + 'QUERY_STRING' => $queryString, + 'PHP_SELF' => '/hello/app.php', + 'SCRIPT_FILENAME' => '/some/path/app.php', + 'REQUEST_URI' => $requestUri, + ); + + $request = new Request(array(), array(), array(), array(), array(), $server); + + $this->assertEquals($expectedPathInfo, $request->getPathInfo()); + $this->assertEquals($expectedUri, $request->getUri()); + $this->assertEquals($queryString, $request->getQueryString()); + $this->assertEquals(8080, $request->getPort()); + $this->assertEquals('host:8080', $request->getHttpHost()); + $this->assertEquals($expectedBaseUrl, $request->getBaseUrl()); + $this->assertEquals($expectedBasePath, $request->getBasePath()); + } } class RequestContentProxy extends Request diff --git a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php index eb0379f97b4f..3d0e63b6fe1b 100644 --- a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php +++ b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php @@ -144,7 +144,7 @@ public function testCheckRequestPath() // Plus must not decoded to space $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar')); // Checking unicode - $this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход')); + $this->assertTrue($utils->checkRequestPath($this->getRequest('/'.urlencode('вход')), '/вход')); } public function testCheckRequestPathWithUrlMatcherAndResourceNotFound() From 3599c476bf0638d7df5f99232cd570aed2baee0c Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Thu, 16 Mar 2017 13:01:13 +0200 Subject: [PATCH 43/80] [Validator] fix URL validator to detect non supported chars according to RFC 3986 --- src/Symfony/Component/Validator/Constraints/UrlValidator.php | 4 +++- .../Validator/Tests/Constraints/UrlValidatorTest.php | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 401f7d8bdd64..db7244f40ce7 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -34,7 +34,9 @@ class UrlValidator extends ConstraintValidator \] # an IPv6 address ) (:[0-9]+)? # a port (optional) - (/?|/\S+|\?\S*|\#\S*) # a /, nothing, a / with something, a query or a fragment + (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path + (?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional) + (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) $~ixu'; /** diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index 98494c66bf36..39f1708cf18a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -128,6 +128,7 @@ public function getValidUrls() array('http://symfony.com#'), array('http://symfony.com#fragment'), array('http://symfony.com/#fragment'), + array('http://symfony.com/#one_more%20test'), ); } @@ -167,6 +168,9 @@ public function getInvalidUrls() array('http://:password@@symfony.com'), array('http://username:passwordsymfony.com'), array('http://usern@me:password@symfony.com'), + array('http://example.com/exploit.html?'), + array('http://example.com/exploit.html?hel lo'), + array('http://example.com/exploit.html?not_a%hex'), ); } From 3a7fa7ede265d4e2d06c8c4030a1c6ddd8168669 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 17 Mar 2017 12:57:37 +0100 Subject: [PATCH 44/80] Set Date header in Response constructor already --- src/Symfony/Component/HttpFoundation/Response.php | 11 +++++++++++ .../Component/HttpFoundation/Tests/ResponseTest.php | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 9d112d15785d..3eb8bd289ce0 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -201,6 +201,11 @@ public function __construct($content = '', $status = 200, $headers = array()) $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); + + /* RFC2616 - 14.18 says all Responses need to have a Date */ + if (!$this->headers->has('Date')) { + $this->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); + } } /** @@ -329,6 +334,7 @@ public function sendHeaders() return $this; } + /* RFC2616 - 14.18 says all Responses need to have a Date */ if (!$this->headers->has('Date')) { $this->setDate(\DateTime::createFromFormat('U', time())); } @@ -612,6 +618,11 @@ public function mustRevalidate() */ public function getDate() { + /* + RFC2616 - 14.18 says all Responses need to have a Date. + Make sure we provide one even if it the header + has been removed in the meantime. + */ if (!$this->headers->has('Date')) { $this->setDate(\DateTime::createFromFormat('U', time())); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index d73dd3d344c3..453a05a9b022 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -276,8 +276,10 @@ public function testGetDate() $this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the date when the header has been modified'); $response = new Response('', 200); + $now = $this->createDateTimeNow(); $response->headers->remove('Date'); - $this->assertInstanceOf('\DateTime', $response->getDate()); + $date = $response->getDate(); + $this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the current Date when the header has previously been removed'); } public function testGetMaxAge() From d980e706ad43801c5edb2bca52876c12a99934b8 Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Thu, 23 Mar 2017 11:17:21 +0200 Subject: [PATCH 45/80] [WebProfilerBundle] Fix for CSS attribute at Profiler Translation Page --- .../Resources/views/Collector/translation.html.twig | 6 +++--- .../Resources/views/Profiler/profiler.css.twig | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig index 0be04e76117d..da55ef919032 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig @@ -169,10 +169,10 @@ {% for message in messages %} {{ message.locale }} - {{ message.domain }} + {{ message.domain }} {{ message.count }} - {{ message.id }} + {{ message.id }} {% if message.transChoiceNumber is not null %} (pluralization is used) @@ -189,7 +189,7 @@ {% endif %} - {{ message.translation }} + {{ message.translation }} {% endfor %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index b807d0bcf9b5..e36c7fdad1e2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -197,6 +197,9 @@ table tbody ul { .nowrap { white-space: pre; } +.prewrap { + white-space: pre-wrap; +} .newline { display: block; } From 6d23c8c41cb4bdc002e5501bc65e3c34f51780e8 Mon Sep 17 00:00:00 2001 From: Antanas Arvasevicius Date: Wed, 1 Mar 2017 14:16:35 +0200 Subject: [PATCH 46/80] #21809 [SecurityBundle] bugfix: if security provider's name contains upper cases then container didn't compile --- .../DependencyInjection/SecurityExtension.php | 6 ++-- .../app/CamelCasedProviders/bundles.php | 16 ++++++++++ .../app/CamelCasedProviders/config.yml | 30 +++++++++++++++++++ ...amelCasedProvidersCausesExceptionsTest.php | 20 +++++++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 36c16e0dbc7d..2fd12c9436c3 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -509,7 +509,7 @@ private function createUserProviders($config, ContainerBuilder $container) // Parses a tag and returns the id for the related user provider service private function createUserDaoProvider($name, $provider, ContainerBuilder $container) { - $name = $this->getUserProviderId(strtolower($name)); + $name = $this->getUserProviderId($name); // Doctrine Entity and In-memory DAO provider are managed by factories foreach ($this->userProviderFactories as $factory) { @@ -533,7 +533,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta if (isset($provider['chain'])) { $providers = array(); foreach ($provider['chain']['providers'] as $providerName) { - $providers[] = new Reference($this->getUserProviderId(strtolower($providerName))); + $providers[] = new Reference($this->getUserProviderId($providerName)); } $container @@ -548,7 +548,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta private function getUserProviderId($name) { - return 'security.user.provider.concrete.'.$name; + return 'security.user.provider.concrete.'.strtolower($name); } private function createExceptionListener($container, $config, $id, $defaultEntryPoint, $stateless) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php new file mode 100644 index 000000000000..86614bdb891d --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), + new Symfony\Bundle\SecurityBundle\SecurityBundle(), + new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), +); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml new file mode 100644 index 000000000000..0b21534ecf42 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml @@ -0,0 +1,30 @@ +imports: + - { resource: ./../config/framework.yml } + +doctrine: + dbal: + driver: pdo_sqlite + memory: true + charset: UTF8 + + orm: + entity_managers: + default: + + auto_mapping: true + +security: + providers: + camelCasedName: + entity: + class: Symfony\Component\Security\Core\User\User + + firewalls: + default: + anonymous: ~ + provider: camelCasedName + + encoders: + Symfony\Component\Security\Core\User\User: plaintext + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php new file mode 100644 index 000000000000..41db3338da97 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional; + +class CamelCasedProvidersCausesExceptionsTest extends WebTestCase +{ + public function testBugfixExceptionThenCamelCasedProviderIsGiven() + { + $client = $this->createClient(array('test_case' => 'CamelCasedProviders', 'root_config' => 'config.yml')); + } +} From e31d3461ea9a50ad7236a023601aac767d3e8868 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 23 Mar 2017 09:02:44 -0700 Subject: [PATCH 47/80] fixed tests --- .../Tests/Functional/app/CamelCasedProviders/config.yml | 1 - src/Symfony/Bundle/SecurityBundle/composer.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml index 0b21534ecf42..a2850489edd7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml @@ -10,7 +10,6 @@ doctrine: orm: entity_managers: default: - auto_mapping: true security: diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 5251f0138aa5..38bae8b0e0f7 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -37,6 +37,7 @@ "symfony/yaml": "^2.0.5", "symfony/expression-language": "~2.6", "doctrine/doctrine-bundle": "~1.2", + "doctrine/orm": "~2.4,>=2.4.5", "twig/twig": "~1.28|~2.0", "ircmaxell/password-compat": "~1.0" }, From 80af0838f5170a3f7738d69a549dc48073d005c2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 23 Mar 2017 09:07:15 -0700 Subject: [PATCH 48/80] removed test that does not test anything --- .../app/CamelCasedProviders/bundles.php | 16 ---------- .../app/CamelCasedProviders/config.yml | 29 ------------------- ...amelCasedProvidersCausesExceptionsTest.php | 20 ------------- .../Bundle/SecurityBundle/composer.json | 1 - 4 files changed, 66 deletions(-) delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php deleted file mode 100644 index 86614bdb891d..000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/bundles.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -return array( - new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), -); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml deleted file mode 100644 index a2850489edd7..000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProviders/config.yml +++ /dev/null @@ -1,29 +0,0 @@ -imports: - - { resource: ./../config/framework.yml } - -doctrine: - dbal: - driver: pdo_sqlite - memory: true - charset: UTF8 - - orm: - entity_managers: - default: - auto_mapping: true - -security: - providers: - camelCasedName: - entity: - class: Symfony\Component\Security\Core\User\User - - firewalls: - default: - anonymous: ~ - provider: camelCasedName - - encoders: - Symfony\Component\Security\Core\User\User: plaintext - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php deleted file mode 100644 index 41db3338da97..000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CamelCasedProvidersCausesExceptionsTest.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Tests\Functional; - -class CamelCasedProvidersCausesExceptionsTest extends WebTestCase -{ - public function testBugfixExceptionThenCamelCasedProviderIsGiven() - { - $client = $this->createClient(array('test_case' => 'CamelCasedProviders', 'root_config' => 'config.yml')); - } -} diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 38bae8b0e0f7..5251f0138aa5 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -37,7 +37,6 @@ "symfony/yaml": "^2.0.5", "symfony/expression-language": "~2.6", "doctrine/doctrine-bundle": "~1.2", - "doctrine/orm": "~2.4,>=2.4.5", "twig/twig": "~1.28|~2.0", "ircmaxell/password-compat": "~1.0" }, From d50ffa1de7e0474024147b68b69db9b036d5b70d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 21 Mar 2017 09:40:59 +0100 Subject: [PATCH 49/80] normalize paths before making them relative --- .../Component/Filesystem/Filesystem.php | 25 +++++++++++++++++++ .../Filesystem/Tests/FilesystemTest.php | 10 ++++++++ 2 files changed, 35 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 3a5e332b9ece..edfc1b9d46a2 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -362,6 +362,31 @@ public function makePathRelative($endPath, $startPath) $startPathArr = explode('/', trim($startPath, '/')); $endPathArr = explode('/', trim($endPath, '/')); + if ('/' !== $startPath[0]) { + array_shift($startPathArr); + } + + if ('/' !== $endPath[0]) { + array_shift($endPathArr); + } + + $normalizePathArray = function ($pathSegments) { + $result = array(); + + foreach ($pathSegments as $segment) { + if ('..' === $segment) { + array_pop($result); + } else { + $result[] = $segment; + } + } + + return $result; + }; + + $startPathArr = $normalizePathArray($startPathArr); + $endPathArr = $normalizePathArray($endPathArr); + // Find for which directory the common path stops $index = 0; while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index be47a2d0ce72..ab2395cd001c 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -868,6 +868,16 @@ public function providePathsForMakePathRelative() array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'), array('/aab/bb', '/aa', '../aab/bb/'), array('/aab', '/aa', '../aab/'), + array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'), + array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'), + array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'), + array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'), + array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'), + array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), + array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'), + array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'), + array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), + array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'), ); if ('\\' === DIRECTORY_SEPARATOR) { From ef39b704ccbdd6680c71d2d3841c0a8e6277d3ce Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 24 Mar 2017 10:02:28 +0100 Subject: [PATCH 50/80] [Form] Improve the exceptions when trying to get the data in a PRE_SET_DATA listener and the data has not already been set --- src/Symfony/Component/Form/Form.php | 12 +++++ .../Component/Form/Tests/SimpleFormTest.php | 46 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 54b9b39ebd02..87cd15bf47d8 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -408,6 +408,10 @@ public function getData() } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead.'); + } + $this->setData($this->config->getData()); } @@ -428,6 +432,10 @@ public function getNormData() } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set.'); + } + $this->setData($this->config->getData()); } @@ -448,6 +456,10 @@ public function getViewData() } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set.'); + } + $this->setData($this->config->getData()); } diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index 6223d3b39f95..62c94c7490ce 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -903,6 +903,7 @@ public function testViewDataMustBeObjectIfDataClassIsSet() /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead. */ public function testSetDataCannotInvokeItself() { @@ -1084,6 +1085,51 @@ public function testCustomOptionsResolver() $fooType->setDefaultOptions($resolver); } + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead. + */ + public function testCannotCallGetDataInPreSetDataListenerIfDataHasNotAlreadyBeenSet() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set. + */ + public function testCannotCallGetNormDataInPreSetDataListener() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getNormData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set. + */ + public function testCannotCallGetViewDataInPreSetDataListener() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getViewData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + protected function createForm() { return $this->getBuilder()->getForm(); From 967f7a7add84628ac3301a892e920b32aa3488bd Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Fri, 24 Mar 2017 04:23:13 +0100 Subject: [PATCH 51/80] MockArraySessionStorage: updated phpdoc for $bags so that IDE autocompletion would work --- .../HttpFoundation/Session/Storage/MockArraySessionStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index c26cc1334d6a..c932d4003f1a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -58,7 +58,7 @@ class MockArraySessionStorage implements SessionStorageInterface protected $metadataBag; /** - * @var array + * @var array|SessionBagInterface[] */ protected $bags; From d984c73e66ec5bd5ecfe46d62e5f0d9fd732a179 Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Fri, 24 Mar 2017 04:07:57 +0100 Subject: [PATCH 52/80] [HttpFoundation][bugfix] should always be initialized --- .../Storage/MockArraySessionStorage.php | 2 +- .../Storage/MockArraySessionStorageTest.php | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index c26cc1334d6a..78404d7b4405 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -60,7 +60,7 @@ class MockArraySessionStorage implements SessionStorageInterface /** * @var array */ - protected $bags; + protected $bags = array(); /** * Constructor. diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php index 99da778b5fd8..82df5543eb54 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php @@ -97,6 +97,30 @@ public function testGetId() $this->assertNotEquals('', $this->storage->getId()); } + public function testClearClearsBags() + { + $this->storage->clear(); + + $this->assertSame(array(), $this->storage->getBag('attributes')->all()); + $this->assertSame(array(), $this->storage->getBag('flashes')->peekAll()); + } + + public function testClearStartsSession() + { + $this->storage->clear(); + + $this->assertTrue($this->storage->isStarted()); + } + + public function testClearWithNoBagsStartsSession() + { + $storage = new MockArraySessionStorage(); + + $storage->clear(); + + $this->assertTrue($storage->isStarted()); + } + /** * @expectedException \RuntimeException */ From cb1348231a2378ff8af5e69c93e81bf3089bb52f Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 24 Mar 2017 09:57:35 +0100 Subject: [PATCH 53/80] [Console] Escape exception messages --- src/Symfony/Component/Console/Application.php | 3 ++- .../Fixtures/application_renderexception3.txt | 16 ++++++++-------- .../application_renderexception3decorated.txt | 18 +++++++++--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index a9351a589720..32bd8373db22 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -13,6 +13,7 @@ use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\DebugFormatterHelper; use Symfony\Component\Console\Helper\ProcessHelper; use Symfony\Component\Console\Helper\QuestionHelper; @@ -651,7 +652,7 @@ public function renderException($e, $output) } $formatter = $output->getFormatter(); $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { + foreach (preg_split('/\r?\n/', OutputFormatter::escape($e->getMessage())) as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt index 8276137bd886..f41925f52a6e 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt @@ -1,13 +1,13 @@ - - [Exception] - Third exception comment - + + [Exception] + Third exception comment + - - [Exception] - Second exception comment - + + [Exception] + Second exception comment + [Exception] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt index b4a7b018af37..5adccdd70245 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt @@ -1,17 +1,17 @@ -  - [Exception]  - Third exception comment  -  +  + [Exception]  + Third exception comment  +  -  - [Exception]  - Second exception comment  -  +  + [Exception]  + Second exception comment  +     [Exception]  - First exception 

this is html

  + First exception

this is html

   foo3:bar From 0577c7b089916bde9243fee8cfd08fc14fad1eac Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 26 Mar 2017 17:08:59 +0200 Subject: [PATCH 54/80] [Bridge\Doctrine] Fix change breaking doctrine-bundle test suite --- ...egisterEventListenersAndSubscribersPass.php | 7 ++----- ...terEventListenersAndSubscribersPassTest.php | 18 +++++++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index 1ec3ba323b78..cb4a4816db70 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -109,15 +109,12 @@ private function addTaggedListeners(ContainerBuilder $container) throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); } - if ($lazy = isset($tag['lazy']) && $tag['lazy']) { + if ($lazy = !empty($tag['lazy'])) { $taggedListenerDef->setPublic(true); } // we add one call per event per service so we have the correct order - $this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array( - $tag['event'], - $lazy ? $id : new Reference($id), - )); + $this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array(array($tag['event']), $lazy ? $id : new Reference($id))); } } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php index 6e4eb202984e..7e99a7d9356c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php @@ -90,11 +90,11 @@ public function testProcessEventListenersWithPriorities() $this->assertEquals( array( - array('addEventListener', array('foo_bar', new Reference('c'))), - array('addEventListener', array('foo_bar', new Reference('a'))), - array('addEventListener', array('bar', new Reference('a'))), - array('addEventListener', array('foo', new Reference('b'))), - array('addEventListener', array('foo', new Reference('a'))), + array('addEventListener', array(array('foo_bar'), new Reference('c'))), + array('addEventListener', array(array('foo_bar'), new Reference('a'))), + array('addEventListener', array(array('bar'), new Reference('a'))), + array('addEventListener', array(array('foo'), new Reference('b'))), + array('addEventListener', array(array('foo'), new Reference('a'))), ), $methodCalls ); @@ -138,16 +138,16 @@ public function testProcessEventListenersWithMultipleConnections() $this->assertEquals( array( - array('addEventListener', array('onFlush', new Reference('a'))), - array('addEventListener', array('onFlush', new Reference('b'))), + array('addEventListener', array(array('onFlush'), new Reference('a'))), + array('addEventListener', array(array('onFlush'), new Reference('b'))), ), $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() ); $this->assertEquals( array( - array('addEventListener', array('onFlush', new Reference('a'))), - array('addEventListener', array('onFlush', new Reference('c'))), + array('addEventListener', array(array('onFlush'), new Reference('a'))), + array('addEventListener', array(array('onFlush'), new Reference('c'))), ), $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls() ); From dbcfa5c65938fb134089aa41ef23079be02afa5f Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Mon, 27 Mar 2017 07:41:37 +0200 Subject: [PATCH 55/80] Remove port from default host in server:status command --- .../Bundle/FrameworkBundle/Command/ServerStatusCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php index fa5c537a0c97..58871896c651 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php @@ -31,7 +31,7 @@ protected function configure() { $this ->setDefinition(array( - new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'), + new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'), new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'), )) ->setName('server:status') From ba8f46ad237f7d81d3917406caf5a2b1eabc4eb8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 27 Mar 2017 16:31:27 +0200 Subject: [PATCH 56/80] [HttpKernel] Fix test --- .../Tests/EventListener/ValidateRequestListenerTest.php | 2 +- src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php index 8311a76e35a0..55dc59e13f71 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php @@ -32,7 +32,7 @@ public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps() $request = new Request(); $request->setTrustedProxies(array('1.1.1.1')); $request->server->set('REMOTE_ADDR', '1.1.1.1'); - $request->headers->set('FORWARDED', '2.2.2.2'); + $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); $dispatcher->addListener(KernelEvents::REQUEST, array(new ValidateRequestListener(), 'onKernelRequest')); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 6a5b2331f713..448dc10cf118 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -287,7 +287,7 @@ public function testInconsistentClientIpsOnMasterRequests() $request = new Request(); $request->setTrustedProxies(array('1.1.1.1')); $request->server->set('REMOTE_ADDR', '1.1.1.1'); - $request->headers->set('FORWARDED', '2.2.2.2'); + $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); $kernel->handle($request, $kernel::MASTER_REQUEST, false); From 3fe419cf66a8a9f033db54186896b142c5cbcada Mon Sep 17 00:00:00 2001 From: Julien Falque Date: Tue, 28 Mar 2017 08:19:43 +0200 Subject: [PATCH 57/80] Disable color support detection for tests --- src/Symfony/Component/Console/Tester/CommandTester.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Tester/CommandTester.php b/src/Symfony/Component/Console/Tester/CommandTester.php index f95298bc90c7..609f46a654da 100644 --- a/src/Symfony/Component/Console/Tester/CommandTester.php +++ b/src/Symfony/Component/Console/Tester/CommandTester.php @@ -70,9 +70,7 @@ public function execute(array $input, array $options = array()) } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } + $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false); if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } From d64679014b5eb6b36594f5d7062ad07f9ef198ab Mon Sep 17 00:00:00 2001 From: Niels Keurentjes Date: Sat, 25 Mar 2017 00:33:11 +0100 Subject: [PATCH 58/80] [WebProfilerBundle] Normalize whitespace in exceptions passed in headers If an exception was thrown with line separators in its message the WebProfiler would cause an exception by passing it through unsanitized into the X-Debug-Error HTTP header. This commit fixes that by replacing all whitespace sequences with a single space in the header. --- .../EventListener/WebDebugToolbarListener.php | 2 +- .../WebDebugToolbarListenerTest.php | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php index 71c5090fc8a5..09d2b9ba92e5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php +++ b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php @@ -68,7 +68,7 @@ public function onKernelResponse(FilterResponseEvent $event) $this->urlGenerator->generate('_profiler', array('token' => $response->headers->get('X-Debug-Token'))) ); } catch (\Exception $e) { - $response->headers->set('X-Debug-Error', get_class($e).': '.$e->getMessage()); + $response->headers->set('X-Debug-Error', get_class($e).': '.preg_replace('/\s+/', ' ', $e->getMessage())); } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php index 446aefb793e8..a121035b7d53 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php @@ -228,6 +228,27 @@ public function testThrowingUrlGenerator() $this->assertEquals('Exception: foo', $response->headers->get('X-Debug-Error')); } + public function testThrowingErrorCleanup() + { + $response = new Response(); + $response->headers->set('X-Debug-Token', 'xxxxxxxx'); + + $urlGenerator = $this->getUrlGeneratorMock(); + $urlGenerator + ->expects($this->once()) + ->method('generate') + ->with('_profiler', array('token' => 'xxxxxxxx')) + ->will($this->throwException(new \Exception("This\nmultiline\r\ntabbed text should\tcome out\r on\n \ta single plain\r\nline"))) + ; + + $event = new FilterResponseEvent($this->getKernelMock(), $this->getRequestMock(), HttpKernelInterface::MASTER_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, 'bottom', $urlGenerator); + $listener->onKernelResponse($event); + + $this->assertEquals('Exception: This multiline tabbed text should come out on a single plain line', $response->headers->get('X-Debug-Error')); + } + protected function getRequestMock($isXmlHttpRequest = false, $requestFormat = 'html', $hasSession = true) { $request = $this->getMock( From 17f1f079b2cec445e1e10b4f9dc936534b8b029d Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 27 Mar 2017 22:18:06 +0200 Subject: [PATCH 59/80] [Console] Revised exception rendering --- src/Symfony/Component/Console/Application.php | 13 ++++++------- .../Component/Console/Tests/ApplicationTest.php | 16 ++++++++++++++++ .../application_renderexception_escapeslines.txt | 9 +++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 32bd8373db22..bc5e9ee66c09 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -650,12 +650,11 @@ public function renderException($e, $output) if (defined('HHVM_VERSION') && $width > 1 << 31) { $width = 1 << 31; } - $formatter = $output->getFormatter(); $lines = array(); - foreach (preg_split('/\r?\n/', OutputFormatter::escape($e->getMessage())) as $line) { + foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length - $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; + $lineLength = $this->stringWidth($line) + 4; $lines[] = array($line, $lineLength); $len = max($lineLength, $len); @@ -663,15 +662,15 @@ public function renderException($e, $output) } $messages = array(); - $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); - $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title))))); + $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); + $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))); foreach ($lines as $line) { - $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); + $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); } $messages[] = $emptyLine; $messages[] = ''; - $output->writeln($messages, OutputInterface::OUTPUT_RAW); + $output->writeln($messages); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('Exception trace:'); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 895fdb926142..df6d1976e719 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -591,6 +591,22 @@ public function testRenderExceptionWithDoubleWidthCharacters() $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal'); } + public function testRenderExceptionEscapesLines() + { + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock(); + $application->setAutoExit(false); + $application->expects($this->any()) + ->method('getTerminalWidth') + ->will($this->returnValue(22)); + $application->register('foo')->setCode(function () { + throw new \Exception('dont break here !'); + }); + $tester = new ApplicationTester($application); + + $tester->run(array('command' => 'foo'), array('decorated' => false)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); + } + public function testRun() { $application = new Application(); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt new file mode 100644 index 000000000000..cf79b37a92d6 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt @@ -0,0 +1,9 @@ + + + [Exception] + dont break here < + info>! + + +foo + From 53ecf8393e976dd1585e9230e0cd4d1997d31760 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Wed, 29 Mar 2017 15:52:26 +0200 Subject: [PATCH 60/80] [Console] Fix table cell styling --- .../Component/Console/Helper/Helper.php | 7 ++++- .../Component/Console/Helper/Table.php | 11 ++++--- .../Console/Tests/Helper/TableTest.php | 29 +++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 90979d5b9d5e..b429e630c721 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -109,6 +109,11 @@ public static function formatMemory($memory) } public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) + { + return self::strlen(self::removeDecoration($formatter, $string)); + } + + public static function removeDecoration(OutputFormatterInterface $formatter, $string) { $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); @@ -118,6 +123,6 @@ public static function strlenWithoutDecoration(OutputFormatterInterface $formatt $string = preg_replace("/\033\[[^m]*m/", '', $string); $formatter->setDecorated($isDecorated); - return self::strlen($string); + return $string; } } diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 8728e33d8396..11bed884c2ac 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -341,7 +341,7 @@ private function buildTableRows($rows) if (!strstr($cell, "\n")) { continue; } - $lines = explode("\n", $cell); + $lines = explode("\n", str_replace("\n", "\n", $cell)); foreach ($lines as $lineKey => $line) { if ($cell instanceof TableCell) { $line = new TableCell($line, array('colspan' => $cell->getColspan())); @@ -382,7 +382,7 @@ private function fillNextRows($rows, $line) $nbLines = $cell->getRowspan() - 1; $lines = array($cell); if (strstr($cell, "\n")) { - $lines = explode("\n", $cell); + $lines = explode("\n", str_replace("\n", "\n", $cell)); $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan())); @@ -514,6 +514,8 @@ private function getColumnWidth($column) return $this->columnWidths[$column]; } + $lengths = array(); + foreach (array_merge($this->headers, $this->rows) as $row) { if ($row instanceof TableSeparator) { continue; @@ -521,9 +523,10 @@ private function getColumnWidth($column) foreach ($row as $i => $cell) { if ($cell instanceof TableCell) { - $textLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::strlen($textContent); if ($textLength > 0) { - $contentColumns = str_split($cell, ceil($textLength / $cell->getColspan())); + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 5fe6b645602f..0e984324e709 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -511,6 +511,35 @@ public function renderProvider() | Dante Alighieri | J. R. R. Tolkien | J. R. R | +-----------------+------------------+---------+ +TABLE + , + true, + ), + 'Row with formatted cells containing a newline' => array( + array(), + array( + array( + new TableCell('Dont break'."\n".'here', array('colspan' => 2)), + ), + new TableSeparator(), + array( + 'foo', + new TableCell('Dont break'."\n".'here', array('rowspan' => 2)), + ), + array( + 'bar', + ), + ), + 'default', + <<<'TABLE' ++-------+------------+ +| Dont break | +| here | ++-------+------------+ +| foo | Dont break | +| bar | here | ++-------+------------+ + TABLE , true, From dc55db2a9db59dacfca599ec5efc3b5e985767ba Mon Sep 17 00:00:00 2001 From: Philipp Kretzschmar Date: Wed, 27 Jul 2016 18:41:51 +0200 Subject: [PATCH 61/80] add expression text to SyntaxError fixes #19445 --- .../Component/ExpressionLanguage/Lexer.php | 5 +-- .../ExpressionLanguage/SyntaxError.php | 10 ++++-- .../ExpressionLanguage/Tests/LexerTest.php | 33 +++++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index 26bb51d42e35..3d3aba25add1 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -87,7 +87,8 @@ public function tokenize($expression) $cursor += strlen($match[0]); } else { // unlexable - throw new SyntaxError(sprintf('Unexpected character "%s"', $expression[$cursor]), $cursor); + $message = sprintf('Unexpected character "%s"', $expression[$cursor]); + throw new SyntaxError($message, $cursor, $expression); } } @@ -95,7 +96,7 @@ public function tokenize($expression) if (!empty($brackets)) { list($expect, $cur) = array_pop($brackets); - throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur); + throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur, $expression); } return new TokenStream($tokens); diff --git a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php index d149c00768ad..c30f6e62f778 100644 --- a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php +++ b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php @@ -13,8 +13,14 @@ class SyntaxError extends \LogicException { - public function __construct($message, $cursor = 0) + public function __construct($message, $cursor = 0, $expression = '') { - parent::__construct(sprintf('%s around position %d.', $message, $cursor)); + $message = sprintf('%s around position %d', $message, $cursor); + if ($expression) { + $message = sprintf('%s for expression "%s"', $message, $expression); + } + $message .= '.'; + + parent::__construct($message); } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php index 4292c2235969..a28537493d97 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php @@ -18,14 +18,43 @@ class LexerTest extends TestCase { + /** + * @var Lexer + */ + private $lexer; + + protected function setUp() + { + $this->lexer = new Lexer(); + } + /** * @dataProvider getTokenizeData */ public function testTokenize($tokens, $expression) { $tokens[] = new Token('end of expression', null, strlen($expression) + 1); - $lexer = new Lexer(); - $this->assertEquals(new TokenStream($tokens), $lexer->tokenize($expression)); + $this->assertEquals(new TokenStream($tokens), $this->lexer->tokenize($expression)); + } + + /** + * @expectedException Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Unexpected character "'" around position 33 for expression "service(faulty.expression.example').dummyMethod()". + */ + public function testTokenizeThrowsErrorWithMessage() + { + $expression = "service(faulty.expression.example').dummyMethod()"; + $this->lexer->tokenize($expression); + } + + /** + * @expectedException Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Unclosed "(" around position 7 for expression "service(unclosed.expression.dummyMethod()". + */ + public function testTokenizeThrowsErrorOnUnclosedBrace() + { + $expression = 'service(unclosed.expression.dummyMethod()'; + $this->lexer->tokenize($expression); } public function getTokenizeData() From fb4d8de5e4c99d074d6b8f67f9251671014a931b Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Fri, 31 Mar 2017 10:23:48 +0200 Subject: [PATCH 62/80] Avoid forcing to define the choices_as_values option when using choice_loader When using the choice loader, choices are ignored entirely. Forcing the dev to add the choices_as_values just to avoid the deprecation warning (and then to remove the option again at some point in 3.x due to deprecation) is a bad developer experience. --- src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 26f7c80f1766..61907067f576 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -357,7 +357,7 @@ public function configureOptions(OptionsResolver $resolver) }; $choicesAsValuesNormalizer = function (Options $options, $choicesAsValues) use ($that) { - if (true !== $choicesAsValues) { + if (true !== $choicesAsValues && null === $options['choice_loader']) { @trigger_error(sprintf('The value "false" for the "choices_as_values" option of the "%s" form type (%s) is deprecated since version 2.8 and will not be supported anymore in 3.0. Set this option to "true" and flip the contents of the "choices" option instead.', $that->getName(), __CLASS__), E_USER_DEPRECATED); } From 071548090bbd098347729ade45c020c5cc7bfcef Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Fri, 31 Mar 2017 14:24:41 +0200 Subject: [PATCH 63/80] Fix tests expecting a valid date --- .../Component/Form/Tests/Extension/Core/Type/DateTypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index d907c9c3d15e..05fc63f055b5 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -598,7 +598,7 @@ public function testIsSynchronizedReturnsTrueIfChoiceAndCompletelyFilled() )); $form->submit(array( - 'day' => '0', + 'day' => '1', 'month' => '6', 'year' => '2010', )); From 9a1915f88bf3ffc6b40a6342ff604c5eff368223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ostroluck=C3=BD?= Date: Sat, 1 Apr 2017 00:21:40 +0200 Subject: [PATCH 64/80] [EventDispatcher] Remove unneded count() --- src/Symfony/Component/EventDispatcher/EventDispatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 87aca2d480ec..d54ecad6bd36 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -80,7 +80,7 @@ public function getListeners($eventName = null) */ public function hasListeners($eventName = null) { - return (bool) count($this->getListeners($eventName)); + return (bool) $this->getListeners($eventName); } /** From 75d5cb1bad123378a0b2202647dd172609a7a541 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 2 Apr 2017 15:23:09 +0200 Subject: [PATCH 65/80] Disable resource tracking if the config component is missing --- .../Component/DependencyInjection/ContainerBuilder.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 496adb9426fc..5bafa94398e6 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -26,6 +26,7 @@ use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; @@ -73,7 +74,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $compiler; - private $trackResources = true; + private $trackResources; /** * @var InstantiatorInterface|null @@ -90,6 +91,13 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $expressionLanguageProviders = array(); + public function __construct(ParameterBagInterface $parameterBag = null) + { + parent::__construct($parameterBag); + + $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface'); + } + /** * Sets the track resources flag. * From 0f623f422019fb450feb2fda0c1aac91b9c6d162 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Fri, 31 Mar 2017 11:34:31 +0200 Subject: [PATCH 66/80] CS: Remove invisible chars --- .../DataTransformer/PercentToLocalizedStringTransformer.php | 2 +- .../Component/Form/Extension/Validator/ValidatorExtension.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 88531feaa222..7fc191a054ff 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -120,7 +120,7 @@ public function reverseTransform($value) $formatter = $this->getNumberFormatter(); // replace normal spaces so that the formatter can read them - $value = $formatter->parse(str_replace(' ', ' ', $value)); + $value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value)); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php index e7ed95c459d0..5548493e8c9c 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php @@ -59,7 +59,7 @@ public function __construct($validator) public function loadTypeGuesser() { - // 2.5 API + // 2.5 API if ($this->validator instanceof ValidatorInterface) { return new ValidatorTypeGuesser($this->validator); } From 7cd744133d74a976f69a33d0dbc1d5983dc30642 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Fri, 31 Mar 2017 10:01:13 +0200 Subject: [PATCH 67/80] Complete the injection of the expression in all syntax errors --- .../Component/ExpressionLanguage/Lexer.php | 9 ++++---- .../Component/ExpressionLanguage/Parser.php | 14 ++++++------- .../ExpressionLanguage/SyntaxError.php | 2 +- .../ExpressionLanguage/Tests/LexerTest.php | 10 ++++----- .../ExpressionLanguage/Tests/ParserTest.php | 4 ++-- .../ExpressionLanguage/TokenStream.php | 21 +++++++++++++++---- 6 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index 3d3aba25add1..8c10b72d8604 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -59,12 +59,12 @@ public function tokenize($expression) } elseif (false !== strpos(')]}', $expression[$cursor])) { // closing bracket if (empty($brackets)) { - throw new SyntaxError(sprintf('Unexpected "%s"', $expression[$cursor]), $cursor); + throw new SyntaxError(sprintf('Unexpected "%s"', $expression[$cursor]), $cursor, $expression); } list($expect, $cur) = array_pop($brackets); if ($expression[$cursor] != strtr($expect, '([{', ')]}')) { - throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur); + throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur, $expression); } $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); @@ -87,8 +87,7 @@ public function tokenize($expression) $cursor += strlen($match[0]); } else { // unlexable - $message = sprintf('Unexpected character "%s"', $expression[$cursor]); - throw new SyntaxError($message, $cursor, $expression); + throw new SyntaxError(sprintf('Unexpected character "%s"', $expression[$cursor]), $cursor, $expression); } } @@ -99,6 +98,6 @@ public function tokenize($expression) throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur, $expression); } - return new TokenStream($tokens); + return new TokenStream($tokens, $expression); } } diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index f121ad9a9cdd..6f9045152229 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -99,7 +99,7 @@ public function parse(TokenStream $stream, $names = array()) $node = $this->parseExpression(); if (!$stream->isEOF()) { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $stream->current->type, $stream->current->value), $stream->current->cursor); + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $stream->current->type, $stream->current->value), $stream->current->cursor, $stream->getExpression()); } return $node; @@ -195,13 +195,13 @@ public function parsePrimaryExpression() default: if ('(' === $this->stream->current->value) { if (false === isset($this->functions[$token->value])) { - throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor); + throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression()); } $node = new Node\FunctionNode($token->value, $this->parseArguments()); } else { if (!in_array($token->value, $this->names, true)) { - throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor); + throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression()); } // is the name used in the compiled code different @@ -227,7 +227,7 @@ public function parsePrimaryExpression() } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); } else { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $token->type, $token->value), $token->cursor); + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $token->type, $token->value), $token->cursor, $this->stream->getExpression()); } } @@ -289,7 +289,7 @@ public function parseHashExpression() } else { $current = $this->stream->current; - throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', $current->type, $current->value), $current->cursor); + throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', $current->type, $current->value), $current->cursor, $this->stream->getExpression()); } $this->stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); @@ -327,7 +327,7 @@ public function parsePostfixExpression($node) // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown. ($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) ) { - throw new SyntaxError('Expected name', $token->cursor); + throw new SyntaxError('Expected name', $token->cursor, $this->stream->getExpression()); } $arg = new Node\ConstantNode($token->value); @@ -345,7 +345,7 @@ public function parsePostfixExpression($node) $node = new Node\GetAttrNode($node, $arg, $arguments, $type); } elseif ('[' === $token->value) { if ($node instanceof Node\GetAttrNode && Node\GetAttrNode::METHOD_CALL === $node->attributes['type'] && PHP_VERSION_ID < 50400) { - throw new SyntaxError('Array calls on a method call is only supported on PHP 5.4+', $token->cursor); + throw new SyntaxError('Array calls on a method call is only supported on PHP 5.4+', $token->cursor, $this->stream->getExpression()); } $this->stream->next(); diff --git a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php index c30f6e62f778..9373e9980b8f 100644 --- a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php +++ b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php @@ -17,7 +17,7 @@ public function __construct($message, $cursor = 0, $expression = '') { $message = sprintf('%s around position %d', $message, $cursor); if ($expression) { - $message = sprintf('%s for expression "%s"', $message, $expression); + $message = sprintf('%s for expression `%s`', $message, $expression); } $message .= '.'; diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php index a28537493d97..87c16f707b92 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php @@ -34,12 +34,12 @@ protected function setUp() public function testTokenize($tokens, $expression) { $tokens[] = new Token('end of expression', null, strlen($expression) + 1); - $this->assertEquals(new TokenStream($tokens), $this->lexer->tokenize($expression)); + $this->assertEquals(new TokenStream($tokens, $expression), $this->lexer->tokenize($expression)); } /** - * @expectedException Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Unexpected character "'" around position 33 for expression "service(faulty.expression.example').dummyMethod()". + * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Unexpected character "'" around position 33 for expression `service(faulty.expression.example').dummyMethod()`. */ public function testTokenizeThrowsErrorWithMessage() { @@ -48,8 +48,8 @@ public function testTokenizeThrowsErrorWithMessage() } /** - * @expectedException Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Unclosed "(" around position 7 for expression "service(unclosed.expression.dummyMethod()". + * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Unclosed "(" around position 7 for expression `service(unclosed.expression.dummyMethod()`. */ public function testTokenizeThrowsErrorOnUnclosedBrace() { diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 8996d5bfa023..b4cfff6d1e75 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -20,7 +20,7 @@ class ParserTest extends TestCase { /** * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Variable "foo" is not valid around position 1. + * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`. */ public function testParseWithInvalidName() { @@ -31,7 +31,7 @@ public function testParseWithInvalidName() /** * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Variable "foo" is not valid around position 1. + * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`. */ public function testParseWithZeroInNames() { diff --git a/src/Symfony/Component/ExpressionLanguage/TokenStream.php b/src/Symfony/Component/ExpressionLanguage/TokenStream.php index 6c4af745b2cf..3c22fc1d46ed 100644 --- a/src/Symfony/Component/ExpressionLanguage/TokenStream.php +++ b/src/Symfony/Component/ExpressionLanguage/TokenStream.php @@ -22,16 +22,19 @@ class TokenStream private $tokens; private $position = 0; + private $expression; /** * Constructor. * - * @param array $tokens An array of tokens + * @param array $tokens An array of tokens + * @param string $expression */ - public function __construct(array $tokens) + public function __construct(array $tokens, $expression = '') { $this->tokens = $tokens; $this->current = $tokens[0]; + $this->expression = $expression; } /** @@ -50,7 +53,7 @@ public function __toString() public function next() { if (!isset($this->tokens[$this->position])) { - throw new SyntaxError('Unexpected end of expression', $this->current->cursor); + throw new SyntaxError('Unexpected end of expression', $this->current->cursor, $this->expression); } ++$this->position; @@ -69,7 +72,7 @@ public function expect($type, $value = null, $message = null) { $token = $this->current; if (!$token->test($type, $value)) { - throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor); + throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor, $this->expression); } $this->next(); } @@ -83,4 +86,14 @@ public function isEOF() { return $this->current->type === Token::EOF_TYPE; } + + /** + * @internal + * + * @return string + */ + public function getExpression() + { + return $this->expression; + } } From 74ee588924cf2e88a5c64d48d6e6ea1283b77bdc Mon Sep 17 00:00:00 2001 From: Arthur de Moulins Date: Mon, 3 Apr 2017 11:21:18 +0200 Subject: [PATCH 68/80] support nullable array or collection --- .../Component/PropertyInfo/Extractor/PhpDocExtractor.php | 6 +++--- .../PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php | 1 + .../Tests/Extractors/ReflectionExtractorTest.php | 1 + .../Component/PropertyInfo/Tests/Fixtures/Dummy.php | 7 +++++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 73e8ad374897..b6b39cc0fc5e 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -242,7 +242,7 @@ private function getDocBlockFromProperty($class, $property) * @param string $ucFirstProperty * @param int $type * - * @return DocBlock|null + * @return array|null */ private function getDocBlockFromMethod($class, $ucFirstProperty, $type) { @@ -337,10 +337,10 @@ private function createType($docType, $nullable) $collectionValueType = null; } else { $collectionKeyType = new Type(Type::BUILTIN_TYPE_INT); - $collectionValueType = new Type($phpType, false, $class); + $collectionValueType = new Type($phpType, $nullable, $class); } - return new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, $collectionKeyType, $collectionValueType); + return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType); } return new Type($phpType, $nullable, $class); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index 10439974820b..6477ba196772 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -68,6 +68,7 @@ public function typesProvider() array('d', array(new Type(Type::BUILTIN_TYPE_BOOL)), null, null), array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null), array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), + array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), array('donotexist', null, null, null), array('staticGetter', null, null, null), array('staticSetter', null, null, null), diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index 7818d0dd4004..6af92affe03d 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -38,6 +38,7 @@ public function testGetProperties() 'parent', 'collection', 'B', + 'g', 'foo', 'foo2', 'foo3', diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 96cb87db4a8f..12065b18b62a 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -51,6 +51,13 @@ class Dummy extends ParentDummy */ public $B; + /** + * Nullable array. + * + * @var array|null + */ + public $g; + public static function getStatic() { } From 8c8b181f063b30b9d4df17fe6b1e9c05516525eb Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Mon, 3 Apr 2017 10:42:32 +0200 Subject: [PATCH 69/80] Lighten tests output by removing composer suggestions --- .travis.yml | 6 +++--- appveyor.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 088de9fec465..7205200d85e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -79,7 +79,7 @@ install: - export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev - if [[ ! $skip && $deps ]]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi - if [[ ! $skip && $deps ]]; then mv composer.json.phpunit composer.json; fi - - if [[ ! $skip ]]; then composer update; fi + - if [[ ! $skip ]]; then composer update --no-suggest; fi - if [[ ! $skip ]]; then ./phpunit install; fi - if [[ ! $skip && ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi @@ -90,5 +90,5 @@ script: - if [[ ! $deps && ! $PHP = hhvm* ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi - if [[ ! $deps && $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data; fi - if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi - - if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY"$REPORT"; fi - - if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'"$REPORT"; fi + - if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --no-suggest --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY"$REPORT"; fi + - if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --no-suggest --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'"$REPORT"; fi diff --git a/appveyor.yml b/appveyor.yml index 5f3953ed8acc..86a943c77c42 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,7 +53,7 @@ install: - 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 composer.phar update --no-progress --ansi + - php composer.phar update --no-progress --no-suggest --ansi - php phpunit install test_script: From 992c6775340b53ab0e2f756ac512929581135305 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 3 Apr 2017 17:01:14 +0200 Subject: [PATCH 70/80] [DI] Don't use auto-registered services to populate type-candidates --- .../Compiler/AutowirePass.php | 56 +++++++++++-------- .../Tests/Compiler/AutowirePassTest.php | 21 ------- 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 9454d1bd4b1a..445a544f4149 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -28,7 +28,7 @@ class AutowirePass implements CompilerPassInterface private $definedTypes = array(); private $types; private $notGuessableTypes = array(); - private $usedTypes = array(); + private $autowired = array(); /** * {@inheritdoc} @@ -45,15 +45,6 @@ public function process(ContainerBuilder $container) $this->completeDefinition($id, $definition); } } - - foreach ($this->usedTypes as $type => $id) { - if (isset($this->usedTypes[$type]) && isset($this->notGuessableTypes[$type])) { - $classOrInterface = class_exists($type) ? 'class' : 'interface'; - $matchingServices = implode(', ', $this->types[$type]); - - throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices)); - } - } } catch (\Exception $e) { } catch (\Throwable $e) { } @@ -66,7 +57,7 @@ public function process(ContainerBuilder $container) $this->definedTypes = array(); $this->types = null; $this->notGuessableTypes = array(); - $this->usedTypes = array(); + $this->autowired = array(); if (isset($e)) { throw $e; @@ -92,47 +83,56 @@ private function completeDefinition($id, Definition $definition) if (!$constructor = $reflectionClass->getConstructor()) { return; } + $parameters = $constructor->getParameters(); + if (method_exists('ReflectionMethod', 'isVariadic') && $constructor->isVariadic()) { + array_pop($parameters); + } $arguments = $definition->getArguments(); - foreach ($constructor->getParameters() as $index => $parameter) { + foreach ($parameters as $index => $parameter) { if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) { continue; } try { if (!$typeHint = $parameter->getClass()) { + if (isset($arguments[$index])) { + continue; + } + // no default value? Then fail if (!$parameter->isOptional()) { throw new RuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id)); } - if (!array_key_exists($index, $arguments)) { - // specifically pass the default value - $arguments[$index] = $parameter->getDefaultValue(); - } + // specifically pass the default value + $arguments[$index] = $parameter->getDefaultValue(); continue; } + if (isset($this->autowired[$typeHint->name])) { + return $this->autowired[$typeHint->name] ? new Reference($this->autowired[$typeHint->name]) : null; + } + if (null === $this->types) { $this->populateAvailableTypes(); } if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) { $value = new Reference($this->types[$typeHint->name]); - $this->usedTypes[$typeHint->name] = $id; } else { try { $value = $this->createAutowiredDefinition($typeHint, $id); - $this->usedTypes[$typeHint->name] = $id; } catch (RuntimeException $e) { - if ($parameter->allowsNull()) { - $value = null; - } elseif ($parameter->isDefaultValueAvailable()) { + if ($parameter->isDefaultValueAvailable()) { $value = $parameter->getDefaultValue(); + } elseif ($parameter->allowsNull()) { + $value = null; } else { throw $e; } + $this->autowired[$typeHint->name] = false; } } } catch (\ReflectionException $e) { @@ -148,6 +148,16 @@ private function completeDefinition($id, Definition $definition) $arguments[$index] = $value; } + if ($parameters && !isset($arguments[++$index])) { + while (0 <= --$index) { + $parameter = $parameters[$index]; + if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) { + break; + } + unset($arguments[$index]); + } + } + // it's possible index 1 was set, then index 0, then 2, etc // make sure that we re-order so they're injected as expected ksort($arguments); @@ -252,13 +262,11 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id) throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface)); } - $argumentId = sprintf('autowired.%s', $typeHint->name); + $this->autowired[$typeHint->name] = $argumentId = sprintf('autowired.%s', $typeHint->name); $argumentDefinition = $this->container->register($argumentId, $typeHint->name); $argumentDefinition->setPublic(false); - $this->populateAvailableType($argumentId, $argumentDefinition); - try { $this->completeDefinition($argumentId, $argumentDefinition); } catch (RuntimeException $e) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 047801ceba8e..9a41fa2ee0da 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -422,10 +422,6 @@ public function testOptionalScalarArgsNotPassedIfLast() array( new Reference('a'), new Reference('lille'), - // third arg shouldn't *need* to be passed - // but that's hard to "pull of" with autowiring, so - // this assumes passing the default val is ok - 'some_val', ), $definition->getArguments() ); @@ -462,23 +458,6 @@ public function testEmptyStringIsKept() $this->assertEquals(array(new Reference('a'), '', new Reference('lille')), $container->getDefinition('foo')->getArguments()); } - /** - * @dataProvider provideAutodiscoveredAutowiringOrder - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMEssage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA, autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB). - */ - public function testAutodiscoveredAutowiringOrder($class) - { - $container = new ContainerBuilder(); - - $container->register('a', __NAMESPACE__.'\\'.$class) - ->setAutowired(true); - - $pass = new AutowirePass(); - $pass->process($container); - } - public function provideAutodiscoveredAutowiringOrder() { return array( From 9b601633a724bf50d8479bf70e46bd33dc19ae5c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 3 Apr 2017 20:00:43 +0200 Subject: [PATCH 71/80] [DI] Autowiring and factories are incompatible with each others --- .../Compiler/AutowirePass.php | 4 ++++ .../Tests/Compiler/AutowirePassTest.php | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 9454d1bd4b1a..8acf2856d5e1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -83,6 +83,10 @@ public function process(ContainerBuilder $container) */ private function completeDefinition($id, Definition $definition) { + if ($definition->getFactory() || $definition->getFactoryClass(false) || $definition->getFactoryService(false)) { + throw new RuntimeException(sprintf('Service "%s" can use either autowiring or a factory, not both.', $id)); + } + if (!$reflectionClass = $this->getReflectionClass($id, $definition)) { return; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 047801ceba8e..6c17fcd66bb0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -486,6 +486,22 @@ public function provideAutodiscoveredAutowiringOrder() array('CannotBeAutowiredReverseOrder'), ); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Service "a" can use either autowiring or a factory, not both. + */ + public function testWithFactory() + { + $container = new ContainerBuilder(); + + $container->register('a', __NAMESPACE__.'\A') + ->setFactory('foo') + ->setAutowired(true); + + $pass = new AutowirePass(); + $pass->process($container); + } } class Foo From 8cf344b2af6b1dc8885fb63b045e9771dec75f6e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Apr 2017 21:27:56 -0700 Subject: [PATCH 72/80] updated CHANGELOG for 2.7.26 --- CHANGELOG-2.7.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 5e137e4366aa..bc4c0fa89d5f 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,37 @@ 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.26 (2017-04-04) + + * bug #22229 [ExpressionLanguage] Provide the expression in syntax errors (k0pernikus, stof) + * bug #22240 [DI] Fix fatal error at ContainerBuilder::compile() if config is not installed (chalasr) + * bug #22140 [Form] Improve the exceptions when trying to get the data in a PRE_SET_DATA listener and the data has not already been set (fancyweb) + * bug #22217 [Console] Fix table cell styling (ro0NL) + * bug #22194 [Console] CommandTester: disable color support detection (julienfalque) + * bug #22188 [Console] Revised exception rendering (ro0NL) + * bug #22154 [WebProfilerBundle] Normalize whitespace in exceptions passed in headers (curry684) + * bug #22142 [Console] Escape exception messages in renderException (chalasr) + * bug #22172 Fix port usage in server:status command (alcaeus) + * bug #22164 [Bridge\Doctrine] Fix change breaking doctrine-bundle test suite (nicolas-grekas) + * bug #22133 [Filesystem] normalize paths before making them relative (xabbuh) + * bug #22138 [HttpFoundation][bugfix] $bags should always be initialized (MacDada) + * bug #21810 #21809 [SecurityBundle] bugfix: if security provider's name contains upper cases then container didn't compile (Antanas Arvasevicius) + * bug #19778 [Security] Fixed roles serialization on token from user object (eko) + * bug #22022 [Validator] fix URL validator to detect non supported chars according to RFC 3986 (e-moe) + * bug #21968 Fixed pathinfo calculation for requests starting with a question mark. (syzygymsu) + * bug #21846 [HttpFoundation] Fix Request::getHost() when having several hosts in X_FORWARDED_HOST (nicolas-grekas) + * bug #21208 [Validator] Add object handling of invalid constraints in Composite (SenseException) + * bug #22044 [Serializer] [XML] Ignore Process Instruction (jordscream) + * bug #22079 [HttpKernel] Fixed bug with purging of HTTPS URLs (ausi) + * bug #21523 #20411 fix Yaml parsing for very long quoted strings (RichardBradley) + * bug #22001 [Doctrine Bridge] fix priority for doctrine event listeners (dmaicher) + * bug #21981 [Console] Use proper line endings in BufferedOutput (julienfalque) + * bug #21957 [Form] Choice type int values (BC Fix) (mcfedr) + * bug #21923 [travis] Test with hhvm 3.18 (nicolas-grekas) + * bug #21823 dumpFile(), preserve existing file permissions (chs2) + * bug #21865 [Security] context listener: hardening user provider handling (xabbuh) + * bug #21883 [HttpKernel] fix Kernel name when stored in a directory starting with a number (fabpot) + * 2.7.25 (2017-03-06) * bug #21671 [Serializer] Xml encoder throws exception for valid data (gr1ev0us) From c06f35e4ebacd52224f85b60566186e268d03c7f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Apr 2017 21:31:39 -0700 Subject: [PATCH 73/80] update CONTRIBUTORS for 2.7.26 --- CONTRIBUTORS.md | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 73387b9f7bb1..90b929e5efcc 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -23,25 +23,26 @@ Symfony is the result of the work of many people who made the code better - Pascal Borreli (pborreli) - Wouter De Jong (wouterj) - Romain Neutron (romain) + - Grégoire Pineau (lyrixx) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - - Grégoire Pineau (lyrixx) - Martin Hasoň (hason) - - Jeremy Mikola (jmikola) + - Robin Chalas (chalas_r) - Maxime Steinhausser (ogizanagi) + - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Robin Chalas (chalas_r) - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Sarah Khalil (saro0h) - Jonathan Wage (jwage) + - Guilhem Niot (energetick) - Diego Saint Esteben (dosten) + - Roland Franssen (ro0) - Alexandre Salomé (alexandresalome) - William Durand (couac) - - Guilhem Niot (energetick) - ornicar - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) @@ -50,20 +51,20 @@ Symfony is the result of the work of many people who made the code better - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - - Roland Franssen (ro0) - Miha Vrhovnik - Iltar van der Berg (kjarli) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) + - Matthias Pigulla (mpdude) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - - Matthias Pigulla (mpdude) + - Pierre du Plessis (pierredup) - Christian Raue - Arnout Boks (aboks) - Deni @@ -71,39 +72,38 @@ Symfony is the result of the work of many people who made the code better - Dariusz Górecki (canni) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Pierre du Plessis (pierredup) - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Jáchym Toušek (enumag) - Graham Campbell (graham) - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Jérémy DERUSSÉ (jderusse) - John Wards (johnwards) - Fran Moreno (franmomu) - - Jáchym Toušek (enumag) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - Dariusz Ruminski - Arnaud Le Blanc (arnaud-lb) - Jérôme Tamarelle (gromnan) + - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - - Maxime STEINHAUSSER - Issei Murasawa (issei_m) - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) + - Baptiste Clavié (talus) - marc.weistroff - lenar - Włodzimierz Gajda (gajdaw) - - Baptiste Clavié (talus) - Vladimir Reznichenko (kalessil) - Alexander Schwenn (xelaris) - Florian Voutzinos (florianv) - Colin Frei - - Jérémy DERUSSÉ (jderusse) - Adrien Brault (adrienbrault) - Joshua Thijssen - Peter Kokot (maastermedia) @@ -148,6 +148,7 @@ Symfony is the result of the work of many people who made the code better - Teoh Han Hui (teohhanhui) - Clemens Tolboom - Helmer Aaviksoo + - Grégoire Paris (greg0ire) - Hiromi Hishida (77web) - Richard van Laak (rvanlaak) - Matthieu Ouellette-Vachon (maoueh) @@ -160,7 +161,7 @@ Symfony is the result of the work of many people who made the code better - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Grégoire Paris (greg0ire) + - Dawid Nowak - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) @@ -168,6 +169,7 @@ Symfony is the result of the work of many people who made the code better - Dennis Benkert (denderello) - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) + - Chris Wilkinson (thewilkybarkid) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - Lars Strojny (lstrojny) @@ -191,16 +193,15 @@ Symfony is the result of the work of many people who made the code better - John Kary (johnkary) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - - Chris Wilkinson (thewilkybarkid) - Christian Schmidt - Michele Orselli (orso) - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Rui Marinho (ruimarinho) - SpacePossum - - Dawid Nowak - Eugene Wissner - Julien Brochet (mewt) + - Julien Falque (julienfalque) - Tristan Darricau (nicofuma) - Sergey Linnik (linniksa) - Michaël Perrin (michael.perrin) @@ -211,6 +212,7 @@ Symfony is the result of the work of many people who made the code better - julien pauli (jpauli) - Lorenz Schori - Sébastien Lavoie (lavoiesl) + - David Maicher (dmaicher) - Francois Zaninotto - Alexander Kotynia (olden) - Daniel Tschinder @@ -236,7 +238,6 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto - - Julien Falque (julienfalque) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -258,7 +259,6 @@ Symfony is the result of the work of many people who made the code better - Beau Simensen (simensen) - Michael Hirschler (mvhirsch) - Robert Kiss (kepten) - - David Maicher (dmaicher) - Roumen Damianoff (roumen) - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) @@ -396,6 +396,7 @@ Symfony is the result of the work of many people who made the code better - EdgarPE - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) + - Andreas Braun - Chris Sedlmayr (catchamonkey) - Seb Koelen - Dany Maillard (maidmaid) @@ -415,6 +416,7 @@ Symfony is the result of the work of many people who made the code better - Gintautas Miselis - Rob Bast - David Badura (davidbadura) + - Jordan Samouh (jordansamouh) - Zander Baldwin - Adam Harvey - Alex Bakhturin @@ -459,11 +461,13 @@ Symfony is the result of the work of many people who made the code better - Jakub Škvára (jskvara) - Andrew Udvare (audvare) - alexpods + - Nikolay Labinskiy (e-moe) - Arjen van der Meijden - Michele Locati - Dariusz Ruminski - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) + - Arthur de Moulins (4rthem) - Almog Baku (almogbaku) - Scott Arciszewski - Norbert Orzechowicz (norzechowicz) @@ -510,8 +514,10 @@ 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) - Jan Behrens - Mantas Var (mvar) + - Frank de Jonge (frenkynet) - Sebastian Krebs - Jean-Christophe Cuvelier [Artack] - Christopher Davis (chrisguitarguy) @@ -539,8 +545,8 @@ Symfony is the result of the work of many people who made the code better - Maxime Douailin - Jean Pasdeloup (pasdeloup) - Benjamin Cremer (bcremer) + - Thierry Thuon (lepiaf) - Javier López (loalf) - - Andreas Braun - Reinier Kip - Geoffrey Brier (geoffrey-brier) - Dustin Dobervich (dustin10) @@ -553,6 +559,7 @@ Symfony is the result of the work of many people who made the code better - Kamil Kokot (pamil) - Aurimas Niekis (gcds) - Max Grigorian (maxakawizard) + - mcfedr (mcfedr) - Rostyslav Kinash - Maciej Malarz (malarzm) - Daisuke Ohata @@ -570,6 +577,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) + - Richard Bradley - Ulumuddin Yunus (joenoez) - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) @@ -629,6 +637,7 @@ Symfony is the result of the work of many people who made the code better - Besnik Br - Dariusz Ruminski - Joshua Nye + - Claudio Zizza - Dave Marshall (davedevelopment) - avorobiev - Venu @@ -647,6 +656,7 @@ Symfony is the result of the work of many people who made the code better - John Bohn (jbohn) - Marc Morera (mmoreram) - Andrew Hilobok (hilobok) + - Noah Heck (myesain) - Christian Soronellas (theunic) - Yosmany Garcia (yosmanyga) - Wouter de Wild @@ -654,17 +664,18 @@ Symfony is the result of the work of many people who made the code better - Degory Valentine - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) - - Arthur de Moulins (4rthem) - Krzysiek Łabuś - Xavier Lacot (xavier) - possum - Denis Zunke (donalberto) + - Ahmed TAILOULOUTE (ahmedtai) - Olivier Maisonneuve (olineuve) - Masterklavi - Francis Turmel (fturmel) - Nikita Nefedov (nikita2206) - cgonzalez - Ben + - Vincent Composieux (eko) - Jayson Xu (superjavason) - Jaik Dean (jaikdean) - fago @@ -675,6 +686,7 @@ Symfony is the result of the work of many people who made the code better - James Michael DuPont - Tom Klingenberg - Christopher Hall (mythmakr) + - Patrick Dawkins (pjcdawkins) - Paul Kamer (pkamer) - Rafał Wrzeszcz (rafalwrzeszcz) - Reen Lokum @@ -720,6 +732,7 @@ Symfony is the result of the work of many people who made the code better - corphi - grizlik - Derek ROTH + - Dmytro Boiko (eagle) - Shin Ohno (ganchiku) - Geert De Deckere (geertdd) - Jan Kramer (jankramer) @@ -782,7 +795,6 @@ Symfony is the result of the work of many people who made the code better - Phan Thanh Ha (haphan) - Chris Jones (leek) - Colin O'Dell (colinodell) - - Frank de Jonge (frenkynet) - xaav - Mahmoud Mostafa (mahmoud) - Alessandro Lai @@ -808,7 +820,6 @@ Symfony is the result of the work of many people who made the code better - Zachary Tong (polyfractal) - Hryhorii Hrebiniuk - Dennis Fridrich (dfridrich) - - mcfedr (mcfedr) - hamza - dantleech - Bastien DURAND (deamon) @@ -841,6 +852,7 @@ Symfony is the result of the work of many people who made the code better - Troy McCabe - Ville Mattila - ilyes kooli + - gr1ev0us - Boris Vujicic (boris.vujicic) - Max Beutel - Antanas Arvasevicius @@ -864,10 +876,12 @@ Symfony is the result of the work of many people who made the code better - Martynas Narbutas - Bailey Parker - Eddie Jaoude + - Antanas Arvasevicius - Haritz Iturbe (hizai) - Nerijus Arlauskas (nercury) - SPolischook - Diego Sapriza + - Anton A. Sumin - Joan Cruz - inspiran - Cristobal Dabed @@ -964,6 +978,7 @@ Symfony is the result of the work of many people who made the code better - Aharon Perkel - matze - Abdul.Mohsen B. A. A + - Martin Auswöger - Benoît Burnichon - pthompson - Malaney J. Hill @@ -1009,7 +1024,9 @@ Symfony is the result of the work of many people who made the code better - Klaas Cuvelier (kcuvelier) - markusu49 - Steve Frécinaux + - Jules Lamur - ShiraNai7 + - Markus Fasselt (digilist) - Vašek Purchart (vasek-purchart) - Janusz Jabłoński (yanoosh) - Sandro Hopf @@ -1034,17 +1051,16 @@ Symfony is the result of the work of many people who made the code better - Luis Galeas - Martin Pärtel - George Mponos (gmponos) - - Noah Heck (myesain) - Patrick Daley (padrig) - Xavier Briand (xavierbriand) - Max Summe - WedgeSama - Felds Liscia - - Ahmed TAILOULOUTE (ahmedtai) - Maxime Veber (nek-) - Sullivan SENECHAL - Tadcka - Beth Binkovitz + - Gonzalo Míguez - Romain Geissler - Adrien Moiruad - Tomaz Ahlin @@ -1104,7 +1120,6 @@ Symfony is the result of the work of many people who made the code better - Konrad Mohrfeldt - Lance Chen - Andrew (drew) - - Nikolay Labinskiy (e-moe) - kor3k kor3k (kor3k) - Stelian Mocanita (stelian) - Flavian (2much) @@ -1143,11 +1158,9 @@ Symfony is the result of the work of many people who made the code better - victoria - Francisco Facioni (fran6co) - Iwan van Staveren (istaveren) - - Thierry Thuon (lepiaf) - Povilas S. (povilas) - pborreli - Eric Caron - - Richard Bradley - 2manypeople - Wing - Thomas Bibb @@ -1171,6 +1184,7 @@ Symfony is the result of the work of many people who made the code better - Michal Gebauer - Gleb Sidora - David Stone + - Niels Keurentjes (curry684) - Jovan Perovic (jperovic) - Pablo Maria Martelletti (pmartelletti) - Yassine Guedidi (yguedidi) @@ -1228,6 +1242,7 @@ Symfony is the result of the work of many people who made the code better - Brian Graham (incognito) - Kevin Vergauwen (innocenzo) - Alessio Baglio (ioalessio) + - Johannes Müller (johmue) - Jordi Llonch (jordillonch) - Cédric Dugat (ph3nol) - Philip Dahlstrøm (phidah) @@ -1289,6 +1304,7 @@ Symfony is the result of the work of many people who made the code better - Jérémy M (th3mouk) - Vincent LEFORT (vlefort) - Sadicov Vladimir (xtech) + - Kevin EMO (zarcox) - Alexander Zogheb - Rémi Blaise - Joel Marcey @@ -1301,7 +1317,6 @@ Symfony is the result of the work of many people who made the code better - adenkejawen - Ari Pringle (apringle) - Dan Ordille (dordille) - - Dmytro Boiko (eagle) - Jan Eichhorn (exeu) - Grégory Pelletier (ip512) - John Nickell (jrnickell) @@ -1350,7 +1365,6 @@ Symfony is the result of the work of many people who made the code better - ddebree - Tomas Liubinas - Alex - - Patrick Dawkins - Klaas Naaijkens - Daniel González Cerviño - Rafał @@ -1363,7 +1377,6 @@ Symfony is the result of the work of many people who made the code better - David Joos (djoos) - Denis Klementjev (dklementjev) - Tomáš Polívka (draczris) - - Vincent Composieux (eko) - Franz Liedke (franzliedke) - Christophe BECKER (goabonga) - gondo (gondo) @@ -1399,6 +1412,7 @@ Symfony is the result of the work of many people who made the code better - Curtis - Gabriel Moreira - Alexey Popkov + - ChS - Joseph Deray - Damian Sromek - Ben @@ -1437,6 +1451,7 @@ Symfony is the result of the work of many people who made the code better - znerol - Christian Eikermann - Antonio Angelino + - Matt Fields - Shawn Iwinski - Niklas Keller - Vladimir Sazhin @@ -1562,6 +1577,7 @@ Symfony is the result of the work of many people who made the code better - ibasaw (ibasaw) - Vladislav Krupenkin (ideea) - Imangazaliev Muhammad (imangazaliev) + - j0k (j0k) - joris de wit (jdewit) - Jérémy CROMBEZ (jeremy) - Jose Manuel Gonzalez (jgonzalez) From 4cc567782e78eca265752650e33683d31dc21ed7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Apr 2017 21:31:58 -0700 Subject: [PATCH 74/80] updated VERSION for 2.7.26 --- 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 be48c7359ba9..7e911bddfaaa 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.26-DEV'; + const VERSION = '2.7.26'; const VERSION_ID = 20726; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 26; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From e580c68899921119e17b6774ef467406eb3b5f8b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Apr 2017 21:47:45 -0700 Subject: [PATCH 75/80] bumped Symfony version to 2.7.27 --- 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 7e911bddfaaa..0d37a6d05e40 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.26'; - const VERSION_ID = 20726; + const VERSION = '2.7.27-DEV'; + const VERSION_ID = 20727; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 26; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 27; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From fffcd247b22f830330c277e4876aaf8772615e38 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 18 Mar 2017 10:10:35 +0100 Subject: [PATCH 76/80] fix some risky tests --- .../Builder/ArrayNodeDefinitionTest.php | 9 +- .../Definition/Builder/TreeBuilderTest.php | 13 ++- .../Config/Tests/Fixtures/BarNode.php | 18 ++++ .../Fixtures/Builder/BarNodeDefinition.php | 2 + .../Component/Form/Tests/CompoundFormTest.php | 2 + .../Extension/Core/Type/ChoiceTypeTest.php | 8 +- .../Extension/Core/Type/CountryTypeTest.php | 8 +- .../Extension/Core/Type/DateTimeTypeTest.php | 2 +- .../Extension/Core/Type/DateTypeTest.php | 2 +- .../Extension/Core/Type/FormTypeTest.php | 14 +-- .../Extension/Core/Type/TimeTypeTest.php | 2 +- .../DependencyInjectionExtensionTest.php | 9 +- .../Component/Form/Tests/FormBuilderTest.php | 2 + .../Component/Form/Tests/FormConfigTest.php | 102 +++++++++--------- .../Component/Form/Tests/SimpleFormTest.php | 17 +-- .../Form/Tests/Util/OrderedHashMapTest.php | 3 + .../HttpFoundation/Tests/IpUtilsTest.php | 8 +- .../Tests/RequestMatcherTest.php | 8 +- .../HttpFoundation/Tests/RequestTest.php | 51 ++++----- .../Tests/Session/SessionTest.php | 2 + .../Tests/Session/Storage/MetadataBagTest.php | 3 + .../Tests/StreamedResponseTest.php | 4 +- .../Acl/Tests/Dbal/MutableAclProviderTest.php | 39 ++++--- .../Domain/PermissionGrantingStrategyTest.php | 11 +- .../Encoder/BCryptPasswordEncoderTest.php | 17 ++- .../Core/Tests/LegacySecurityContextTest.php | 3 +- .../Http/Tests/Firewall/DigestDataTest.php | 13 ++- 27 files changed, 222 insertions(+), 150 deletions(-) create mode 100644 src/Symfony/Component/Config/Tests/Fixtures/BarNode.php diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php index 6456639af305..63efd719b5f5 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php @@ -145,13 +145,16 @@ public function providePrototypedArrayNodeDefaults() public function testNestedPrototypedArrayNodes() { - $node = new ArrayNodeDefinition('root'); - $node + $nodeDefinition = new ArrayNodeDefinition('root'); + $nodeDefinition ->addDefaultChildrenIfNoneSet() ->prototype('array') ->prototype('array') ; - $node->getNode(); + $node = $nodeDefinition->getNode(); + + $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node); + $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node->getPrototype()); } public function testEnabledNodeDefaults() diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php index 16a10227cc29..13304fae36e9 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php @@ -71,6 +71,8 @@ public function testPrototypedArrayNodeUseTheCustomNodeBuilder() $root = $builder->root('override', 'array', new CustomNodeBuilder()); $root->prototype('bar')->end(); + + $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\BarNode', $root->getNode(true)->getPrototype()); } public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren() @@ -79,7 +81,7 @@ public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren() $builder->root('propagation') ->children() - ->setNodeClass('extended', 'Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition') + ->setNodeClass('extended', 'Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition') ->node('foo', 'extended')->end() ->arrayNode('child') ->children() @@ -88,6 +90,15 @@ public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren() ->end() ->end() ->end(); + + $node = $builder->buildTree(); + $children = $node->getChildren(); + + $this->assertInstanceOf('Symfony\Component\Config\Definition\BooleanNode', $children['foo']); + + $childChildren = $children['child']->getChildren(); + + $this->assertInstanceOf('Symfony\Component\Config\Definition\BooleanNode', $childChildren['foo']); } public function testDefinitionInfoGetsTransferredToNode() diff --git a/src/Symfony/Component/Config/Tests/Fixtures/BarNode.php b/src/Symfony/Component/Config/Tests/Fixtures/BarNode.php new file mode 100644 index 000000000000..0b9c32dedaf1 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Fixtures/BarNode.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Tests\Fixtures; + +use Symfony\Component\Config\Definition\ArrayNode; + +class BarNode extends ArrayNode +{ +} diff --git a/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php b/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php index 47701c1b29eb..0d46f3d2c8c0 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php @@ -12,10 +12,12 @@ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\NodeDefinition; +use Symfony\Component\Config\Tests\Fixtures\BarNode; class BarNodeDefinition extends NodeDefinition { protected function createNode() { + return new BarNode($this->name); } } diff --git a/src/Symfony/Component/Form/Tests/CompoundFormTest.php b/src/Symfony/Component/Form/Tests/CompoundFormTest.php index 3738a4c953c0..b9b93e54c163 100644 --- a/src/Symfony/Component/Form/Tests/CompoundFormTest.php +++ b/src/Symfony/Component/Form/Tests/CompoundFormTest.php @@ -299,6 +299,8 @@ public function testRemoveThrowsExceptionIfAlreadySubmitted() public function testRemoveIgnoresUnknownName() { $this->form->remove('notexisting'); + + $this->assertCount(0, $this->form); } public function testArrayAccess() 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 983397b09d62..3e36c7dd2936 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -126,9 +126,9 @@ public function testChoiceLoaderOptionExpectsChoiceLoaderInterface() public function testChoiceListAndChoicesCanBeEmpty() { - $this->factory->create(static::TESTED_TYPE, null, array( + $this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, null, array( 'choices_as_values' => true, - )); + ))); } public function testExpandedChoicesOptionsTurnIntoChildren() @@ -2251,10 +2251,10 @@ public function testAdjustFullNameForMultipleNonExpanded() // https://github.com/symfony/symfony/issues/3298 public function testInitializeWithEmptyChoices() { - $this->factory->createNamed('name', static::TESTED_TYPE, null, array( + $this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->createNamed('name', static::TESTED_TYPE, null, array( 'choices' => array(), 'choices_as_values' => true, - )); + ))); } public function testInitializeWithDefaultObjectChoice() diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php index 3d8e86defb39..7765f4706d39 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php @@ -43,11 +43,13 @@ public function testUnknownCountryIsNotIncluded() $choices = $this->factory->create(static::TESTED_TYPE, 'country') ->createView()->vars['choices']; + $countryCodes = array(); + foreach ($choices as $choice) { - if ('ZZ' === $choice->value) { - $this->fail('Should not contain choice "ZZ"'); - } + $countryCodes[] = $choice->value; } + + $this->assertNotContains('ZZ', $countryCodes); } public function testSubmitNull($expected = null, $norm = null, $view = null) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index dca17c340022..9a80bdd87ba8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -273,7 +273,7 @@ public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type - $this->factory->create(static::TESTED_TYPE, new \DateTime()); + $this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime())); } public function testSingleTextWidgetShouldUseTheRightInputType() diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index d907c9c3d15e..7fcb1f505d33 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -711,7 +711,7 @@ public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type - $this->factory->create(static::TESTED_TYPE, new \DateTime()); + $this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime())); } public function testSingleTextWidgetShouldUseTheRightInputType() diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php index 5f5d5def6937..1ff4057d5f37 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -149,23 +149,23 @@ public function testPassMaxLengthBCToView() public function testDataClassMayBeNull() { - $this->factory->createBuilder(static::TESTED_TYPE, null, array( + $this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array( 'data_class' => null, - )); + ))); } public function testDataClassMayBeAbstractClass() { - $this->factory->createBuilder(static::TESTED_TYPE, null, array( + $this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AbstractAuthor', - )); + ))); } public function testDataClassMayBeInterface() { - $this->factory->createBuilder(static::TESTED_TYPE, null, array( + $this->assertInstanceOf('Symfony\Component\Form\FormBuilderInterface', $this->factory->createBuilder(static::TESTED_TYPE, null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AuthorInterface', - )); + ))); } /** @@ -652,7 +652,7 @@ public function testCanGetErrorsWhenButtonInForm() $form = $builder->getForm(); //This method should not throw a Fatal Error Exception. - $form->getErrorsAsString(); + $this->assertInternalType('string', $form->getErrorsAsString()); } public function testSubmitNull($expected = null, $norm = null, $view = null) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index 8537c96fe049..48fd5964db61 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -488,7 +488,7 @@ public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type - $this->factory->create(static::TESTED_TYPE, new \DateTime()); + $this->assertInstanceOf('Symfony\Component\Form\FormInterface', $this->factory->create(static::TESTED_TYPE, new \DateTime())); } public function testSingleTextWidgetShouldUseTheRightInputType() diff --git a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php index 22f3f9d8e358..f04d092e878d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php @@ -46,16 +46,21 @@ public function testGetTypeExtensions() public function testThrowExceptionForInvalidExtendedType() { + $formTypeExtension = $this->createFormTypeExtensionMock('unmatched'); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container->expects($this->any()) ->method('get') ->with('extension') - ->willReturn($this->createFormTypeExtensionMock('unmatched')); + ->willReturn($formTypeExtension); $extension = new DependencyInjectionExtension($container, array(), array('test' => array('extension')), array()); - $extension->getTypeExtensions('test'); + $extensions = $extension->getTypeExtensions('test'); + + $this->assertCount(1, $extensions); + $this->assertSame($formTypeExtension, $extensions[0]); } public function testGetTypeGuesser() diff --git a/src/Symfony/Component/Form/Tests/FormBuilderTest.php b/src/Symfony/Component/Form/Tests/FormBuilderTest.php index fae2b1623dbf..4f0a813ccd8b 100644 --- a/src/Symfony/Component/Form/Tests/FormBuilderTest.php +++ b/src/Symfony/Component/Form/Tests/FormBuilderTest.php @@ -161,6 +161,8 @@ public function testAddButton() { $this->builder->add(new ButtonBuilder('reset')); $this->builder->add(new SubmitButtonBuilder('submit')); + + $this->assertCount(2, $this->builder->all()); } public function testGetUnknown() diff --git a/src/Symfony/Component/Form/Tests/FormConfigTest.php b/src/Symfony/Component/Form/Tests/FormConfigTest.php index 21eabba871d3..bb922bf3d61f 100644 --- a/src/Symfony/Component/Form/Tests/FormConfigTest.php +++ b/src/Symfony/Component/Form/Tests/FormConfigTest.php @@ -12,9 +12,7 @@ namespace Symfony\Component\Form\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormConfigBuilder; -use Symfony\Component\Form\Exception\InvalidArgumentException; /** * @author Bernhard Schussek @@ -24,72 +22,65 @@ class FormConfigTest extends TestCase public function getHtml4Ids() { return array( - array('z0', true), - array('A0', true), - array('A9', true), - array('Z0', true), - array('#', false), - array('a#', false), - array('a$', false), - array('a%', false), - array('a ', false), - array("a\t", false), - array("a\n", false), - array('a-', true), - array('a_', true), - array('a:', true), + array('z0'), + array('A0'), + array('A9'), + array('Z0'), + array('#', 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array('a#', 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array('a$', 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array('a%', 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array('a ', 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array("a\t", 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array("a\n", 'Symfony\Component\Form\Exception\InvalidArgumentException'), + array('a-'), + array('a_'), + array('a:'), // Periods are allowed by the HTML4 spec, but disallowed by us // because they break the generated property paths - array('a.', false), + array('a.', 'Symfony\Component\Form\Exception\InvalidArgumentException'), // Contrary to the HTML4 spec, we allow names starting with a // number, otherwise naming fields by collection indices is not // possible. // For root forms, leading digits will be stripped from the // "id" attribute to produce valid HTML4. - array('0', true), - array('9', true), + array('0'), + array('9'), // Contrary to the HTML4 spec, we allow names starting with an // underscore, since this is already a widely used practice in // Symfony. // For root forms, leading underscores will be stripped from the // "id" attribute to produce valid HTML4. - array('_', true), + array('_'), // Integers are allowed - array(0, true), - array(123, true), + array(0), + array(123), // NULL is allowed - array(null, true), + array(null), // Other types are not - array(1.23, false), - array(5., false), - array(true, false), - array(new \stdClass(), false), + array(1.23, 'Symfony\Component\Form\Exception\UnexpectedTypeException'), + array(5., 'Symfony\Component\Form\Exception\UnexpectedTypeException'), + array(true, 'Symfony\Component\Form\Exception\UnexpectedTypeException'), + array(new \stdClass(), 'Symfony\Component\Form\Exception\UnexpectedTypeException'), ); } /** * @dataProvider getHtml4Ids */ - public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) + public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $expectedException = null) { $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - try { - new FormConfigBuilder($name, null, $dispatcher); - if (!$accepted) { - $this->fail(sprintf('The value "%s" should not be accepted', $name)); - } - } catch (UnexpectedTypeException $e) { - // if the value was not accepted, but should be, rethrow exception - if ($accepted) { - throw $e; - } - } catch (InvalidArgumentException $e) { - // if the value was not accepted, but should be, rethrow exception - if ($accepted) { - throw $e; - } + if (null !== $expectedException && method_exists($this, 'expectException')) { + $this->expectException($expectedException); + } elseif (null !== $expectedException) { + $this->setExpectedException($expectedException); } + + $formConfigBuilder = new FormConfigBuilder($name, null, $dispatcher); + + $this->assertSame((string) $name, $formConfigBuilder->getName()); } public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet() @@ -109,27 +100,42 @@ public function testGetRequestHandlerReusesNativeRequestHandlerInstance() public function testSetMethodAllowsGet() { - $this->getConfigBuilder()->setMethod('GET'); + $formConfigBuilder = $this->getConfigBuilder(); + $formConfigBuilder->setMethod('GET'); + + self::assertSame('GET', $formConfigBuilder->getMethod()); } public function testSetMethodAllowsPost() { - $this->getConfigBuilder()->setMethod('POST'); + $formConfigBuilder = $this->getConfigBuilder(); + $formConfigBuilder->setMethod('POST'); + + self::assertSame('POST', $formConfigBuilder->getMethod()); } public function testSetMethodAllowsPut() { - $this->getConfigBuilder()->setMethod('PUT'); + $formConfigBuilder = $this->getConfigBuilder(); + $formConfigBuilder->setMethod('PUT'); + + self::assertSame('PUT', $formConfigBuilder->getMethod()); } public function testSetMethodAllowsDelete() { - $this->getConfigBuilder()->setMethod('DELETE'); + $formConfigBuilder = $this->getConfigBuilder(); + $formConfigBuilder->setMethod('DELETE'); + + self::assertSame('DELETE', $formConfigBuilder->getMethod()); } public function testSetMethodAllowsPatch() { - $this->getConfigBuilder()->setMethod('PATCH'); + $formConfigBuilder = $this->getConfigBuilder(); + $formConfigBuilder->setMethod('PATCH'); + + self::assertSame('PATCH', $formConfigBuilder->getMethod()); } /** diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index 6223d3b39f95..9d745e3edf81 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -918,12 +918,11 @@ public function testSetDataCannotInvokeItself() public function testSubmittingWrongDataIsIgnored() { - $test = $this; + $called = 0; $child = $this->getBuilder('child', $this->dispatcher); - $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) { - // child form doesn't receive the wrong data that is submitted on parent - $test->assertNull($event->getData()); + $child->addEventListener(FormEvents::PRE_SUBMIT, function () use (&$called) { + ++$called; }); $parent = $this->getBuilder('parent', new EventDispatcher()) @@ -933,6 +932,8 @@ public function testSubmittingWrongDataIsIgnored() ->getForm(); $parent->submit('not-an-array'); + + $this->assertSame(0, $called, 'PRE_SUBMIT event listeners are not called for wrong data'); } public function testHandleRequestForwardsToRequestHandler() @@ -1036,15 +1037,17 @@ public function testPostSubmitDataIsNullIfInheritData() public function testSubmitIsNeverFiredIfInheritData() { - $test = $this; + $called = 0; $form = $this->getBuilder() - ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) { - $test->fail('The SUBMIT event should not be fired'); + ->addEventListener(FormEvents::SUBMIT, function () use (&$called) { + ++$called; }) ->setInheritData(true) ->getForm(); $form->submit('foo'); + + $this->assertSame(0, $called, 'The SUBMIT event is not fired when data are inherited from the parent form'); } public function testInitializeSetsDefaultData() diff --git a/src/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php b/src/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php index 4328919651ef..89735ea6180c 100644 --- a/src/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php +++ b/src/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php @@ -114,8 +114,11 @@ public function testUnset() public function testUnsetNonExistingSucceeds() { $map = new OrderedHashMap(); + $map['second'] = 2; unset($map['first']); + + $this->assertSame(array('second' => 2), iterator_to_array($map)); } public function testEmptyIteration() diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index 61aa74861dde..297ee3d8d354 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -17,14 +17,14 @@ class IpUtilsTest extends TestCase { /** - * @dataProvider testIpv4Provider + * @dataProvider getIpv4Data */ public function testIpv4($matches, $remoteAddr, $cidr) { $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); } - public function testIpv4Provider() + public function getIpv4Data() { return array( array(true, '192.168.1.1', '192.168.1.1'), @@ -43,7 +43,7 @@ public function testIpv4Provider() } /** - * @dataProvider testIpv6Provider + * @dataProvider getIpv6Data */ public function testIpv6($matches, $remoteAddr, $cidr) { @@ -54,7 +54,7 @@ public function testIpv6($matches, $remoteAddr, $cidr) $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); } - public function testIpv6Provider() + public function getIpv6Data() { return array( array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php index 6f864d4468fe..b5d80048ff11 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php @@ -18,7 +18,7 @@ class RequestMatcherTest extends TestCase { /** - * @dataProvider testMethodFixtures + * @dataProvider getMethodData */ public function testMethod($requestMethod, $matcherMethod, $isMatch) { @@ -32,7 +32,7 @@ public function testMethod($requestMethod, $matcherMethod, $isMatch) $this->assertSame($isMatch, $matcher->matches($request)); } - public function testMethodFixtures() + public function getMethodData() { return array( array('get', 'get', true), @@ -64,7 +64,7 @@ public function testScheme() } /** - * @dataProvider testHostFixture + * @dataProvider getHostData */ public function testHost($pattern, $isMatch) { @@ -78,7 +78,7 @@ public function testHost($pattern, $isMatch) $this->assertSame($isMatch, $matcher->matches($request)); } - public function testHostFixture() + public function getHostData() { return array( array('.*\.example\.com', true), diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 2d8baa7142e1..6f9d76b4835e 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -306,6 +306,10 @@ public function testGetFormatFromMimeType($format, $mimeTypes) $request->setFormat($format, $mimeTypes); foreach ($mimeTypes as $mime) { $this->assertEquals($format, $request->getFormat($mime)); + + if (null !== $format) { + $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); + } } } @@ -315,17 +319,6 @@ public function testGetFormatFromMimeTypeWithParameters() $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8')); } - /** - * @dataProvider getFormatToMimeTypeMapProvider - */ - public function testGetMimeTypeFromFormat($format, $mimeTypes) - { - if (null !== $format) { - $request = new Request(); - $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); - } - } - public function testGetFormatWithCustomMimeType() { $request = new Request(); @@ -821,7 +814,7 @@ public function testGetSetMethod() } /** - * @dataProvider testGetClientIpsProvider + * @dataProvider getClientIpsProvider */ public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) { @@ -833,7 +826,7 @@ public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trus } /** - * @dataProvider testGetClientIpsProvider + * @dataProvider getClientIpsProvider */ public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) { @@ -845,7 +838,7 @@ public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $tru } /** - * @dataProvider testGetClientIpsForwardedProvider + * @dataProvider getClientIpsForwardedProvider */ public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies) { @@ -856,7 +849,7 @@ public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded Request::setTrustedProxies(array()); } - public function testGetClientIpsForwardedProvider() + public function getClientIpsForwardedProvider() { // $expected $remoteAddr $httpForwarded $trustedProxies return array( @@ -869,7 +862,7 @@ public function testGetClientIpsForwardedProvider() ); } - public function testGetClientIpsProvider() + public function getClientIpsProvider() { // $expected $remoteAddr $httpForwardedFor $trustedProxies return array( @@ -926,7 +919,7 @@ public function testGetClientIpsProvider() /** * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException - * @dataProvider testGetClientIpsWithConflictingHeadersProvider + * @dataProvider getClientIpsWithConflictingHeadersProvider */ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor) { @@ -945,7 +938,7 @@ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXFor $request->getClientIps(); } - public function testGetClientIpsWithConflictingHeadersProvider() + public function getClientIpsWithConflictingHeadersProvider() { // $httpForwarded $httpXForwardedFor return array( @@ -958,9 +951,9 @@ public function testGetClientIpsWithConflictingHeadersProvider() } /** - * @dataProvider testGetClientIpsWithAgreeingHeadersProvider + * @dataProvider getClientIpsWithAgreeingHeadersProvider */ - public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor) + public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps) { $request = new Request(); @@ -974,21 +967,23 @@ public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwar $request->initialize(array(), array(), array(), array(), array(), $server); - $request->getClientIps(); + $clientIps = $request->getClientIps(); Request::setTrustedProxies(array()); + + $this->assertSame($expectedIps, $clientIps); } - public function testGetClientIpsWithAgreeingHeadersProvider() + public function getClientIpsWithAgreeingHeadersProvider() { // $httpForwarded $httpXForwardedFor return array( - array('for="192.0.2.60"', '192.0.2.60'), - array('for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21'), - array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60'), - array('for="192.0.2.60:80"', '192.0.2.60'), - array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60'), - array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17'), + array('for="192.0.2.60"', '192.0.2.60', array('192.0.2.60')), + array('for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21', array('87.65.43.21', '192.0.2.60')), + array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60', array('192.0.2.60', '::face')), + array('for="192.0.2.60:80"', '192.0.2.60', array('192.0.2.60')), + array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', array('192.0.2.60')), + array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', array('2001:db8:cafe::17')), ); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php index 4d5d337a3c01..fa93507a41aa 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php @@ -177,6 +177,8 @@ public function testSave() { $this->session->start(); $this->session->save(); + + $this->assertFalse($this->session->isStarted()); } public function testGetId() diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php index 1f55a2d5c440..159e62114e1a 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php @@ -103,6 +103,9 @@ public function testGetLastUsed() public function testClear() { $this->bag->clear(); + + // the clear method has no side effects, we just want to ensure it doesn't trigger any exceptions + $this->addToAssertionCount(1); } public function testSkipLastUsedUpdate() diff --git a/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php index 844274b1e7e2..5874145348ea 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php @@ -51,10 +51,12 @@ public function testPrepareWith10Protocol() public function testPrepareWithHeadRequest() { - $response = new StreamedResponse(function () { echo 'foo'; }); + $response = new StreamedResponse(function () { echo 'foo'; }, 200, array('Content-Length' => '123')); $request = Request::create('/', 'HEAD'); $response->prepare($request); + + $this->assertSame('123', $response->headers->get('Content-Length')); } public function testPrepareWithCacheHeaders() diff --git a/src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php b/src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php index e7de0b54875e..f11916822195 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php @@ -19,8 +19,6 @@ use Symfony\Component\Security\Acl\Domain\Entry; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\Acl; -use Symfony\Component\Security\Acl\Exception\AclNotFoundException; -use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException; use Symfony\Component\Security\Acl\Dbal\AclProvider; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Dbal\MutableAclProvider; @@ -79,23 +77,25 @@ public function testCreateAcl() $this->assertTrue($acl->getObjectIdentity()->equals($oid)); } + /** + * @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException + */ public function testDeleteAcl() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); - $acl = $provider->createAcl($oid); + $provider->createAcl($oid); $provider->deleteAcl($oid); $loadedAcls = $this->getField($provider, 'loadedAcls'); $this->assertCount(0, $loadedAcls['Foo']); - try { - $provider->findAcl($oid); - $this->fail('ACL has not been properly deleted.'); - } catch (AclNotFoundException $e) { - } + $provider->findAcl($oid); } + /** + * @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException + */ public function testDeleteAclDeletesChildren() { $provider = $this->getProvider(); @@ -105,11 +105,7 @@ public function testDeleteAclDeletesChildren() $provider->updateAcl($acl); $provider->deleteAcl($parentAcl->getObjectIdentity()); - try { - $provider->findAcl(new ObjectIdentity(1, 'Foo')); - $this->fail('Child-ACLs have not been deleted.'); - } catch (AclNotFoundException $e) { - } + $provider->findAcl(new ObjectIdentity(1, 'Foo')); } public function testFindAclsAddsPropertyListener() @@ -273,6 +269,9 @@ public function testUpdateDoesNothingWhenThereAreNoChanges() $provider->updateAcl($acl); } + /** + * @expectedException \Symfony\Component\Security\Acl\Exception\ConcurrentModificationException + */ public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProperties() { $provider = $this->getProvider(); @@ -291,11 +290,7 @@ public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProp $acl1->insertClassAce($sid, 3); $acl2->insertClassAce($sid, 5); - try { - $provider->updateAcl($acl1); - $this->fail('Provider failed to detect a concurrent modification.'); - } catch (ConcurrentModificationException $e) { - } + $provider->updateAcl($acl1); } public function testUpdateAcl() @@ -366,7 +361,7 @@ public function testUpdateAclUpdatesChildAclsCorrectly() $this->assertEquals($newParentParentAcl->getId(), $reloadedAcl->getParentAcl()->getParentAcl()->getId()); } - public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintViolations() + public function testUpdateAclInsertingMultipleObjectFieldAcesDoesNotThrowDBConstraintViolations() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); @@ -386,9 +381,11 @@ public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintV $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid3, 4); $provider->updateAcl($acl); + + $this->assertCount(3, $provider->findAcl($oid)->getObjectFieldAces($fieldName)); } - public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations() + public function testUpdateAclDeletingObjectFieldAcesDoesNotThrowDBConstraintViolations() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); @@ -412,6 +409,8 @@ public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid3, 4); $provider->updateAcl($acl); + + $this->assertCount(2, $provider->findAcl($oid)->getObjectFieldAces($fieldName)); } public function testUpdateUserSecurityIdentity() diff --git a/src/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php b/src/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php index f77262654f12..abb89eceac9a 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php @@ -17,7 +17,6 @@ use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; -use Symfony\Component\Security\Acl\Exception\NoAceFoundException; class PermissionGrantingStrategyTest extends TestCase { @@ -152,11 +151,13 @@ public function testIsGrantedStrategies($maskStrategy, $aceMask, $requiredMask, $acl->insertObjectAce($sid, $aceMask, 0, true, $maskStrategy); if (false === $result) { - try { - $strategy->isGranted($acl, array($requiredMask), array($sid)); - $this->fail('The ACE is not supposed to match.'); - } catch (NoAceFoundException $e) { + if (method_exists($this, 'expectException')) { + $this->expectException('Symfony\Component\Security\Acl\Exception\NoAceFoundException'); + } else { + $this->setExpectedException('Symfony\Component\Security\Acl\Exception\NoAceFoundException'); } + + $strategy->isGranted($acl, array($requiredMask), array($sid)); } else { $this->assertTrue($strategy->isGranted($acl, array($requiredMask), array($sid))); } diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php index 10c8da692a6f..b6b6ab8c8015 100644 --- a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php @@ -39,11 +39,20 @@ public function testCostAboveRange() new BCryptPasswordEncoder(32); } - public function testCostInRange() + /** + * @dataProvider validRangeData + */ + public function testCostInRange($cost) + { + $this->assertInstanceOf('Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', new BCryptPasswordEncoder($cost)); + } + + public function validRangeData() { - for ($cost = 4; $cost <= 31; ++$cost) { - new BCryptPasswordEncoder($cost); - } + $costs = range(4, 31); + array_walk($costs, function (&$cost) { $cost = array($cost); }); + + return $costs; } public function testResultLength() diff --git a/src/Symfony/Component/Security/Core/Tests/LegacySecurityContextTest.php b/src/Symfony/Component/Security/Core/Tests/LegacySecurityContextTest.php index 3661c7be9560..3c842aae76ce 100644 --- a/src/Symfony/Component/Security/Core/Tests/LegacySecurityContextTest.php +++ b/src/Symfony/Component/Security/Core/Tests/LegacySecurityContextTest.php @@ -86,7 +86,8 @@ public function testOldConstructorSignature() { $authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(); $accessDecisionManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')->getMock(); - new SecurityContext($authenticationManager, $accessDecisionManager); + + $this->assertInstanceOf('Symfony\Component\Security\Core\SecurityContext', new SecurityContext($authenticationManager, $accessDecisionManager)); } /** diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php index 2238a7418885..7317e2f83c7c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php @@ -100,6 +100,9 @@ public function testGetUsernameWithEscape() $this->assertEquals('"u\\ser"', $digestAuth->getUsername()); } + /** + * @group time-sensitive + */ public function testValidateAndDecode() { $time = microtime(true); @@ -112,11 +115,11 @@ public function testValidateAndDecode() 'response="b52938fc9e6d7c01be7702ece9031b42"' ); - try { - $digestAuth->validateAndDecode($key, 'Welcome, robot!'); - } catch (\Exception $e) { - $this->fail(sprintf('testValidateAndDecode fail with message: %s', $e->getMessage())); - } + $digestAuth->validateAndDecode($key, 'Welcome, robot!'); + + sleep(1); + + $this->assertTrue($digestAuth->isNonceExpired()); } public function testCalculateServerDigest() From 2fe1631be8bed747c3993540c68f9aa5c38b9a2d Mon Sep 17 00:00:00 2001 From: insekticid Date: Tue, 4 Apr 2017 16:54:31 +0200 Subject: [PATCH 77/80] Allow Upper Case property names ReflectionExtractor::getProperties() returns $id instead of $Id. It is bad naming convention, but is possible ``` class Entity { protected $Id; public function getId() { return $this->Id; } } ``` # Conflicts: # src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php # src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php --- .../Extractor/ReflectionExtractor.php | 2 +- .../Extractors/ReflectionExtractorTest.php | 9 +++++++++ .../PropertyInfo/Tests/Fixtures/Dummy.php | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 0e7bb091adc8..8ba5db00d352 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -76,7 +76,7 @@ public function getProperties($class, array $context = array()) if (!$propertyName || isset($properties[$propertyName])) { continue; } - if (!preg_match('/^[A-Z]{2,}/', $propertyName)) { + if (!$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName)) { $propertyName = lcfirst($propertyName); } $properties[$propertyName] = true; diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index 6af92affe03d..55f75b901671 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -38,6 +38,7 @@ public function testGetProperties() 'parent', 'collection', 'B', + 'Guid', 'g', 'foo', 'foo2', @@ -47,6 +48,7 @@ public function testGetProperties() 'files', 'a', 'DOB', + 'Id', 'c', 'd', 'e', @@ -129,6 +131,10 @@ public function testIsReadable() $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'd', array())); $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array())); $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array())); + $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Id', array())); + $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'id', array())); + $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Guid', array())); + $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'guid', array())); } public function testIsWritable() @@ -142,5 +148,8 @@ public function testIsWritable() $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'd', array())); $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array())); $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array())); + $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Id', array())); + $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Guid', array())); + $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'guid', array())); } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 12065b18b62a..2f6fc11b0de5 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -51,6 +51,16 @@ class Dummy extends ParentDummy */ public $B; + /** + * @var int + */ + protected $Id; + + /** + * @var string + */ + public $Guid; + /** * Nullable array. * @@ -99,4 +109,11 @@ public function setB(ParentDummy $parent = null) public function getDOB() { } + + /** + * @return int + */ + public function getId() + { + } } From 6e1cee62b90e2b8e06fb531538d632dfcff48322 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 4 Apr 2017 16:31:24 +0200 Subject: [PATCH 78/80] [FrameworkBundle] Update console fixtures after #22217 --- .../FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt | 6 +++--- .../FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt | 6 +++--- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt index 587543fb0a47..ed0bcca6562e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt @@ -11,7 +11,7 @@ | Requirements | name: [a-z]+ | | Class | Symfony\Component\Routing\Route | | Defaults | name: Joseph | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | +--------------+---------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt index e75c19e13112..828f6316bedb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt @@ -11,7 +11,7 @@ | Requirements | NO CUSTOM | | Class | Symfony\Component\Routing\Route | | Defaults | NONE | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | +--------------+---------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 1001174eb7b8..857c7271ccd4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -38,7 +38,7 @@ }, "require-dev": { "symfony/browser-kit": "~2.4|~3.0.0", - "symfony/console": "~2.8.8|~3.0.8", + "symfony/console": "~2.8.19|~3.3", "symfony/css-selector": "^2.0.5|~3.0.0", "symfony/dom-crawler": "^2.0.5|~3.0.0", "symfony/polyfill-intl-icu": "~1.0", From f0c4b3fb8096911a080b923cc3fc1ef3526abb8f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Apr 2017 21:04:21 -0700 Subject: [PATCH 79/80] updated CHANGELOG for 2.8.19 --- CHANGELOG-2.8.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 54e46eb428f2..65264dd3ec5b 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,46 @@ 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.19 (2017-04-05) + + * bug #22265 Allow Upper Case property names (insekticid) + * bug #22258 [DI] Autowiring and factories are incompatible with each others (nicolas-grekas) + * bug #22254 [DI] Don't use auto-registered services to populate type-candidates (nicolas-grekas) + * bug #22229 [ExpressionLanguage] Provide the expression in syntax errors (k0pernikus, stof) + * bug #22251 [PropertyInfo] Support nullable array or collection (4rthem) + * bug #22240 [DI] Fix fatal error at ContainerBuilder::compile() if config is not installed (chalasr) + * bug #22140 [Form] Improve the exceptions when trying to get the data in a PRE_SET_DATA listener and the data has not already been set (fancyweb) + * bug #22217 [Console] Fix table cell styling (ro0NL) + * bug #22194 [Console] CommandTester: disable color support detection (julienfalque) + * bug #22188 [Console] Revised exception rendering (ro0NL) + * bug #22154 [WebProfilerBundle] Normalize whitespace in exceptions passed in headers (curry684) + * bug #22142 [Console] Escape exception messages in renderException (chalasr) + * bug #22172 Fix port usage in server:status command (alcaeus) + * bug #22164 [Bridge\Doctrine] Fix change breaking doctrine-bundle test suite (nicolas-grekas) + * bug #22133 [Filesystem] normalize paths before making them relative (xabbuh) + * bug #22138 [HttpFoundation][bugfix] $bags should always be initialized (MacDada) + * bug #21810 #21809 [SecurityBundle] bugfix: if security provider's name contains upper cases then container didn't compile (Antanas Arvasevicius) + * bug #22123 [WebProfilerBundle] Fix for CSS attribute at Profiler Translation Page (e-moe) + * bug #19778 [Security] Fixed roles serialization on token from user object (eko) + * bug #22036 Set Date header in Response constructor already (mpdude) + * bug #22022 [Validator] fix URL validator to detect non supported chars according to RFC 3986 (e-moe) + * bug #21849 [HttpFoundation] Fix missing handling of for/host/proto info from "Forwarded" header (nicolas-grekas) + * bug #21968 Fixed pathinfo calculation for requests starting with a question mark. (syzygymsu) + * bug #22027 Revert "bug #21841 [Console] Do not squash input changes made from console.command event (chalasr)" (chalasr) + * bug #21846 [HttpFoundation] Fix Request::getHost() when having several hosts in X_FORWARDED_HOST (nicolas-grekas) + * bug #21208 [Validator] Add object handling of invalid constraints in Composite (SenseException) + * bug #22044 [Serializer] [XML] Ignore Process Instruction (jordscream) + * bug #22079 [HttpKernel] Fixed bug with purging of HTTPS URLs (ausi) + * bug #21523 #20411 fix Yaml parsing for very long quoted strings (RichardBradley) + * bug #22001 [Doctrine Bridge] fix priority for doctrine event listeners (dmaicher) + * bug #21981 [Console] Use proper line endings in BufferedOutput (julienfalque) + * bug #21976 [VarDumper] Add missing isset() checks in some casters (nicolas-grekas) + * bug #21957 [Form] Choice type int values (BC Fix) (mcfedr) + * bug #21923 [travis] Test with hhvm 3.18 (nicolas-grekas) + * bug #21823 dumpFile(), preserve existing file permissions (chs2) + * bug #21865 [Security] context listener: hardening user provider handling (xabbuh) + * bug #21883 [HttpKernel] fix Kernel name when stored in a directory starting with a number (fabpot) + * 2.8.18 (2017-03-06) * bug #21841 [Console] Do not squash input changes made from console.command event (chalasr) From 19ccd43812851de341868518b80e745fc556089d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Apr 2017 21:04:34 -0700 Subject: [PATCH 80/80] updated VERSION for 2.8.19 --- 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 97cc5111970a..b871a8ebd498 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.19-DEV'; + const VERSION = '2.8.19'; const VERSION_ID = 20819; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 19; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019';