From dd69b8875dc2477a12edc18f1baaf0113c8331b3 Mon Sep 17 00:00:00 2001 From: Julien Falque Date: Mon, 7 Nov 2016 20:38:43 +0100 Subject: [PATCH 01/60] Fix bundle commands are not available via find() --- .../FrameworkBundle/Console/Application.php | 10 ++++ .../Tests/Console/ApplicationTest.php | 46 +++++++++++-------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 221a00425069b..6e6aca6043c67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -90,6 +90,16 @@ public function doRun(InputInterface $input, OutputInterface $output) return parent::doRun($input, $output); } + /** + * {@inheritdoc} + */ + public function find($name) + { + $this->registerCommands(); + + return parent::find($name); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index fc0e7654db2ca..a944da863f6d0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -32,8 +32,7 @@ public function testBundleInterfaceImplementation() public function testBundleCommandsAreRegistered() { - $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); - $bundle->expects($this->once())->method('registerCommands'); + $bundle = $this->createBundleMock(array()); $kernel = $this->getKernel(array($bundle), true); @@ -46,8 +45,7 @@ public function testBundleCommandsAreRegistered() public function testBundleCommandsAreRetrievable() { - $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); - $bundle->expects($this->once())->method('registerCommands'); + $bundle = $this->createBundleMock(array()); $kernel = $this->getKernel(array($bundle)); @@ -60,47 +58,41 @@ public function testBundleCommandsAreRetrievable() public function testBundleSingleCommandIsRetrievable() { - $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); - $bundle->expects($this->once())->method('registerCommands'); + $command = new Command('example'); + + $bundle = $this->createBundleMock(array($command)); $kernel = $this->getKernel(array($bundle)); $application = new Application($kernel); - $command = new Command('example'); - $application->add($command); - $this->assertSame($command, $application->get('example')); } public function testBundleCommandCanBeFound() { - $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); - $bundle->expects($this->once())->method('registerCommands'); + $command = new Command('example'); + + $bundle = $this->createBundleMock(array($command)); $kernel = $this->getKernel(array($bundle)); $application = new Application($kernel); - $command = new Command('example'); - $application->add($command); - $this->assertSame($command, $application->find('example')); } public function testBundleCommandCanBeFoundByAlias() { - $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); - $bundle->expects($this->once())->method('registerCommands'); + $command = new Command('example'); + $command->setAliases(array('alias')); + + $bundle = $this->createBundleMock(array($command)); $kernel = $this->getKernel(array($bundle)); $application = new Application($kernel); - $command = new Command('example'); - $command->setAliases(array('alias')); - $application->add($command); - $this->assertSame($command, $application->find('alias')); } @@ -167,4 +159,18 @@ private function getKernel(array $bundles, $useDispatcher = false) return $kernel; } + + private function createBundleMock(array $commands) + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); + $bundle + ->expects($this->once()) + ->method('registerCommands') + ->will($this->returnCallback(function (Application $application) use ($commands) { + $application->addCommands($commands); + })) + ; + + return $bundle; + } } From 6954a071915dc2a4d214ade0a6041eae8bbceb22 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 12 Nov 2016 12:41:58 +0100 Subject: [PATCH 02/60] [Doctrine][Form] support large integers --- .../Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php | 2 +- .../Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 632cdbfec0558..8930dc9f27377 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -104,7 +104,7 @@ public function getEntitiesByIds($identifier, array $values) // Filter out non-integer values (e.g. ""). If we don't, some // databases such as PostgreSQL fail. $values = array_values(array_filter($values, function ($v) { - return (string) $v === (string) (int) $v; + return (string) $v === (string) (int) $v || ctype_digit($v); })); } elseif ('guid' === $metadata->getTypeOfField($identifier)) { $parameterType = Connection::PARAM_STR_ARRAY; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index d755af5430bc4..1f07b8e465db0 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -87,7 +87,7 @@ public function testFilterNonIntegerValues() $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(1, 2, 3), Connection::PARAM_INT_ARRAY) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(1, 2, 3, '9223372036854775808'), Connection::PARAM_INT_ARRAY) ->willReturn($query); $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') @@ -103,7 +103,7 @@ public function testFilterNonIntegerValues() ->from('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', 'e'); $loader = new ORMQueryBuilderLoader($qb); - $loader->getEntitiesByIds('id', array(1, '', 2, 3, 'foo')); + $loader->getEntitiesByIds('id', array(1, '', 2, 3, 'foo', '9223372036854775808')); } public function testEmbeddedIdentifierName() From 55e134cab0173c484cb9ed3f0252a4609f90ab7b Mon Sep 17 00:00:00 2001 From: Pierre-Chanel Gauthier Date: Fri, 18 Nov 2016 18:16:13 +0100 Subject: [PATCH 03/60] Fix annotation type for $context Previous type ExecutionContextInterface was referring to a non declared namespace. Replacing it by ExecutionContextInterface2Dot5 fixes autocomplete. --- src/Symfony/Component/Validator/ConstraintValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/ConstraintValidator.php b/src/Symfony/Component/Validator/ConstraintValidator.php index b156c6dde9a16..804a9b2a193ec 100644 --- a/src/Symfony/Component/Validator/ConstraintValidator.php +++ b/src/Symfony/Component/Validator/ConstraintValidator.php @@ -38,7 +38,7 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface const OBJECT_TO_STRING = 2; /** - * @var ExecutionContextInterface + * @var ExecutionContextInterface2Dot5 */ protected $context; From aefd0489a9d57e9fbe533513bde7c1931f47a834 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Nov 2016 17:12:23 -0800 Subject: [PATCH 04/60] updated CHANGELOG for 2.7.21 --- CHANGELOG-2.7.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index c6f63e1b6c2b5..fd12d3a03612e 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,24 @@ 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.21 (2016-11-21) + + * bug #20543 [DI] Fix error when trying to resolve a DefinitionDecorator (nicolas-grekas) + * bug #20484 bumped min version of Twig to 1.28 (fabpot) + * bug #20519 [Debug] Remove GLOBALS from exception context to avoid endless recursion (Seldaek) + * bug #20455 [ClassLoader] Fix ClassCollectionLoader inlining with __halt_compiler (giosh94mhz) + * bug #20307 [Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds (LuisDeimos) + * bug #20466 [Translation] fixed nested fallback catalogue using multiple locales. (aitboudad) + * bug #20465 [#18637][TranslationDebug] workaround for getFallbackLocales. (aitboudad) + * bug #20440 [TwigBridge][TwigBundle][HttpKernel] prefer getSourceContext() over getSource() (xabbuh) + * bug #20422 [Translation][fallback] add missing resources in parent catalogues. (aitboudad) + * bug #20378 [Form] Fixed show float values as choice value in ChoiceType (yceruto) + * bug #20375 [HttpFoundation][Session] Fix memcache session handler (klandaika) + * bug #20377 [Console] Fix infinite loop on missing input (chalasr) + * bug #20342 [Form] Fix UrlType transforms valid protocols (ogizanagi) + * bug #20292 Enhance GAE compat by removing some realpath() (nicolas-grekas) + * bug #20321 Compatibility with Twig 1.27 (xkobal) + * 2.7.20 (2016-10-27) * bug #20289 Fix edge case with StreamedResponse where headers are sent twice (Nicofuma) From 4367d0c853363be7f26eca812f24c070e12eda2a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Nov 2016 17:12:28 -0800 Subject: [PATCH 05/60] update CONTRIBUTORS for 2.7.21 --- CONTRIBUTORS.md | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 41c883159c8e2..c5fb26e0e91d8 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -22,16 +22,16 @@ Symfony is the result of the work of many people who made the code better - Abdellatif Ait boudad (aitboudad) - Pascal Borreli (pborreli) - Wouter De Jong (wouterj) - - Joseph Bielawski (stloyd) - Romain Neutron (romain) + - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) + - Grégoire Pineau (lyrixx) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Grégoire Pineau (lyrixx) - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Sarah Khalil (saro0h) @@ -45,11 +45,11 @@ Symfony is the result of the work of many people who made the code better - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) + - Robin Chalas (chalas_r) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - Diego Saint Esteben (dii3g0) - - Robin Chalas (chalas_r) - Ener-Getick (energetick) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) @@ -84,19 +84,19 @@ Symfony is the result of the work of many people who made the code better - Fran Moreno (franmomu) - Antoine Hérault (herzult) - Paráda József (paradajozsef) + - Roland Franssen (ro0) + - Dariusz Ruminski - Jáchym Toušek (enumag) - Arnaud Le Blanc (arnaud-lb) - Jérôme Tamarelle (gromnan) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - - Dariusz Ruminski - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - marc.weistroff - Issei Murasawa (issei_m) - lenar - Włodzimierz Gajda (gajdaw) - - Roland Franssen (ro0) - Baptiste Clavié (talus) - Alexander Schwenn (xelaris) - Florian Voutzinos (florianv) @@ -132,6 +132,7 @@ Symfony is the result of the work of many people who made the code better - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) - jwdeitch + - Tobias Nyholm (tobias) - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) - Vyacheslav Pavlov @@ -145,12 +146,14 @@ Symfony is the result of the work of many people who made the code better - Clemens Tolboom - Helmer Aaviksoo - Hiromi Hishida (77web) + - Yonel Ceruto González (yonelceruto) - Richard van Laak (rvanlaak) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba + - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -160,13 +163,12 @@ Symfony is the result of the work of many people who made the code better - Richard Miller (mr_r_miller) - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) - - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - Lars Strojny (lstrojny) - - Yonel Ceruto González (yonelceruto) + - Maxime STEINHAUSSER - Stepan Anchugov (kix) - bronze1man - sun (sun) @@ -236,7 +238,6 @@ Symfony is the result of the work of many people who made the code better - Grégoire Paris (greg0ire) - Leo Feyer - Chekote - - Tobias Nyholm (tobias) - Thomas Adam - Albert Casademont (acasademont) - Jhonny Lidfors (jhonne) @@ -245,6 +246,7 @@ Symfony is the result of the work of many people who made the code better - Nikita Konstantinov - Wodor Wodorski - Thomas Lallement (raziel057) + - Giorgio Premi - Matthieu Napoli (mnapoli) - Beau Simensen (simensen) - Michael Hirschler (mvhirsch) @@ -295,7 +297,6 @@ Symfony is the result of the work of many people who made the code better - Mark Challoner (markchalloner) - Gregor Harlan (gharlan) - Gennady Telegin (gtelegin) - - Giorgio Premi - Ben Davies (bendavies) - Erin Millard - Artur Melo (restless) @@ -393,7 +394,6 @@ Symfony is the result of the work of many people who made the code better - Christian Schmidt - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - - Maxime STEINHAUSSER - Marek Pietrzak - Chad Sikorra (chadsikorra) - franek (franek) @@ -439,6 +439,7 @@ Symfony is the result of the work of many people who made the code better - Vicent Soria Durá (vicentgodella) - Nicolas Dewez (nicolas_dewez) - Anthony Ferrara + - Victor Bocharsky (bocharsky_bw) - Ioan Negulescu - Jakub Škvára (jskvara) - Andrew Udvare (audvare) @@ -611,7 +612,6 @@ Symfony is the result of the work of many people who made the code better - Andrew Tchircoff (andrewtch) - michaelwilliams - 1emming - - Victor Bocharsky (bocharsky_bw) - Leevi Graham (leevigraham) - Jordan Deitch - Casper Valdemar Poulsen @@ -769,6 +769,7 @@ Symfony is the result of the work of many people who made the code better - fabios - Sander Coolen (scoolen) - Nicolas Le Goff (nlegoff) + - Andreas Braun - Ben Oman - Manuele Menozzi - Anton Babenko (antonbabenko) @@ -858,6 +859,7 @@ Symfony is the result of the work of many people who made the code better - rpg600 - Péter Buri (burci) - Davide Borsatto (davide.borsatto) + - Indra Gunawan (guind) - kaiwa - Charles Sanquer (csanquer) - Albert Ganiev (helios-ag) @@ -969,6 +971,7 @@ Symfony is the result of the work of many people who made the code better - Sandro Hopf - Łukasz Makuch - George Giannoulopoulos + - Luis Ramirez (luisdeimos) - Daniel Richter (richtermeister) - ChrisC - Ilya Biryukov @@ -985,6 +988,7 @@ Symfony is the result of the work of many people who made the code better - Pete Mitchell (peterjmit) - Tom Corrigan (tomcorrigan) - Martin Pärtel + - Noah Heck (myesain) - Patrick Daley (padrig) - Xavier Briand (xavierbriand) - Max Summe @@ -1041,6 +1045,7 @@ Symfony is the result of the work of many people who made the code better - Sebastian Ionescu - Thomas Ploch - Simon Neidhold + - Xavier HAUSHERR - Valentin VALCIU - Kevin Dew - James Cowgill @@ -1163,6 +1168,7 @@ Symfony is the result of the work of many people who made the code better - Koalabaerchen - michalmarcinkowski - Warwick + - VJ - Chris - JakeFr - Simon Sargeant @@ -1236,6 +1242,7 @@ Symfony is the result of the work of many people who made the code better - Joel Marcey - David Christmann - root + - Wouter J - James Hudson - Tom Maguire - David Zuelke @@ -1312,6 +1319,7 @@ Symfony is the result of the work of many people who made the code better - Jelle Bekker (jbekker) - Ian Jenkins (jenkoian) - Jorge Martin (jorgemartind) + - Julien Falque (julienfalque) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - Muriel (metalmumu) @@ -1379,6 +1387,7 @@ Symfony is the result of the work of many people who made the code better - Jörg Rühl - wesleyh - sergey + - Karim Miladi - Michael Genereux - patrick-mcdougle - Dariusz Czech @@ -1559,6 +1568,7 @@ Symfony is the result of the work of many people who made the code better - Sergey Fedotov - Michael - fh-github@fholzhauer.de + - Jan Emrich - Mark Topper - Xavier REN - Zander Baldwin From dec83adc4b434763b047d20dc6ee003cb5118c29 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Nov 2016 17:12:54 -0800 Subject: [PATCH 06/60] updated VERSION for 2.7.21 --- 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 5bd08cbd1537b..423bcd19f2225 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.21-DEV'; + const VERSION = '2.7.21'; const VERSION_ID = 20721; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 21; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 2af58be68f891806f6fed363838584e90a852350 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Nov 2016 18:19:38 -0800 Subject: [PATCH 07/60] bumped Symfony version to 2.7.22 --- 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 423bcd19f2225..4ed457d9931a1 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.21'; - const VERSION_ID = 20721; + const VERSION = '2.7.22-DEV'; + const VERSION_ID = 20722; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 21; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 22; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From d94a631f4d49cb001c425bec6e3bfca21bf98ebd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Nov 2016 18:42:55 -0800 Subject: [PATCH 08/60] bumped Symfony version to 2.8.15 --- 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 5d958b272298a..408ff9d874913 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.14'; - const VERSION_ID = 20814; + const VERSION = '2.8.15-DEV'; + const VERSION_ID = 20815; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 14; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 15; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 2acaf5f5112ea353e04879e91e116904d9ebf8e7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 2 Nov 2016 09:57:00 +0100 Subject: [PATCH 09/60] [github] Tweak PR template --- .github/PULL_REQUEST_TEMPLATE.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 99ba8e00213af..216a2ba4e5625 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,19 @@ | Q | A | ------------- | --- -| Branch? | "master" for new features / 2.7, 2.8 or 3.1 for fixes +| Branch? | master / 2.7, 2.8, 3.1 or 3.2 | Bug fix? | yes/no | New feature? | yes/no | BC breaks? | yes/no | Deprecations? | yes/no | Tests pass? | yes/no -| Fixed tickets | comma-separated list of tickets fixed by the PR, if any +| Fixed tickets | #... | License | MIT -| Doc PR | reference to the documentation PR, if any +| Doc PR | symfony/symfony-docs#... + + From 69bfbbf8c2481f75673b0c796938a2d466690bb0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 21 Nov 2016 09:40:36 +0100 Subject: [PATCH 10/60] [Process] Do feat test before enabling TTY mode --- src/Symfony/Component/Process/Process.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index d6adf21fa9390..5b23192eb9734 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -911,8 +911,16 @@ public function setTty($tty) if ('\\' === DIRECTORY_SEPARATOR && $tty) { throw new RuntimeException('TTY mode is not supported on Windows platform.'); } - if ($tty && (!file_exists('/dev/tty') || !is_readable('/dev/tty'))) { - throw new RuntimeException('TTY mode requires /dev/tty to be readable.'); + if ($tty) { + static $isTtySupported; + + if (null === $isTtySupported) { + $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes); + } + + if (!$isTtySupported) { + throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); + } } $this->tty = (bool) $tty; @@ -1214,7 +1222,7 @@ public static function isPtySupported() return $result = false; } - return $result = (bool) @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes); + return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes); } /** From b25c1d30f6bc1e8aa90a8f53963b6c8f38af18cf Mon Sep 17 00:00:00 2001 From: Julien Falque Date: Mon, 21 Nov 2016 23:14:54 +0100 Subject: [PATCH 11/60] Fix complete config tests --- .../DependencyInjection/CompleteConfigurationTest.php | 8 ++++++-- .../PhpCompleteConfigurationTest.php | 10 +++++++--- .../XmlCompleteConfigurationTest.php | 10 +++++++--- .../YamlCompleteConfigurationTest.php | 10 +++++++--- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 8a0a14ddb32a8..16e5787bdf60e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -21,7 +21,9 @@ abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase { private static $containerCache = array(); - abstract protected function loadFromFile(ContainerBuilder $container, $file); + abstract protected function getLoader(ContainerBuilder $container); + + abstract protected function getFileExtension(); public function testRolesHierarchy() { @@ -237,6 +239,8 @@ public function testRememberMeThrowExceptions() protected function getContainer($file) { + $file = $file.'.'.$this->getFileExtension(); + if (isset(self::$containerCache[$file])) { return self::$containerCache[$file]; } @@ -246,7 +250,7 @@ protected function getContainer($file) $bundle = new SecurityBundle(); $bundle->build($container); // Attach all default factories - $this->loadFromFile($container, $file); + $this->getLoader($container)->load($file); $container->getCompilerPassConfig()->setOptimizationPasses(array()); $container->getCompilerPassConfig()->setRemovingPasses(array()); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/PhpCompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/PhpCompleteConfigurationTest.php index 131c38d5e50b7..6495485d1bb87 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/PhpCompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/PhpCompleteConfigurationTest.php @@ -17,9 +17,13 @@ class PhpCompleteConfigurationTest extends CompleteConfigurationTest { - protected function loadFromFile(ContainerBuilder $container, $file) + protected function getLoader(ContainerBuilder $container) { - $loadXml = new PhpFileLoader($container, new FileLocator(__DIR__.'/Fixtures/php')); - $loadXml->load($file.'.php'); + return new PhpFileLoader($container, new FileLocator(__DIR__.'/Fixtures/php')); + } + + protected function getFileExtension() + { + return 'php'; } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCompleteConfigurationTest.php index cf6833a22ab61..2399f5ee460dc 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCompleteConfigurationTest.php @@ -17,9 +17,13 @@ class XmlCompleteConfigurationTest extends CompleteConfigurationTest { - protected function loadFromFile(ContainerBuilder $container, $file) + protected function getLoader(ContainerBuilder $container) { - $loadXml = new XmlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/xml')); - $loadXml->load($file.'.xml'); + return new XmlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/xml')); + } + + protected function getFileExtension() + { + return 'xml'; } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/YamlCompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/YamlCompleteConfigurationTest.php index 568b8623ea007..d5d5e693abdcd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/YamlCompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/YamlCompleteConfigurationTest.php @@ -17,9 +17,13 @@ class YamlCompleteConfigurationTest extends CompleteConfigurationTest { - protected function loadFromFile(ContainerBuilder $container, $file) + protected function getLoader(ContainerBuilder $container) { - $loadXml = new YamlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/yml')); - $loadXml->load($file.'.yml'); + return new YamlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/yml')); + } + + protected function getFileExtension() + { + return 'yml'; } } From 6c3150df63379516802a43ef9a832d376df42c45 Mon Sep 17 00:00:00 2001 From: Imangazaliev Date: Sun, 13 Nov 2016 14:38:04 +0300 Subject: [PATCH 12/60] [DOMCrawler] Bug fixed --- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index cf588eae5aad8..d4b7d45009a40 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -816,7 +816,7 @@ public static function xpathLiteral($s) } } - return sprintf('concat(%s)', implode($parts, ', ')); + return sprintf('concat(%s)', implode(', ', $parts)); } /** From 7752308c962aafe24c645edff0bda2783ed6f20a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 22 Nov 2016 19:19:49 +0100 Subject: [PATCH 13/60] [DI] Aliases should preserve the aliased invalid behavior --- .../DependencyInjection/ContainerBuilder.php | 2 +- .../Tests/ContainerBuilderTest.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 7c9f5a243190a..d391459bcb284 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -430,7 +430,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV } if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) { - return $this->get($this->aliasDefinitions[$id]); + return $this->get($this->aliasDefinitions[$id], $invalidBehavior); } try { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 8f8c8b179f790..7f13417fb97a9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -231,6 +231,18 @@ public function testSetReplacesAlias() $this->assertSame($foo, $builder->get('alias'), '->set() replaces an existing alias'); } + public function testAliasesKeepInvalidBehavior() + { + $builder = new ContainerBuilder(); + + $aliased = new Definition('stdClass'); + $aliased->addMethodCall('setBar', array(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); + $builder->setDefinition('aliased', $aliased); + $builder->setAlias('alias', 'aliased'); + + $this->assertEquals(new \stdClass(), $builder->get('alias')); + } + public function testAddGetCompilerPass() { $builder = new ContainerBuilder(); From 0c3b7d7b8d9d6542b3484936754c9d27dc263fa6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 23 Nov 2016 13:49:06 +0100 Subject: [PATCH 14/60] [HttpKernel] Revert BC breaking change of Request::isMethodSafe() --- .../Component/HttpFoundation/BinaryFileResponse.php | 2 +- src/Symfony/Component/HttpFoundation/Request.php | 6 ++++-- .../Component/HttpFoundation/Tests/RequestTest.php | 9 ++++++++- .../HttpKernel/EventListener/FragmentListener.php | 2 +- src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php | 2 +- .../Security/Http/Firewall/ExceptionListener.php | 2 +- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index a39984dffa717..f95d90c364051 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -190,7 +190,7 @@ public function prepare(Request $request) if (!$this->headers->has('Accept-Ranges')) { // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); + $this->headers->set('Accept-Ranges', $request->isMethodSafe(false) ? 'bytes' : 'none'); } if (!$this->headers->has('Content-Type')) { diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index ad1578758663b..cdaa57e0e6ff6 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1466,11 +1466,13 @@ public function isMethod($method) /** * Checks whether the method is safe or not. * + * @param bool $andCacheable Adds the additional condition that the method should be cacheable. True by default. + * * @return bool */ - public function isMethodSafe() + public function isMethodSafe(/* $andCacheable = true */) { - return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); + return in_array($this->getMethod(), 0 < func_num_args() && !func_get_arg(0) ? array('GET', 'HEAD', 'OPTIONS', 'TRACE') : array('GET', 'HEAD')); } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 2fa72d9aacfed..ad06622696298 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1929,7 +1929,7 @@ public function testMethodSafe($method, $safe) { $request = new Request(); $request->setMethod($method); - $this->assertEquals($safe, $request->isMethodSafe()); + $this->assertEquals($safe, $request->isMethodSafe(false)); } public function methodSafeProvider() @@ -1948,6 +1948,13 @@ public function methodSafeProvider() ); } + public function testMethodSafeChecksCacheable() + { + $request = new Request(); + $request->setMethod('OPTION'); + $this->assertFalse($request->isMethodSafe()); + } + /** * @dataProvider methodCacheableProvider */ diff --git a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php index 2ab6c8589eec3..ad6349286dde7 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php @@ -81,7 +81,7 @@ public function onKernelRequest(GetResponseEvent $event) protected function validateRequest(Request $request) { // is the Request safe? - if (!$request->isMethodSafe()) { + if (!$request->isMethodSafe(false)) { throw new AccessDeniedHttpException(); } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index efb08d693c891..941d4c6fa033d 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -202,7 +202,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } $this->traces[$request->getMethod().' '.$path] = array(); - if (!$request->isMethodSafe()) { + if (!$request->isMethodSafe(false)) { $response = $this->invalidate($request, $catch); } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { $response = $this->pass($request, $catch); diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index a1cae2a437214..4e8066b7e198b 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -209,7 +209,7 @@ private function startAuthentication(Request $request, AuthenticationException $ protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example - if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) { + if ($request->hasSession() && $request->isMethodSafe(false) && !$request->isXmlHttpRequest()) { $request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri()); } } From 412fbe613fe9a8ff203c5b2cda796b2d77eb9813 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 23 Nov 2016 22:37:45 +0100 Subject: [PATCH 15/60] [DI] minor FileLoaders tests update --- .../DependencyInjection/Tests/Loader/XmlFileLoaderTest.php | 4 ++-- .../DependencyInjection/Tests/Loader/YamlFileLoaderTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 2de5915f4ef41..1989c61fd3dae 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -131,8 +131,8 @@ public function testLoadImports() { $container = new ContainerBuilder(); $resolver = new LoaderResolver(array( - new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), - new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), + new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')), + new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yml')), $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), )); $loader->setResolver($resolver); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 0827b48eb8d12..b2082f07a126d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -104,8 +104,8 @@ public function testLoadImports() { $container = new ContainerBuilder(); $resolver = new LoaderResolver(array( - new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), - new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), + new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')), + new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')), $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), )); From 7a5e11eb1206a121824b09a3e645d74b0781c92e Mon Sep 17 00:00:00 2001 From: kiler129 Date: Wed, 23 Nov 2016 11:45:56 -0600 Subject: [PATCH 16/60] =?UTF-8?q?[DI]=20Fixed=20custom=20services=20defini?= =?UTF-8?q?tion=20BC=20break=20introduced=20in=20ec7e70fb=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DependencyInjection/ContainerBuilder.php | 4 ++-- .../Tests/ContainerBuilderTest.php | 11 ++++++++++- .../Tests/Fixtures/CustomDefinition.php | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/CustomDefinition.php diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 7c9f5a243190a..28ff635854b48 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -840,8 +840,8 @@ public function findDefinition($id) */ public function createService(Definition $definition, $id, $tryProxy = true) { - if ('Symfony\Component\DependencyInjection\Definition' !== get_class($definition)) { - throw new RuntimeException(sprintf('Constructing service "%s" from a %s is not supported at build time.', $id, get_class($definition))); + if ($definition instanceof DefinitionDecorator) { + throw new RuntimeException(sprintf('Constructing decorated service "%s" from a %s is not supported at build time.', $id, get_class($definition))); } if ($definition->isSynthetic()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 8f8c8b179f790..cb91eb50ed2d9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -29,6 +29,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition; use Symfony\Component\ExpressionLanguage\Expression; class ContainerBuilderTest extends \PHPUnit_Framework_TestCase @@ -407,7 +408,7 @@ public function testResolveServices() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Constructing service "foo" from a Symfony\Component\DependencyInjection\DefinitionDecorator is not supported at build time. + * @expectedExceptionMessage Constructing decorated service "foo" from a Symfony\Component\DependencyInjection\DefinitionDecorator is not supported at build time. */ public function testResolveServicesWithDecoratedDefinition() { @@ -419,6 +420,14 @@ public function testResolveServicesWithDecoratedDefinition() $builder->get('foo'); } + public function testResolveServicesWithCustomDefinitionClass() + { + $builder = new ContainerBuilder(); + $builder->setDefinition('foo', new CustomDefinition('stdClass')); + + $this->assertInstanceOf('stdClass', $builder->get('foo')); + } + public function testMerge() { $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CustomDefinition.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CustomDefinition.php new file mode 100644 index 0000000000000..65eea2106ed70 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CustomDefinition.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\DependencyInjection\Tests\Fixtures; + +use Symfony\Component\DependencyInjection\Definition; + +class CustomDefinition extends Definition +{ +} From 962325a54e5e4c8deb8cb21ee414e8ac68dbf4e1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Nov 2016 18:44:53 +0100 Subject: [PATCH 17/60] [WebProfilerBundle] Dont use request attributes in RouterController --- .../Bundle/WebProfilerBundle/Controller/RouterController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php index d77eb279f4a69..b5d299e204184 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php @@ -87,7 +87,7 @@ private function getTraces(RequestDataCollector $request, $method) $traceRequest = Request::create( $request->getPathInfo(), $request->getRequestServer()->get('REQUEST_METHOD'), - $request->getRequestAttributes()->all(), + array(), $request->getRequestCookies()->all(), array(), $request->getRequestServer()->all() From 97e94b4019ee2a386dfd5f543a2ffa4fe37c79d4 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 24 Nov 2016 22:33:31 +0100 Subject: [PATCH 18/60] Tag missing internals --- src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php | 4 ++-- src/Symfony/Component/Form/Util/OrderedHashMapIterator.php | 4 ++-- .../Core/Authentication/RememberMe/PersistentToken.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index c429417c25f80..c479daa75ee78 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -155,11 +155,11 @@ public function setValue($value) /** * Adds a choice to the current ones. * - * This method should only be used internally. - * * @param \DOMElement $node * * @throws \LogicException When choice provided is not multiple nor radio + * + * @internal */ public function addChoice(\DOMElement $node) { diff --git a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php index 32f591c860698..534d74ea6f0e4 100644 --- a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php +++ b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php @@ -14,9 +14,9 @@ /** * Iterator for {@link OrderedHashMap} objects. * - * This class is internal and should not be used. - * * @author Bernhard Schussek + * + * @internal */ class OrderedHashMapIterator implements \Iterator { diff --git a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php index d85572d0e07db..76873fc603cd7 100644 --- a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php @@ -12,9 +12,9 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe; /** - * This class is only used by PersistentTokenRememberMeServices internally. - * * @author Johannes M. Schmitt + * + * @internal */ final class PersistentToken implements PersistentTokenInterface { From 0af433b01f6d0b7870fc20e752e313c4eae0b8a0 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 19 Nov 2016 11:21:18 +0000 Subject: [PATCH 19/60] [DI] Initialize properties before method calls --- .../DependencyInjection/ContainerBuilder.php | 8 ++++---- .../DependencyInjection/Dumper/PhpDumper.php | 6 +++--- .../Tests/ContainerBuilderTest.php | 14 ++++++++++++++ .../Tests/Dumper/PhpDumperTest.php | 19 +++++++++++++++++++ .../Tests/Fixtures/includes/classes.php | 17 +++++++++++++++++ .../Tests/Fixtures/php/services9.php | 6 +++--- .../Tests/Fixtures/php/services9_compiled.php | 6 +++--- 7 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 7c9f5a243190a..9313370004b2b 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -902,15 +902,15 @@ public function createService(Definition $definition, $id, $tryProxy = true) $this->shareService($definition, $service, $id); } - foreach ($definition->getMethodCalls() as $call) { - $this->callMethod($service, $call); - } - $properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties()))); foreach ($properties as $name => $value) { $service->$name = $value; } + foreach ($definition->getMethodCalls() as $call) { + $this->callMethod($service, $call); + } + if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { $callable[0] = $parameterBag->resolveValue($callable[0]); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 37c3275444bcc..2f7a01bc081d4 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -335,8 +335,8 @@ private function addServiceInlinedDefinitions($id, $definition) $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { - $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); $code .= $this->addServiceProperties(null, $sDefinition, $name); + $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); $code .= $this->addServiceConfigurator(null, $sDefinition, $name); } @@ -507,8 +507,8 @@ private function addServiceInlinedDefinitionsSetup($id, Definition $definition) } $name = (string) $this->definitionVariables->offsetGet($iDefinition); - $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceProperties(null, $iDefinition, $name); + $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceConfigurator(null, $iDefinition, $name); } @@ -663,8 +663,8 @@ private function addService($id, Definition $definition) $this->addServiceInlinedDefinitions($id, $definition). $this->addServiceInstance($id, $definition). $this->addServiceInlinedDefinitionsSetup($id, $definition). - $this->addServiceMethodCalls($id, $definition). $this->addServiceProperties($id, $definition). + $this->addServiceMethodCalls($id, $definition). $this->addServiceConfigurator($id, $definition). $this->addServiceReturn($id, $definition) ; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 8f8c8b179f790..16e8ae19d244b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -798,6 +798,20 @@ public function testLazyLoadedService() $this->assertTrue($classInList); } + + public function testInitializePropertiesBeforeMethodCalls() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass'); + $container->register('bar', 'MethodCallClass') + ->setProperty('simple', 'bar') + ->setProperty('complex', new Reference('foo')) + ->addMethodCall('callMe'); + + $container->compile(); + + $this->assertTrue($container->get('bar')->callPassed(), '->compile() initializes properties before method calls'); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 3d9570d4dbcef..72215e8c486a5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -267,4 +267,23 @@ public function testInlinedDefinitionReferencingServiceContainer() $dumper = new PhpDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container'); } + + public function testInitializePropertiesBeforeMethodCalls() + { + require_once self::$fixturesPath.'/includes/classes.php'; + + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass'); + $container->register('bar', 'MethodCallClass') + ->setProperty('simple', 'bar') + ->setProperty('complex', new Reference('foo')) + ->addMethodCall('callMe'); + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls'))); + + $container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls(); + $this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls'); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index 70c3d275b8898..48b687c1f4e53 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -59,3 +59,20 @@ public function __construct(BarClass $bar) $this->bar = $bar; } } + +class MethodCallClass +{ + public $simple; + public $complex; + private $callPassed = false; + + public function callMe() + { + $this->callPassed = is_scalar($this->simple) && is_object($this->complex); + } + + public function callPassed() + { + return $this->callPassed; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index abdfcbce3a55a..ce8930b8ddeba 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -170,11 +170,11 @@ protected function getFooService() $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this); - $instance->setBar($this->get('bar')); - $instance->initialize(); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')); + $instance->setBar($this->get('bar')); + $instance->initialize(); sc_configure($instance); return $instance; @@ -333,8 +333,8 @@ protected function getInlinedService() { $this->services['inlined'] = $instance = new \Bar(); - $instance->setBaz($this->get('baz')); $instance->pub = 'pub'; + $instance->setBaz($this->get('baz')); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 6ee0d40f5652e..559560fa6da60 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -179,11 +179,11 @@ protected function getFooService() $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); - $instance->setBar($this->get('bar')); - $instance->initialize(); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); + $instance->setBar($this->get('bar')); + $instance->initialize(); sc_configure($instance); return $instance; @@ -230,8 +230,8 @@ protected function getFooWithInlineService() $this->services['foo_with_inline'] = $instance = new \Foo(); - $a->setBaz($this->get('baz')); $a->pub = 'pub'; + $a->setBaz($this->get('baz')); $instance->setBar($a); From c17a85beff05e6b1255fe7bfe14beade27315f94 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Nov 2016 10:58:59 +0100 Subject: [PATCH 20/60] [HttpFoundation] Add links to RFC-7231 --- src/Symfony/Component/HttpFoundation/Request.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index cdaa57e0e6ff6..888e5fdc010d3 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1466,6 +1466,8 @@ public function isMethod($method) /** * Checks whether the method is safe or not. * + * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 + * * @param bool $andCacheable Adds the additional condition that the method should be cacheable. True by default. * * @return bool @@ -1478,6 +1480,8 @@ public function isMethodSafe(/* $andCacheable = true */) /** * Checks whether the method is cacheable or not. * + * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 + * * @return bool */ public function isMethodCacheable() From 25a629419a86bb1f8344ad5c5f18a4ef038e6ebd Mon Sep 17 00:00:00 2001 From: Alexandru Bucur Date: Fri, 25 Nov 2016 10:30:34 +0200 Subject: [PATCH 21/60] Update documentation link to the component Update documentation link to the component since it has standalone examples --- src/Symfony/Component/Validator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/README.md b/src/Symfony/Component/Validator/README.md index 9dfbffb3f545a..3ccb2901adeac 100644 --- a/src/Symfony/Component/Validator/README.md +++ b/src/Symfony/Component/Validator/README.md @@ -7,7 +7,7 @@ The Validator component provides tools to validate values following the Resources --------- - * [Documentation](https://symfony.com/doc/current/book/validation.html) + * [Documentation](https://symfony.com/doc/current/components/validator.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) From cf333f32c567a759cd583025e63849c776eddd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Tue, 1 Nov 2016 12:50:51 +0100 Subject: [PATCH 22/60] [FrameworkBundle] Improve performance of ControllerNameParser --- .../Controller/ControllerNameParser.php | 5 +++-- .../Routing/DelegatingLoader.php | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index 374d0eba10ff6..989dc8cd23d7c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -46,11 +46,12 @@ public function __construct(KernelInterface $kernel) */ public function parse($controller) { - $originalController = $controller; - if (3 !== count($parts = explode(':', $controller))) { + $parts = explode(':', $controller); + if (3 !== count($parts) || in_array('', $parts, true)) { throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.', $controller)); } + $originalController = $controller; list($bundle, $controller, $action) = $parts; $controller = str_replace('/', '\\', $controller); $bundles = array(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php index 801149372af99..22f658ee7d5cb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php @@ -21,7 +21,7 @@ * DelegatingLoader delegates route loading to other loaders using a loader resolver. * * This implementation resolves the _controller attribute from the short notation - * to the fully-qualified form (from a:b:c to class:method). + * to the fully-qualified form (from a:b:c to class::method). * * @author Fabien Potencier */ @@ -85,15 +85,18 @@ public function load($resource, $type = null) $this->loading = false; foreach ($collection->all() as $route) { - if ($controller = $route->getDefault('_controller')) { - try { - $controller = $this->parser->parse($controller); - } catch (\InvalidArgumentException $e) { - // unable to optimize unknown notation - } + $controller = $route->getDefault('_controller'); + if (!$controller) { + continue; + } - $route->setDefault('_controller', $controller); + try { + $controller = $this->parser->parse($controller); + } catch (\InvalidArgumentException $e) { + // unable to optimize unknown notation } + + $route->setDefault('_controller', $controller); } return $collection; From 73fbd085f184a97de3400e4bbf05b0ed139d5ec6 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 10 Nov 2016 15:01:21 +0100 Subject: [PATCH 23/60] [Routing] Fail properly when a route parameter name cannot be used as a PCRE subpattern name --- .../Component/Routing/RouteCompiler.php | 24 +++++++++++++++---- .../Routing/Tests/RouteCompilerTest.php | 16 ++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index f6637da666b82..1ce18ceb6607c 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -28,12 +28,22 @@ class RouteCompiler implements RouteCompilerInterface */ const SEPARATORS = '/,;.:-_~+*=@|'; + /** + * The maximum supported length of a PCRE subpattern name + * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. + * + * @var int + * + * @internal + */ + const VARIABLE_MAXIMUM_LENGTH = 32; + /** * {@inheritdoc} * * @throws \LogicException If a variable is referenced more than once - * @throws \DomainException If a variable name is numeric because PHP raises an error for such - * subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)". + * @throws \DomainException If a variable name starts with a digit or if it is too long to be successfully used as + * a PCRE subpattern. */ public static function compile(Route $route) { @@ -95,13 +105,19 @@ private static function compilePattern(Route $route, $pattern, $isHost) $precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : ''; $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); - if (is_numeric($varName)) { - throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern)); + // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the + // variable would not be usable as a Controller action argument. + if (preg_match('/^\d/', $varName)) { + throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); } if (in_array($varName, $variables)) { throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); } + if (strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { + throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); + } + if ($isSeparator && strlen($precedingText) > 1) { $tokens[] = array('text', substr($precedingText, 0, -1)); } elseif (!$isSeparator && strlen($precedingText) > 0) { diff --git a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php index b4b4f45a8379f..f08b9688a921d 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Routing\Tests; use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCompiler; class RouteCompilerTest extends \PHPUnit_Framework_TestCase { @@ -176,16 +177,16 @@ public function testRouteWithSameVariableTwice() } /** - * @dataProvider getNumericVariableNames + * @dataProvider getVariableNamesStartingWithADigit * @expectedException \DomainException */ - public function testRouteWithNumericVariableName($name) + public function testRouteWithVariableNameStartingWithADigit($name) { $route = new Route('/{'.$name.'}'); $route->compile(); } - public function getNumericVariableNames() + public function getVariableNamesStartingWithADigit() { return array( array('09'), @@ -264,4 +265,13 @@ public function provideCompileWithHostData() ), ); } + + /** + * @expectedException \DomainException + */ + public function testRouteWithTooLongVariableName() + { + $route = new Route(sprintf('/{%s}', str_repeat('a', RouteCompiler::VARIABLE_MAXIMUM_LENGTH + 1))); + $route->compile(); + } } From 70c42f2676eb82ba2d6137919ddf50b41eaa73ee Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Wed, 16 Nov 2016 18:59:59 +0100 Subject: [PATCH 24/60] Cast result to int before adding to it This fixes the occasional warning about non-numeric values when using PHP 7.1 --- .../Loader/XmlFileLoader.php | 23 ++++++++++--------- .../xml/with_key_outside_collection.xml | 9 ++++++++ .../Tests/Loader/XmlFileLoaderTest.php | 9 ++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/with_key_outside_collection.xml diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index e60c2f7df76c1..b3e4ef4d3e7c1 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -346,21 +346,22 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $lowercase = true) $arg->setAttribute('key', $arg->getAttribute('name')); } - if (!$arg->hasAttribute('key')) { - $key = !$arguments ? 0 : max(array_keys($arguments)) + 1; - } else { - $key = $arg->getAttribute('key'); - } - - // parameter keys are case insensitive - if ('parameter' == $name && $lowercase) { - $key = strtolower($key); - } - // this is used by DefinitionDecorator to overwrite a specific // argument of the parent definition if ($arg->hasAttribute('index')) { $key = 'index_'.$arg->getAttribute('index'); + } elseif (!$arg->hasAttribute('key')) { + // Append an empty argument, then fetch its key to overwrite it later + $arguments[] = null; + $keys = array_keys($arguments); + $key = array_pop($keys); + } else { + $key = $arg->getAttribute('key'); + + // parameter keys are case insensitive + if ('parameter' == $name && $lowercase) { + $key = strtolower($key); + } } switch ($arg->getAttribute('type')) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/with_key_outside_collection.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/with_key_outside_collection.xml new file mode 100644 index 0000000000000..5f3a2843612df --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/with_key_outside_collection.xml @@ -0,0 +1,9 @@ + + + + + foo + bar + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 2de5915f4ef41..fd4517228430c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -542,4 +542,13 @@ public function testLoadInlinedServices() $this->assertSame('Baz', $barConfigurator[0]->getClass()); $this->assertSame('configureBar', $barConfigurator[1]); } + + public function testArgumentWithKeyOutsideCollection() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('with_key_outside_collection.xml'); + + $this->assertSame(array('type' => 'foo', 'bar'), $container->getDefinition('foo')->getArguments()); + } } From 7e8490715c29e02270cee788f09a2b0e43496a5e Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sun, 6 Nov 2016 15:11:25 +0100 Subject: [PATCH 25/60] [Form] fixed "empty_value" option deprecation --- .../Component/Form/Extension/Core/Type/ChoiceType.php | 9 +++++++-- .../Component/Form/Extension/Core/Type/DateType.php | 4 ++-- .../Component/Form/Extension/Core/Type/TimeType.php | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 49bea1aceca09..d376109828718 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -39,6 +39,11 @@ class ChoiceType extends AbstractType { + /** + * @internal To be removed in 3.0 + */ + const DEPRECATED_EMPTY_VALUE = '__deprecated_empty_value__'; + /** * Caches created choice lists. * @@ -336,7 +341,7 @@ public function configureOptions(OptionsResolver $resolver) }; $placeholderNormalizer = function (Options $options, $placeholder) use ($that) { - if (!is_object($options['empty_value']) || !$options['empty_value'] instanceof \Exception) { + if ($that::DEPRECATED_EMPTY_VALUE !== $options['empty_value']) { @trigger_error(sprintf('The form option "empty_value" of the "%s" form type (%s) is deprecated since version 2.6 and will be removed in 3.0. Use "placeholder" instead.', $that->getName(), __CLASS__), E_USER_DEPRECATED); if (null === $placeholder || '' === $placeholder) { @@ -388,7 +393,7 @@ public function configureOptions(OptionsResolver $resolver) 'preferred_choices' => array(), 'group_by' => null, 'empty_data' => $emptyData, - 'empty_value' => new \Exception(), // deprecated + 'empty_value' => self::DEPRECATED_EMPTY_VALUE, 'placeholder' => $placeholder, 'error_bubbling' => false, 'compound' => $compound, diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index ae4c6bacf2066..8af7a96f13cd6 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -183,7 +183,7 @@ public function configureOptions(OptionsResolver $resolver) }; $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (!is_object($options['empty_value']) || !$options['empty_value'] instanceof \Exception) { + if (ChoiceType::DEPRECATED_EMPTY_VALUE !== $options['empty_value']) { @trigger_error('The form option "empty_value" is deprecated since version 2.6 and will be removed in 3.0. Use "placeholder" instead.', E_USER_DEPRECATED); $placeholder = $options['empty_value']; @@ -218,7 +218,7 @@ public function configureOptions(OptionsResolver $resolver) 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, - 'empty_value' => new \Exception(), // deprecated + 'empty_value' => ChoiceType::DEPRECATED_EMPTY_VALUE, 'placeholder' => $placeholder, 'html5' => true, // Don't modify \DateTime classes by reference, we treat diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index 8232170278502..dab0572927be8 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -171,7 +171,7 @@ public function configureOptions(OptionsResolver $resolver) }; $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (!is_object($options['empty_value']) || !$options['empty_value'] instanceof \Exception) { + if (ChoiceType::DEPRECATED_EMPTY_VALUE !== $options['empty_value']) { @trigger_error('The form option "empty_value" is deprecated since version 2.6 and will be removed in 3.0. Use "placeholder" instead.', E_USER_DEPRECATED); $placeholder = $options['empty_value']; @@ -203,7 +203,7 @@ public function configureOptions(OptionsResolver $resolver) 'with_seconds' => false, 'model_timezone' => null, 'view_timezone' => null, - 'empty_value' => new \Exception(), // deprecated + 'empty_value' => ChoiceType::DEPRECATED_EMPTY_VALUE, 'placeholder' => $placeholder, 'html5' => true, // Don't modify \DateTime classes by reference, we treat From 2699009770ab5fc6b198d879acede4780efab08b Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 25 Nov 2016 23:28:18 +0100 Subject: [PATCH 26/60] [HttpFoundation] Fix test ensuring isMethodSafe() checks cacheable --- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index ad06622696298..74f058923f13b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1951,7 +1951,7 @@ public function methodSafeProvider() public function testMethodSafeChecksCacheable() { $request = new Request(); - $request->setMethod('OPTION'); + $request->setMethod('OPTIONS'); $this->assertFalse($request->isMethodSafe()); } From 73cf7960297b2892d064717c5fe68c8dc0320c30 Mon Sep 17 00:00:00 2001 From: Jerzy Zawadzki Date: Sun, 27 Nov 2016 21:34:49 +0000 Subject: [PATCH 27/60] bug #20653 [WebProfilerBundle] Profiler includes ghost panels --- .../WebProfilerBundle/Resources/views/Profiler/layout.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig index bcf97ddcbfb46..a3d761deedba2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig @@ -38,7 +38,7 @@ {% for name, template in templates %} {% set menu -%} {% with { 'collector': profile.getcollector(name) } %} - {{ block('menu', template) }} + {{- block('menu', template) -}} {% endwith %} {%- endset %} {% if menu != '' %} From 56c8ff8b219cbb4d151f2459cb1c2b2718f6059a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 28 Nov 2016 07:53:19 +0100 Subject: [PATCH 28/60] ensure the proper context for nested validations --- .../Validator/Context/ExecutionContext.php | 5 +++++ .../Tests/Validator/Abstract2Dot5ApiTest.php | 19 +++++++++++++++++++ .../RecursiveContextualValidator.php | 10 ++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index dce975c2038e6..721766a253383 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -287,6 +287,11 @@ public function getGroup() return $this->group; } + public function getConstraint() + { + return $this->constraint; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php index 27d5a25ce26a8..1e6f3403e7284 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Tests\Validator; use Symfony\Component\Validator\Constraints\Callback; +use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Traverse; @@ -720,4 +721,22 @@ public function testPassConstraintToViolation() $this->assertCount(1, $violations); $this->assertSame($constraint, $violations[0]->getConstraint()); } + + public function testCollectionConstraitViolationHasCorrectContext() + { + $data = array( + 'foo' => 'fooValue', + ); + + // Missing field must not be the first in the collection validation + $constraint = new Collection(array( + 'foo' => new NotNull(), + 'bar' => new NotNull(), + )); + + $violations = $this->validate($data, $constraint); + + $this->assertCount(1, $violations); + $this->assertSame($constraint, $violations[0]->getConstraint()); + } } diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index db5d8809690d1..bbd09b821241c 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; +use Symfony\Component\Validator\Context\ExecutionContext; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\NoSuchMetadataException; @@ -110,6 +111,11 @@ public function validate($value, $constraints = null, $groups = null) $previousMetadata = $this->context->getMetadata(); $previousPath = $this->context->getPropertyPath(); $previousGroup = $this->context->getGroup(); + $previousConstraint = null; + + if ($this->context instanceof ExecutionContext || method_exists($this->context, 'getConstraint')) { + $previousConstraint = $this->context->getConstraint(); + } // If explicit constraints are passed, validate the value against // those constraints @@ -138,6 +144,10 @@ public function validate($value, $constraints = null, $groups = null) $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); + if (null !== $previousConstraint) { + $this->context->setConstraint($previousConstraint); + } + return $this; } From 595a9781e2482e2cd0929a888eb99b8d90696b2c Mon Sep 17 00:00:00 2001 From: Antanas Arvasevicius Date: Sat, 10 Sep 2016 20:39:00 +0300 Subject: [PATCH 29/60] [DependencyInjection] PhpDumper.php: hasReference() should not search references in lazy service arguments. --- .../Compiler/CheckCircularReferencesPass.php | 17 ++++--- .../DependencyInjection/Dumper/PhpDumper.php | 7 +++ .../Tests/Dumper/PhpDumperTest.php | 51 +++++++++++++++++++ .../Tests/Fixtures/includes/classes.php | 30 +++++++++++ 4 files changed, 99 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php index d7570ddc2c4d1..b6a898736f653 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php @@ -60,14 +60,19 @@ private function checkOutEdges(array $edges) $id = $node->getId(); if (empty($this->checkedNodes[$id])) { - $searchKey = array_search($id, $this->currentPath); - $this->currentPath[] = $id; - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey)); - } + // * don't check circular dependencies in lazy services. + $isLazy = $node->getValue() && $node->getValue()->isLazy(); + if (!$isLazy) { + $searchKey = array_search($id, $this->currentPath); + $this->currentPath[] = $id; + + if (false !== $searchKey) { + throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey)); + } - $this->checkOutEdges($node->getOutEdges()); + $this->checkOutEdges($node->getOutEdges()); + } $this->checkedNodes[$id] = true; array_pop($this->currentPath); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 2f7a01bc081d4..bf5956b394d43 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1293,6 +1293,13 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi $visited[$argumentId] = true; $service = $this->container->getDefinition($argumentId); + + // if exists proxy dumper (proxy-manager) don't search references in lazy services. + // As these services will be instantiated lazily and don't have direct related references. + if ($service->isLazy() && !($this->getProxyDumper() instanceof NullDumper)) { + continue; + } + $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); if ($this->hasReference($id, $arguments, $deep, $visited)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 72215e8c486a5..ab9d5926106a5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper; +use DummyProxyDumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; @@ -19,6 +20,8 @@ use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\ExpressionLanguage\Expression; +require_once __DIR__.'/../Fixtures/includes/classes.php'; + class PhpDumperTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; @@ -286,4 +289,52 @@ public function testInitializePropertiesBeforeMethodCalls() $container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls(); $this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls'); } + + public function testCircularReferenceAllowanceForLazyServices() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->addArgument(new Reference('bar')); + $container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo')); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->dump(); + } + + public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServices() + { + /* + * test graph: + * [connection] -> [event_manager] --> [entity_manager](lazy) + * | + * --(call)- addEventListener ("@lazy_service") + * + * [lazy_service](lazy) -> [entity_manager](lazy) + * + */ + + $container = new ContainerBuilder(); + + $eventManagerDefinition = new Definition('stdClass'); + + $connectionDefinition = $container->register('connection', 'stdClass'); + $connectionDefinition->addArgument($eventManagerDefinition); + + $container->register('entity_manager', 'stdClass') + ->setLazy(true) + ->addArgument(new Reference('connection')); + + $lazyServiceDefinition = $container->register('lazy_service', 'stdClass'); + $lazyServiceDefinition->setLazy(true); + $lazyServiceDefinition->addArgument(new Reference('entity_manager')); + + $eventManagerDefinition->addMethodCall('addEventListener', array(new Reference('lazy_service'))); + + $container->compile(); + + $dumper = new PhpDumper($container); + + $dumper->setProxyDumper(new DummyProxyDumper()); + $dumper->dump(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index 48b687c1f4e53..cdc89e42ab3a8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -1,5 +1,8 @@ configure(); @@ -76,3 +79,30 @@ public function callPassed() return $this->callPassed; } } + +class DummyProxyDumper implements ProxyDumper +{ + /** + * {@inheritdoc} + */ + public function isProxyCandidate(Definition $definition) + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getProxyFactoryCode(Definition $definition, $id) + { + return ''; + } + + /** + * {@inheritdoc} + */ + public function getProxyCode(Definition $definition) + { + return ''; + } +} From 6d1f1b5d4ade77b53de83064cecadfb01fb20eed Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 28 Nov 2016 20:51:39 +0100 Subject: [PATCH 30/60] [ClassLoader] Use only forward slashes in generated class map --- .../Component/ClassLoader/ClassCollectionLoader.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php index 593ed44ca0eb5..5d09848952e8e 100644 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -63,7 +63,7 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir)); } $cacheDir = rtrim(realpath($cacheDir) ?: $cacheDir, '/'.DIRECTORY_SEPARATOR); - $cache = $cacheDir.DIRECTORY_SEPARATOR.$name.$extension; + $cache = $cacheDir.'/'.$name.$extension; // auto-reload $reload = false; @@ -114,7 +114,7 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = REGEX; $dontInlineRegex = str_replace('.', $spacesRegex, $dontInlineRegex); - $cacheDir = explode(DIRECTORY_SEPARATOR, $cacheDir); + $cacheDir = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $cacheDir)); $files = array(); $content = ''; foreach (self::getOrderedClasses($classes) as $class) { @@ -126,7 +126,7 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = $c = file_get_contents($file); if (preg_match($dontInlineRegex, $c)) { - $file = explode(DIRECTORY_SEPARATOR, $file); + $file = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $file)); for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) { if ($file[$i] !== $cacheDir[$i]) { @@ -134,11 +134,11 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = } } if (1 >= $i) { - $file = var_export(implode(DIRECTORY_SEPARATOR, $file), true); + $file = var_export(implode('/', $file), true); } else { $file = array_slice($file, $i); - $file = str_repeat('..'.DIRECTORY_SEPARATOR, count($cacheDir) - $i).implode(DIRECTORY_SEPARATOR, $file); - $file = '__DIR__.'.var_export(DIRECTORY_SEPARATOR.$file, true); + $file = str_repeat('../', count($cacheDir) - $i).implode('/', $file); + $file = '__DIR__.'.var_export('/'.$file, true); } $c = "\nnamespace {require $file;}"; From 609245e9536961fcaa5a871b46a7717fd1f9a639 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 28 Nov 2016 14:17:01 +0100 Subject: [PATCH 31/60] [Config] ConfigCache::isFresh() should return false on __PHP_Incomplete_Class --- src/Symfony/Component/Config/ConfigCache.php | 27 ++++++++++++++++++- .../Config/Tests/ConfigCacheTest.php | 9 +++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index cc99bc9211cde..a34328ee8f31f 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -85,8 +85,33 @@ public function isFresh() return false; } + $e = null; + $meta = false; $time = filemtime($this->file); - $meta = unserialize(file_get_contents($metadata)); + $signalingException = new \UnexpectedValueException(); + $prevUnserializeHandler = ini_set('unserialize_callback_func', ''); + $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) { + if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) { + throw $signalingException; + } + + return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; + }); + + try { + $meta = unserialize(file_get_contents($metadata)); + } catch (\Error $e) { + } catch (\Exception $e) { + } + restore_error_handler(); + ini_set('unserialize_callback_func', $prevUnserializeHandler); + if (null !== $e && $e !== $signalingException) { + throw $e; + } + if (false === $meta) { + return false; + } + foreach ($meta as $resource) { if (!$resource->isFresh($time)) { return false; diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index f3f2a446a2bf6..ee30d0b394fdd 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -93,6 +93,15 @@ public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() $this->assertFalse($cache->isFresh()); } + public function testCacheIsNotFreshWhenUnserializeFails() + { + file_put_contents($this->metaFile, str_replace('FileResource', 'ClassNotHere', file_get_contents($this->metaFile))); + + $cache = new ConfigCache($this->cacheFile, true); + + $this->assertFalse($cache->isFresh()); + } + public function testWriteDumpsFile() { unlink($this->cacheFile); From 18fc6b54da0108cb0393142066affa005c99e88b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 30 Nov 2016 19:19:43 +0100 Subject: [PATCH 32/60] [Console] Fix wrong handling of multiline arg/opt descriptions --- .../Console/Descriptor/TextDescriptor.php | 16 ++++++++-------- .../Console/Tests/Fixtures/input_argument_4.txt | 2 +- .../Console/Tests/Fixtures/input_option_5.txt | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index 0d722ed5aaeae..eb02c89dfa372 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -38,13 +38,13 @@ protected function describeInputArgument(InputArgument $argument, array $options } $totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName()); - $spacingWidth = $totalWidth - strlen($argument->getName()) + 2; + $spacingWidth = $totalWidth - strlen($argument->getName()); - $this->writeText(sprintf(' %s%s%s%s', + $this->writeText(sprintf(' %s %s%s%s', $argument->getName(), str_repeat(' ', $spacingWidth), - // + 17 = 2 spaces + + + 2 spaces - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), $default ), $options); } @@ -75,13 +75,13 @@ protected function describeInputOption(InputOption $option, array $options = arr sprintf('--%s%s', $option->getName(), $value) ); - $spacingWidth = $totalWidth - strlen($synopsis) + 2; + $spacingWidth = $totalWidth - strlen($synopsis); - $this->writeText(sprintf(' %s%s%s%s%s', + $this->writeText(sprintf(' %s %s%s%s%s', $synopsis, str_repeat(' ', $spacingWidth), - // + 17 = 2 spaces + + + 2 spaces - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.txt index aa74e8ceb2507..fc7d669a112ec 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.txt @@ -1,2 +1,2 @@ argument_name multiline - argument description + argument description diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.txt index 4368883cc7217..9563b4cab142c 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.txt @@ -1,2 +1,2 @@ -o, --option_name=OPTION_NAME multiline - option description + option description From 26f588a7b584b3e39f6223d06bbb305e00e6453c Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 1 Dec 2016 15:23:59 +0100 Subject: [PATCH 33/60] Fix unresolved parameters from default bundle configs in debug:config --- .../Bundle/FrameworkBundle/Command/ConfigDebugCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 9059905e04f54..22a98d8023a4e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -90,7 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln(sprintf('# Current configuration for "%s"', $name)); } - $output->writeln(Yaml::dump(array($extension->getAlias() => $config), 10)); + $output->writeln(Yaml::dump(array($extension->getAlias() => $container->getParameterBag()->resolveValue($config)), 10)); } private function compileContainer() From 997beb21bf942c1f54ae225c8da61a13255ef396 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 1 Dec 2016 20:26:29 +0100 Subject: [PATCH 34/60] [WebProfilerBundle] Fix dump block is unfairly restrained --- .../Resources/views/Profiler/toolbar.css.twig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index d87e81399d412..14dd2d4b591ce 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -356,11 +356,13 @@ border-color: #777; border-radius: 0; margin: 6px 0 12px 0; - width: 200px; } .sf-toolbar-block-dump pre.sf-dump:last-child { margin-bottom: 0; } +.sf-toolbar-block-dump .sf-toolbar-info-piece { + display: block; +} .sf-toolbar-block-dump .sf-toolbar-info-piece .sf-toolbar-file-line { color: #AAA; margin-left: 4px; From 2c818193c1ead4748a8f31d687418f0baff91898 Mon Sep 17 00:00:00 2001 From: Maxime STEINHAUSSER Date: Thu, 1 Dec 2016 11:14:14 +0100 Subject: [PATCH 35/60] [TwigBundle] Fix twig loader registered twice --- .../TwigBundle/DependencyInjection/Compiler/ExtensionPass.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 87469984688ab..d09de2d615c0a 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -73,7 +74,7 @@ public function process(ContainerBuilder $container) $loader->addTag('twig.loader'); $loader->setMethodCalls($container->getDefinition('twig.loader.filesystem')->getMethodCalls()); - $container->setDefinition('twig.loader.filesystem', $loader); + $container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false)); } if ($container->has('assets.packages')) { From 9b9d33959cf8402ed16a988f0ff1dd27d386f712 Mon Sep 17 00:00:00 2001 From: vlakoff Date: Sat, 3 Dec 2016 05:32:18 +0100 Subject: [PATCH 36/60] [Finder] Refine phpdoc about argument for NumberComparator --- src/Symfony/Component/Finder/Comparator/NumberComparator.php | 2 +- src/Symfony/Component/Finder/Finder.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Finder/Comparator/NumberComparator.php b/src/Symfony/Component/Finder/Comparator/NumberComparator.php index 4b5b5ba8380ce..16f91285a6d8c 100644 --- a/src/Symfony/Component/Finder/Comparator/NumberComparator.php +++ b/src/Symfony/Component/Finder/Comparator/NumberComparator.php @@ -37,7 +37,7 @@ class NumberComparator extends Comparator /** * Constructor. * - * @param string $test A comparison string + * @param string|int $test A comparison string or an integer * * @throws \InvalidArgumentException If the test is not understood */ diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 90dcd20958118..c9d14809dc28a 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -200,7 +200,7 @@ public function files() * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * - * @param int $level The depth level expression + * @param string|int $level The depth level expression * * @return Finder|SplFileInfo[] The current Finder instance * @@ -372,7 +372,7 @@ public function notPath($pattern) * $finder->size('<= 1Ki'); * $finder->size(4); * - * @param string $size A size range string + * @param string|int $size A size range string or an integer * * @return Finder|SplFileInfo[] The current Finder instance * From 5f62f0194304fd5e22caa290e625d01c735bf848 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 3 Dec 2016 11:50:08 +0100 Subject: [PATCH 37/60] fixed CS --- .../Compiler/CheckCircularReferencesPass.php | 5 ++--- .../Component/DependencyInjection/Dumper/PhpDumper.php | 6 +++--- .../Tests/Fixtures/includes/classes.php | 9 --------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php index b6a898736f653..11856b6cbc053 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php @@ -61,9 +61,8 @@ private function checkOutEdges(array $edges) if (empty($this->checkedNodes[$id])) { - // * don't check circular dependencies in lazy services. - $isLazy = $node->getValue() && $node->getValue()->isLazy(); - if (!$isLazy) { + // don't check circular dependencies for lazy services + if (!$node->getValue() && $node->getValue()->isLazy()) { $searchKey = array_search($id, $this->currentPath); $this->currentPath[] = $id; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index bf5956b394d43..c4bfa93d2a950 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1294,9 +1294,9 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi $service = $this->container->getDefinition($argumentId); - // if exists proxy dumper (proxy-manager) don't search references in lazy services. - // As these services will be instantiated lazily and don't have direct related references. - if ($service->isLazy() && !($this->getProxyDumper() instanceof NullDumper)) { + // if the proxy manager is enabled, disable searching for references in lazy services, + // as these services will be instantiated lazily and don't have direct related references. + if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index cdc89e42ab3a8..0ecdea3fbfb89 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -82,25 +82,16 @@ public function callPassed() class DummyProxyDumper implements ProxyDumper { - /** - * {@inheritdoc} - */ public function isProxyCandidate(Definition $definition) { return false; } - /** - * {@inheritdoc} - */ public function getProxyFactoryCode(Definition $definition, $id) { return ''; } - /** - * {@inheritdoc} - */ public function getProxyCode(Definition $definition) { return ''; From 36b7ba64f4a27c742be010f855d0fb27bfccfb76 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 2 Nov 2016 11:44:02 -0400 Subject: [PATCH 38/60] [Form][DX] FileType "multiple" fixes --- .../Form/Extension/Core/Type/FileType.php | 41 ++++++++++++++++--- .../Extension/Core/Type/FileTypeTest.php | 27 ++++++++++++ 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index bc24899de5cb0..914c9402fc8e4 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -12,12 +12,37 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; +use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class FileType extends AbstractType { + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + if ($options['multiple']) { + $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { + $form = $event->getForm(); + $data = $event->getData(); + + // submitted data for an input file (not required) without choosing any file + if (array(null) === $data) { + $emptyData = $form->getConfig()->getEmptyData(); + + $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData; + $event->setData($data); + } + }); + } + } + /** * {@inheritdoc} */ @@ -39,9 +64,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) */ public function finishView(FormView $view, FormInterface $form, array $options) { - $view - ->vars['multipart'] = true - ; + $view->vars['multipart'] = true; } /** @@ -49,10 +72,18 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function configureOptions(OptionsResolver $resolver) { + $dataClass = function (Options $options) { + return $options['multiple'] ? null : 'Symfony\Component\HttpFoundation\File\File'; + }; + + $emptyData = function (Options $options) { + return $options['multiple'] ? array() : null; + }; + $resolver->setDefaults(array( 'compound' => false, - 'data_class' => 'Symfony\Component\HttpFoundation\File\File', - 'empty_data' => null, + 'data_class' => $dataClass, + 'empty_data' => $emptyData, 'multiple' => false, )); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php index 55555efecb7bf..c6a61af8b7159 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -44,6 +44,33 @@ public function testSubmitEmpty() $this->assertNull($form->getData()); } + public function testSubmitEmptyMultiple() + { + $form = $this->factory->createBuilder('file', null, array( + 'multiple' => true, + ))->getForm(); + + // submitted data when an input file is uploaded without choosing any file + $form->submit(array(null)); + + $this->assertSame(array(), $form->getData()); + } + + public function testSetDataMultiple() + { + $form = $this->factory->createBuilder('file', null, array( + 'multiple' => true, + ))->getForm(); + + $data = array( + $this->createUploadedFileMock('abcdef', 'first.jpg', true), + $this->createUploadedFileMock('zyxwvu', 'second.jpg', true), + ); + + $form->setData($data); + $this->assertSame($data, $form->getData()); + } + public function testSubmitMultiple() { $form = $this->factory->createBuilder('file', null, array( From aea04784513aff2e9e56cfe692746597ccb2392e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 3 Dec 2016 14:48:59 +0100 Subject: [PATCH 39/60] fix a test checking for a value --- .../Compiler/CheckCircularReferencesPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php index 11856b6cbc053..156bcc0c3ab7b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php @@ -62,7 +62,7 @@ private function checkOutEdges(array $edges) if (empty($this->checkedNodes[$id])) { // don't check circular dependencies for lazy services - if (!$node->getValue() && $node->getValue()->isLazy()) { + if (!$node->getValue() || !$node->getValue()->isLazy()) { $searchKey = array_search($id, $this->currentPath); $this->currentPath[] = $id; From d1a7164626f06f5bcaeab20ff964318ef474b88b Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Mon, 5 Dec 2016 08:37:16 +0100 Subject: [PATCH 40/60] Regression test for missing controller arguments --- .../HttpKernel/Controller/ControllerResolver.php | 10 +++++++++- .../Tests/Controller/ControllerResolverTest.php | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index c76b57bb6a7db..a1cff53535dc1 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -36,6 +36,13 @@ class ControllerResolver implements ControllerResolverInterface */ private $supportsVariadic; + /** + * If scalar types exists. + * + * @var bool + */ + private $supportsScalarTypes; + /** * Constructor. * @@ -46,6 +53,7 @@ public function __construct(LoggerInterface $logger = null) $this->logger = $logger; $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); + $this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType'); } /** @@ -132,7 +140,7 @@ protected function doGetArguments(Request $request, $controller, array $paramete $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); - } elseif ($param->allowsNull()) { + } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) { $arguments[] = null; } else { if (is_array($controller)) { diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 9aa7e20a9a910..f3b0ac025d6bf 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -223,6 +223,19 @@ public function testCreateControllerCanReturnAnyCallable() $mock->getController($request); } + /** + * @expectedException \RuntimeException + */ + public function testIfExceptionIsThrownWhenMissingAnArgument() + { + $resolver = new ControllerResolver(); + $request = Request::create('/'); + + $controller = array($this, 'controllerMethod1'); + + $resolver->getArguments($request, $controller); + } + /** * @requires PHP 7.1 */ From 899fa7936bccb786d0d661c504e06489660101d3 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sat, 3 Dec 2016 12:12:21 +0100 Subject: [PATCH 41/60] [Console] fixed PHP7 Errors when not using Dispatcher --- src/Symfony/Component/Console/Application.php | 8 +++++++- .../Console/Tests/ApplicationTest.php | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index b11268ade33bf..2aff1b635ba1c 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -843,7 +843,13 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } if (null === $this->dispatcher) { - return $command->run($input, $output); + try { + return $command->run($input, $output); + } catch (\Exception $e) { + throw $e; + } catch (\Throwable $e) { + throw new FatalThrowableError($e); + } } $event = new ConsoleCommandEvent($command, $input, $output); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 9d375f6b7b264..2612be9e9eaaa 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -951,6 +951,24 @@ public function testRunDispatchesAllEventsWithException() $this->assertContains('before.foo.caught.after.', $tester->getDisplay()); } + public function testRunWithError() + { + $this->setExpectedException('Exception', 'dymerr'); + + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dym')); + } + /** * @expectedException \LogicException * @expectedExceptionMessage caught From bfe149fdc68b411e76aca2610e2358cde50b6ac4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 5 Dec 2016 18:10:19 +0100 Subject: [PATCH 42/60] [Cache] Fix dumping SplDoublyLinkedList iter mode --- .../Component/VarDumper/Caster/SplCaster.php | 2 +- .../VarDumper/Tests/Caster/SplCasterTest.php | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index 79e8bb80b9afc..b0b57e3cda598 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -64,7 +64,7 @@ public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, S $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); $a += array( - $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_KEEP) ? 'IT_MODE_KEEP' : 'IT_MODE_DELETE'), $mode), + $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), $prefix.'dllist' => iterator_to_array($c), ); $c->setIteratorMode($mode); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php new file mode 100644 index 0000000000000..96e0307385fb6 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use Symfony\Component\VarDumper\Test\VarDumperTestCase; + +class SplCasterTest extends VarDumperTestCase +{ + /** + * @dataProvider provideCastSplDoublyLinkedList + */ + public function testCastSplDoublyLinkedList($modeValue, $modeDump) + { + $var = new \SplDoublyLinkedList(); + $var->setIteratorMode($modeValue); + $dump = <<assertDumpMatchesFormat($dump, $var); + } + + public function provideCastSplDoublyLinkedList() + { + return array( + array(\SplDoublyLinkedList::IT_MODE_FIFO, 'IT_MODE_FIFO | IT_MODE_KEEP'), + array(\SplDoublyLinkedList::IT_MODE_LIFO, 'IT_MODE_LIFO | IT_MODE_KEEP'), + array(\SplDoublyLinkedList::IT_MODE_FIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_FIFO | IT_MODE_DELETE'), + array(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'), + ); + } +} From 182f90638d9b5f2f35a177471a5afe5af29cfec7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 6 Dec 2016 15:06:08 +0100 Subject: [PATCH 43/60] Fix merge --- .../Component/Form/Tests/Extension/Core/Type/FileTypeTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php index cbeeb468c1c22..fe7a6b1d727ec 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php @@ -56,7 +56,7 @@ public function testSubmitEmpty() public function testSubmitEmptyMultiple() { - $form = $this->factory->createBuilder('file', null, array( + $form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FileType', null, array( 'multiple' => true, ))->getForm(); @@ -68,7 +68,7 @@ public function testSubmitEmptyMultiple() public function testSetDataMultiple() { - $form = $this->factory->createBuilder('file', null, array( + $form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FileType', null, array( 'multiple' => true, ))->getForm(); From 488ebbfe5d8acfad8baf8710fcdcf390962f5394 Mon Sep 17 00:00:00 2001 From: ShinDarth Date: Tue, 6 Dec 2016 16:01:27 +0100 Subject: [PATCH 44/60] [VarDumper] fix tests when xdebug is enabled --- src/Symfony/Component/VarDumper/Tests/VarClonerTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php index 1184f2c76a255..9f60032e0c62b 100644 --- a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php @@ -137,6 +137,10 @@ public function testClone() public function testJsonCast() { + if (ini_get('xdebug.overload_var_dump') == 2) { + $this->markTestSkipped('xdebug is active'); + } + $data = (array) json_decode('{"1":{}}'); $cloner = new VarCloner(); From 4e563aee0232e81667a74884978a123f24e75704 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 6 Dec 2016 21:51:50 +0100 Subject: [PATCH 45/60] fix the docblock in regard to the role argument --- .../Security/Core/Authentication/Token/AbstractToken.php | 2 +- .../Core/Authentication/Token/PreAuthenticatedToken.php | 2 +- .../Core/Authentication/Token/UsernamePasswordToken.php | 2 +- 3 files changed, 3 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 7538648b1329f..2e9c0f34b4b5d 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -33,7 +33,7 @@ abstract class AbstractToken implements TokenInterface /** * Constructor. * - * @param RoleInterface[]|string[] $roles An array of roles + * @param (RoleInterface|string)[] $roles An array of roles * * @throws \InvalidArgumentException */ diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php index b4b5e70b188fb..a5460f50839ee 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php @@ -29,7 +29,7 @@ class PreAuthenticatedToken extends AbstractToken * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string * @param mixed $credentials The user credentials * @param string $providerKey The provider key - * @param RoleInterface[]|string[] $roles An array of roles + * @param (RoleInterface|string)[] $roles An array of roles */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 33b00f01f82ae..71d19adc14f2b 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -29,7 +29,7 @@ class UsernamePasswordToken extends AbstractToken * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method * @param string $credentials This usually is the password of the user * @param string $providerKey The provider key - * @param RoleInterface[]|string[] $roles An array of roles + * @param (RoleInterface|string)[] $roles An array of roles * * @throws \InvalidArgumentException */ From ad477e705e5f95e7869d3b0aa50fb5e540bf1727 Mon Sep 17 00:00:00 2001 From: Victor Bocharsky Date: Wed, 7 Dec 2016 13:56:23 +0200 Subject: [PATCH 46/60] Fix email address --- .../Security/Guard/Token/PostAuthenticationGuardToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php b/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php index 36c40cab9579d..5b353d97a6dd6 100644 --- a/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php +++ b/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php @@ -21,7 +21,7 @@ * If you're using Guard authentication, you *must* use a class that implements * GuardTokenInterface as your authenticated token (like this class). * - * @author Ryan Weaver n@gmail.com> + * @author Ryan Weaver */ class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface { From 3f94abde00df6fd1038a8beede3f101e79352b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz?= Date: Thu, 8 Dec 2016 08:04:49 +0100 Subject: [PATCH 47/60] Fixed typo --- .../Resources/views/Collector/exception.css.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig index 197cc010d2e40..0d057b98a4334 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig @@ -9,7 +9,7 @@ padding-bottom: 2px; } .sf-reset .traces li { - ccolor: #222; + color: #222; font-size: 14px; padding: 5px 0; list-style-type: decimal; From 685a9b9d9adff18befeafffdc525e87c5034e29b Mon Sep 17 00:00:00 2001 From: Maxime STEINHAUSSER Date: Thu, 8 Dec 2016 11:30:28 +0100 Subject: [PATCH 48/60] [Config] Fix YamlReferenceDumper extra space --- .../Component/Config/Definition/Dumper/YamlReferenceDumper.php | 2 +- .../Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php | 1 + .../Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php | 1 + .../Tests/Fixtures/Configuration/ExampleConfiguration.php | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php index f9da698e0924e..12ababe39435b 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php @@ -120,7 +120,7 @@ private function writeNode(NodeInterface $node, $depth = 0) $default = (string) $default != '' ? ' '.$default : ''; $comments = count($comments) ? '# '.implode(', ', $comments) : ''; - $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' '); + $text = rtrim(sprintf('%-21s%s %s', $node->getName().':', $default, $comments), ' '); if ($info = $node->getInfo()) { $this->writeLine(''); diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php index 42207b0399e37..2c0551d062ef0 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php @@ -49,6 +49,7 @@ private function getConfigurationAsString() scalar-array-empty="" scalar-array-defaults="elem1,elem2" scalar-required="" + node-with-a-looong-name="" enum-with-default="this" enum="" > diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php index 131ca072fe6f6..ad1daddd7e07c 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php @@ -43,6 +43,7 @@ private function getConfigurationAsString() - elem1 - elem2 scalar_required: ~ # Required + node_with_a_looong_name: ~ enum_with_default: this # One of "this"; "that" enum: ~ # One of "this"; "that" diff --git a/src/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php b/src/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php index 68aa0c059399c..1573177f440ce 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php @@ -34,6 +34,7 @@ public function getConfigTreeBuilder() ->scalarNode('scalar_array_empty')->defaultValue(array())->end() ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end() ->scalarNode('scalar_required')->isRequired()->end() + ->scalarNode('node_with_a_looong_name')->end() ->enumNode('enum_with_default')->values(array('this', 'that'))->defaultValue('this')->end() ->enumNode('enum')->values(array('this', 'that'))->end() ->arrayNode('array') From 1ed9335e88ed543e8ab9104c3c2f4a5370d716a2 Mon Sep 17 00:00:00 2001 From: Maxime STEINHAUSSER Date: Thu, 8 Dec 2016 11:59:24 +0100 Subject: [PATCH 49/60] [Config] Do not skip YamlReferenceDumperTest entirely --- .../Tests/Definition/Dumper/YamlReferenceDumperTest.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php index 131ca072fe6f6..21cce575e3732 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php @@ -22,8 +22,8 @@ public function testDumper() $dumper = new YamlReferenceDumper(); + $this->assertContains($this->getConfigurationAsString(), $dumper->dump($configuration)); $this->markTestIncomplete('The Yaml Dumper currently does not support prototyped arrays'); - $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration)); } private function getConfigurationAsString() @@ -32,7 +32,7 @@ private function getConfigurationAsString() acme_root: boolean: true scalar_empty: ~ - scalar_null: ~ + scalar_null: null scalar_true: true scalar_false: false scalar_default: default @@ -59,10 +59,6 @@ enum: ~ # One of "this"; "that" # Prototype name: ~ - connections: - # Prototype - - { user: ~, pass: ~ } - EOL; } } From 073a1dae1318519066ca9fb0d2dc53392ac5fbca Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Dec 2016 13:07:24 +0100 Subject: [PATCH 50/60] [Validator] Fix init of YamlFileLoader::$classes for empty files --- .../Validator/Mapping/Loader/YamlFileLoader.php | 12 +++--------- .../Tests/Mapping/Loader/YamlFileLoaderTest.php | 4 ++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index cf6dd92dcad9b..16212833dc169 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -46,13 +46,7 @@ public function loadClassMetadata(ClassMetadata $metadata) $this->yamlParser = new YamlParser(); } - // This method may throw an exception. Do not modify the class' - // state before it completes - if (false === ($classes = $this->parseFile($this->file))) { - return false; - } - - $this->classes = $classes; + $this->classes = $this->parseFile($this->file); if (isset($this->classes['namespaces'])) { foreach ($this->classes['namespaces'] as $alias => $namespace) { @@ -111,7 +105,7 @@ protected function parseNodes(array $nodes) * * @param string $path The path of the YAML file * - * @return array|null The class descriptions or null, if the file was empty + * @return array The class descriptions * * @throws \InvalidArgumentException If the file could not be loaded or did * not contain a YAML array @@ -126,7 +120,7 @@ private function parseFile($path) // empty file if (null === $classes) { - return; + return array(); } // not an array diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php index 2ca64122aafae..15f02139ae318 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -31,6 +31,10 @@ public function testLoadClassMetadataReturnsFalseIfEmpty() $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $this->assertFalse($loader->loadClassMetadata($metadata)); + + $r = new \ReflectionProperty($loader, 'classes'); + $r->setAccessible(true); + $this->assertSame(array(), $r->getValue($loader)); } /** From 9218cacf317c0df071b4c338dd4173c63922328d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Dec 2016 14:23:09 +0100 Subject: [PATCH 51/60] [Twig] Fix deprecations with Twig 1.29 --- .../Tests/Translation/TwigExtractorTest.php | 17 ++++++++++++++--- .../Bridge/Twig/Translation/TwigExtractor.php | 12 ++++++++---- src/Symfony/Bundle/TwigBundle/TwigEngine.php | 8 +++++++- .../Resources/views/Profiler/layout.html.twig | 8 +++++--- .../Resources/views/Profiler/toolbar.html.twig | 18 ++++++++++-------- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php index 5e7c4ce5216d0..23869da436d68 100644 --- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php @@ -72,8 +72,7 @@ public function getExtractData() } /** - * @expectedException \Twig_Error - * @expectedExceptionMessageRegExp /Unclosed "block" in ".*extractor(\/|\\)syntax_error\.twig" at line 1/ + * @expectedException \Twig_Error * @dataProvider resourcesWithSyntaxErrorsProvider */ public function testExtractSyntaxError($resources) @@ -82,7 +81,19 @@ public function testExtractSyntaxError($resources) $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface'))); $extractor = new TwigExtractor($twig); - $extractor->extract($resources, new MessageCatalogue('en')); + + try { + $extractor->extract($resources, new MessageCatalogue('en')); + } catch (\Twig_Error $e) { + if (method_exists($e, 'getSourceContext')) { + $this->assertSame(dirname(__DIR__).strtr('/Fixtures/extractor/syntax_error.twig', '/', DIRECTORY_SEPARATOR), $e->getFile()); + $this->assertSame(1, $e->getLine()); + $this->assertSame('Unclosed "block".', $e->getMessage()); + } else { + $this->expectExceptionMessageRegExp('/Unclosed "block" in ".*extractor(\\/|\\\\)syntax_error\\.twig" at line 1/'); + } + throw $e; + } } /** diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php index 950c4d0810db0..35995dbd64518 100644 --- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php +++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php @@ -61,10 +61,14 @@ public function extract($resource, MessageCatalogue $catalogue) try { $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); } catch (\Twig_Error $e) { - if ($file instanceof SplFileInfo) { - $e->setTemplateName($file->getRelativePathname()); - } elseif ($file instanceof \SplFileInfo) { - $e->setTemplateName($file->getRealPath() ?: $file->getPathname()); + if ($file instanceof \SplFileInfo) { + $path = $file->getRealPath() ?: $file->getPathname(); + $name = $file instanceof SplFileInfo ? $file->getRelativePathname() : $path; + if (method_exists($e, 'setSourceContext')) { + $e->setSourceContext(new \Twig_Source('', $name, $path)); + } else { + $e->setTemplateName($name); + } } throw $e; diff --git a/src/Symfony/Bundle/TwigBundle/TwigEngine.php b/src/Symfony/Bundle/TwigBundle/TwigEngine.php index 0d01648d57587..fb4b728a5bede 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigEngine.php +++ b/src/Symfony/Bundle/TwigBundle/TwigEngine.php @@ -74,7 +74,13 @@ public function render($name, array $parameters = array()) if ($name instanceof TemplateReference) { try { // try to get the real name of the template where the error occurred - $e->setTemplateName(sprintf('%s', $this->locator->locate($this->parser->parse($e->getTemplateName())))); + $name = $e->getTemplateName(); + $path = (string) $this->locator->locate($this->parser->parse($name)); + if (method_exists($e, 'setSourceContext')) { + $e->setSourceContext(new \Twig_Source('', $name, $path)); + } else { + $e->setTemplateName($path); + } } catch (\Exception $e2) { } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig index a3d761deedba2..37be3ab98da46 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig @@ -37,9 +37,11 @@