From 317da3bdf83c5834dde2fc850509d39da8435472 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Jan 2018 17:21:59 +0100 Subject: [PATCH 01/16] keep the context when validating forms --- .../Form/Extension/Validator/Constraints/FormValidator.php | 2 ++ .../Tests/Extension/Validator/Constraints/FormValidatorTest.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index bddb8a09e8..4183e1a726 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -124,6 +124,7 @@ class FormValidator extends ConstraintValidator : gettype($form->getViewData()); if ($this->context instanceof ExecutionContextInterface) { + $this->context->setConstraint($constraint); $this->context->buildViolation($config->getOption('invalid_message')) ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) ->setInvalidValue($form->getViewData()) @@ -144,6 +145,7 @@ class FormValidator extends ConstraintValidator // Mark the form with an error if it contains extra fields if (!$config->getOption('allow_extra_fields') && count($form->getExtraData()) > 0) { if ($this->context instanceof ExecutionContextInterface) { + $this->context->setConstraint($constraint); $this->context->buildViolation($config->getOption('extra_fields_message')) ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) ->setInvalidValue($form->getExtraData()) diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 78015b5049..4bb360a99f 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -51,6 +51,8 @@ class FormValidatorTest extends AbstractConstraintValidatorTest $this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(array('getNormalizedIniPostMaxSize', 'getContentLength'))->getMock(); parent::setUp(); + + $this->constraint = new Form(); } protected function getApiVersion() From 35f98e208962d2d40f91ada5c3c994d2edc79b83 Mon Sep 17 00:00:00 2001 From: Greg Anderson Date: Fri, 19 Jan 2018 15:19:59 -0800 Subject: [PATCH 02/16] Follow-on to #25825: Fix edge case in getParameterOption. Add one test to demonstrate getParameterOption fix. Add several tests to demonstrate current limitations in hasParameterOption. --- .../Component/Console/Input/ArgvInput.php | 19 +++++++---- .../Console/Input/InputInterface.php | 4 +++ .../Console/Tests/Input/ArgvInputTest.php | 32 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index c2f533eb36..da064598d0 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -279,7 +279,11 @@ class ArgvInput extends Input foreach ($this->tokens as $token) { foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ($token === $value || 0 === strpos($token, $leading)) { return true; } } @@ -300,13 +304,16 @@ class ArgvInput extends Input $token = array_shift($tokens); foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - if (false !== $pos = strpos($token, '=')) { - return substr($token, $pos + 1); - } - + if ($token === $value) { return array_shift($tokens); } + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if (0 === strpos($token, $leading)) { + return substr($token, strlen($leading)); + } } } diff --git a/src/Symfony/Component/Console/Input/InputInterface.php b/src/Symfony/Component/Console/Input/InputInterface.php index 9de6e3a409..ac14de7d6f 100644 --- a/src/Symfony/Component/Console/Input/InputInterface.php +++ b/src/Symfony/Component/Console/Input/InputInterface.php @@ -30,6 +30,8 @@ interface InputInterface * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. * * @param string|array $values The values to look for in the raw parameters (can be an array) * @@ -42,6 +44,8 @@ interface InputInterface * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 1fe21d0f6c..04f5ce3157 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -296,6 +296,10 @@ class ArgvInputTest extends TestCase $input = new ArgvInput(array('cli.php', '-f', 'foo')); $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '-etest')); + $this->assertTrue($input->hasParameterOption('-e'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $this->assertFalse($input->hasParameterOption('-s'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '--foo', 'foo')); $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input'); @@ -306,6 +310,33 @@ class ArgvInputTest extends TestCase $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input'); } + public function testHasParameterOptionEdgeCasesAndLimitations() + { + $input = new ArgvInput(array('cli.php', '-fh')); + // hasParameterOption does not know if the previous short option, -f, + // takes a value or not. If -f takes a value, then -fh does NOT include + // -h; Otherwise it does. Since we do not know which short options take + // values, hasParameterOption does not support this use-case. + $this->assertFalse($input->hasParameterOption('-h'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // hasParameterOption does detect that `-fh` contains `-f`, since + // `-f` is the first short option in the set. + $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // The test below happens to pass, although it might make more sense + // to disallow it, and require the use of + // $input->hasParameterOption('-f') && $input->hasParameterOption('-h') + // instead. + $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // In theory, if -fh is supported, then -hf should also work. + // However, this is not supported. + $this->assertFalse($input->hasParameterOption('-hf'), '->hasParameterOption() returns true if the given short option is in the raw input'); + + $input = new ArgvInput(array('cli.php', '-f', '-h')); + // If hasParameterOption('-fh') is supported for 'cli.php -fh', then + // one might also expect that it should also be supported for + // 'cli.php -f -h'. However, this is not supported. + $this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + } + public function testToString() { $input = new ArgvInput(array('cli.php', '-f', 'foo')); @@ -327,6 +358,7 @@ class ArgvInputTest extends TestCase public function provideGetParameterOptionValues() { return array( + array(array('app/console', 'foo:bar', '-edev'), '-e', 'dev'), array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'dev'), array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'dev'), array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'dev'), From ae252916108f3006ebdc26545f130442054f0eec Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 4 Feb 2018 18:41:24 +0100 Subject: [PATCH 03/16] [HttpKernel] fix FC --- src/Symfony/Component/HttpKernel/Tests/ClientTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/ClientTest.php b/src/Symfony/Component/HttpKernel/Tests/ClientTest.php index 1ac72c7359..051d5d47c0 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ClientTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ClientTest.php @@ -97,6 +97,7 @@ class ClientTest extends TestCase public function testUploadedFile() { $source = tempnam(sys_get_temp_dir(), 'source'); + file_put_contents($source, '1'); $target = sys_get_temp_dir().'/sf.moved.file'; @unlink($target); @@ -104,8 +105,8 @@ class ClientTest extends TestCase $client = new Client($kernel); $files = array( - array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 123, 'error' => UPLOAD_ERR_OK), - new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true), + array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 1, 'error' => UPLOAD_ERR_OK), + new UploadedFile($source, 'original', 'mime/original', 1, UPLOAD_ERR_OK, true), ); $file = null; @@ -120,7 +121,7 @@ class ClientTest extends TestCase $this->assertEquals('original', $file->getClientOriginalName()); $this->assertEquals('mime/original', $file->getClientMimeType()); - $this->assertEquals('123', $file->getClientSize()); + $this->assertSame(1, $file->getClientSize()); $this->assertTrue($file->isValid()); } From f167b505c427625fc283a1720be76a83262ae9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 5 Feb 2018 08:51:00 +0100 Subject: [PATCH 04/16] [DI] minor: use a strict comparision in setDecoratedService --- src/Symfony/Component/DependencyInjection/Definition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 6f2a3c7e82..8286e9d1e7 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -144,7 +144,7 @@ class Definition */ public function setDecoratedService($id, $renamedId = null) { - if ($renamedId && $id == $renamedId) { + if ($renamedId && $id === $renamedId) { throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); } From 5f9471ef47c0f9e4a2d67dce797c653a87534add Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 5 Feb 2018 16:46:42 +0100 Subject: [PATCH 05/16] use libsodium to run Argon2i related tests --- .travis.yml | 8 ++++++++ .../DependencyInjection/Fixtures/yml/argon2i_encoder.yml | 2 +- .../Tests/Functional/UserPasswordEncoderCommandTest.php | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 245b374876..8cbcc71c82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -149,7 +149,15 @@ before_install: ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") tfold ext.apcu tpecl apcu-4.0.11 apcu.so elif [[ ! $skip && $PHP = 7.* ]]; then + # install libsodium + if [[ ! -e ~/php-ext/$(php -r "echo basename(ini_get('extension_dir'));")/libsodium/sodium.so ]]; then + sudo add-apt-repository ppa:ondrej/php -y + sudo apt-get update -q + sudo apt-get install libsodium-dev -y + fi + tfold ext.apcu tpecl apcu-5.1.6 apcu.so + tfold ext.libsodium tpecl libsodium sodium.so tfold ext.mongodb tpecl mongodb-1.4.0RC1 mongodb.so fi diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml index a51e766005..6a1f925160 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml @@ -1,6 +1,6 @@ security: encoders: - JMS\FooBundle\Entity\User6: + JMS\FooBundle\Entity\User7: algorithm: argon2i providers: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php index fa0be42c5d..01b2ce303a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php @@ -86,7 +86,7 @@ class UserPasswordEncoderCommandTest extends WebTestCase $this->assertContains('Password encoding succeeded', $output); $encoder = new Argon2iPasswordEncoder(); - preg_match('# Encoded password\s+(\$argon2i\$[\w\d,=\$+\/]+={0,2})\s+#', $output, $matches); + preg_match('# Encoded password\s+(\$argon2id\$[\w\d,=\$+\/]+={0,2})\s+#', $output, $matches); $hash = $matches[1]; $this->assertTrue($encoder->isPasswordValid($hash, 'password', null)); } @@ -272,7 +272,7 @@ EOTXT private function setupArgon2i() { putenv('COLUMNS='.(119 + strlen(PHP_EOL))); - $kernel = $this->createKernel(array('test_case' => 'PasswordEncode', 'root_config' => 'argon2i')); + $kernel = $this->createKernel(array('test_case' => 'PasswordEncode', 'root_config' => 'argon2i.yml')); $kernel->boot(); $application = new Application($kernel); From 899ead2b66639c8fdc49c2ce1e1e80424a27943d Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 6 Feb 2018 07:47:25 -0200 Subject: [PATCH 06/16] Fix misspelling variable --- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 5dad405761..96f87958ed 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1982,11 +1982,11 @@ class RequestTest extends TestCase /** * @dataProvider methodCacheableProvider */ - public function testMethodCacheable($method, $chacheable) + public function testMethodCacheable($method, $cacheable) { $request = new Request(); $request->setMethod($method); - $this->assertEquals($chacheable, $request->isMethodCacheable()); + $this->assertEquals($cacheable, $request->isMethodCacheable()); } public function methodCacheableProvider() From 54253ecfff7fc0a6b01c0e402490ce5cd916bbfb Mon Sep 17 00:00:00 2001 From: Jared Farrish Date: Sat, 27 Jan 2018 14:03:37 -0600 Subject: [PATCH 07/16] PhpDocExtractor::getTypes() throws fatal error when type omitted --- .../PropertyInfo/Extractor/PhpDocExtractor.php | 4 +++- .../Tests/Extractors/PhpDocExtractorTest.php | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 2ce31a0170..a0d6f2e5e1 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -131,7 +131,9 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property $types = array(); /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ foreach ($docBlock->getTagsByName($tag) as $tag) { - $types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType())); + if ($tag && null !== $tag->getType()) { + $types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType())); + } } if (!isset($types[0])) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index 9cc0a8d6e1..f16e29242c 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -40,6 +40,11 @@ class PhpDocExtractorTest extends TestCase $this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property)); } + public function testParamTagTypeIsOmitted() + { + $this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType')); + } + /** * @dataProvider typesWithCustomPrefixesProvider */ @@ -176,3 +181,13 @@ class EmptyDocBlock { public $foo; } + +class OmittedParamTagTypeDocBlock +{ + /** + * @param $omittedTagType + */ + public function setOmittedType(array $omittedTagType) + { + } +} From 8f0e47f6361399305c378407480d9c5575f02ca6 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 5 Feb 2018 09:49:20 +0100 Subject: [PATCH 08/16] [WebProfilerBundle] Fix sub request link --- .../Resources/views/Collector/request.html.twig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig index 8f94f6f5f0..903d009c98 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig @@ -271,9 +271,7 @@
{% for child in profile.children %}

- - {{ helper.set_handler(child.getcollector('request').controller) }} - + {{ helper.set_handler(child.getcollector('request').controller) }} (token = {{ child.token }})

From c8465ed97f00d18a11161215dda7801dc1cc205f Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 10 Jan 2018 18:42:09 +0100 Subject: [PATCH 09/16] [TwigBundle] Register TwigBridge extensions first --- .../Compiler/TwigEnvironmentPass.php | 19 +++- .../Compiler/TwigEnvironmentPassTest.php | 89 +++++++++++++++++++ 2 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php index f520ab11f0..d5e6cb6c4a 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php @@ -34,11 +34,22 @@ class TwigEnvironmentPass implements CompilerPassInterface // For instance, global variable definitions must be registered // afterward. If not, the globals from the extensions will never // be registered. - $calls = $definition->getMethodCalls(); - $definition->setMethodCalls(array()); + $currentMethodCalls = $definition->getMethodCalls(); + $twigBridgeExtensionsMethodCalls = array(); + $othersExtensionsMethodCalls = array(); foreach ($container->findTaggedServiceIds('twig.extension', true) as $id => $attributes) { - $definition->addMethodCall('addExtension', array(new Reference($id))); + $methodCall = array('addExtension', array(new Reference($id))); + $extensionClass = $container->getDefinition($id)->getClass(); + + if (is_string($extensionClass) && 0 === strpos($extensionClass, 'Symfony\Bridge\Twig\Extension')) { + $twigBridgeExtensionsMethodCalls[] = $methodCall; + } else { + $othersExtensionsMethodCalls[] = $methodCall; + } + } + + if (!empty($twigBridgeExtensionsMethodCalls) || !empty($othersExtensionsMethodCalls)) { + $definition->setMethodCalls(array_merge($twigBridgeExtensionsMethodCalls, $othersExtensionsMethodCalls, $currentMethodCalls)); } - $definition->setMethodCalls(array_merge($definition->getMethodCalls(), $calls)); } } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php new file mode 100644 index 0000000000..b8fdf1af6a --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigEnvironmentPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +class TwigEnvironmentPassTest extends TestCase +{ + public function testTwigBridgeExtensionsAreRegisteredFirst() + { + $twigDefinition = new Definition('twig'); + + $containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class) + ->setMethods(array('hasDefinition', 'get', 'findTaggedServiceIds', 'getDefinition')) + ->getMock(); + $containerBuilderMock + ->expects($this->once()) + ->method('hasDefinition') + ->with('twig') + ->will($this->returnValue(true)); + $containerBuilderMock + ->expects($this->once()) + ->method('findTaggedServiceIds') + ->with('twig.extension') + ->will($this->returnValue(array( + 'other_extension' => array( + array() + ), + 'twig_bridge_extension' => array( + array() + ) + ))); + + $otherExtensionDefinitionMock = $this->getMockBuilder(Definition::class) + ->setMethods(array('getClass')) + ->getMock(); + $otherExtensionDefinitionMock + ->expects($this->once()) + ->method('getClass') + ->will($this->returnValue('Foo\\Bar')); + + $twigExtensionDefinitionMock = $this->getMockBuilder(Definition::class) + ->setMethods(array('getClass')) + ->getMock(); + $twigExtensionDefinitionMock + ->expects($this->once()) + ->method('getClass') + ->will($this->returnValue('Symfony\\Bridge\\Twig\\Extension\\Foo')); + + $containerBuilderMock + ->expects($this->exactly(3)) + ->method('getDefinition') + ->withConsecutive(array('twig'), array('other_extension'), array('twig_bridge_extension')) + ->willReturnOnConsecutiveCalls( + $this->returnValue($twigDefinition), + $this->returnValue($otherExtensionDefinitionMock), + $this->returnValue($twigExtensionDefinitionMock) + ); + + $twigEnvironmentPass = new TwigEnvironmentPass(); + $twigEnvironmentPass->process($containerBuilderMock); + + $methodCalls = $twigDefinition->getMethodCalls(); + $this->assertCount(2, $methodCalls); + + $twigBridgeExtensionReference = $methodCalls[0][1][0]; + $this->assertInstanceOf(Reference::class, $twigBridgeExtensionReference); + /* @var Reference $twigBridgeExtensionReference */ + $this->assertEquals('twig_bridge_extension', $twigBridgeExtensionReference->__toString()); + + $otherExtensionReference = $methodCalls[1][1][0]; + $this->assertInstanceOf(Reference::class, $otherExtensionReference); + /* @var Reference $otherExtensionReference */ + $this->assertEquals('other_extension', $otherExtensionReference->__toString()); + } +} From 39e88ed3128933d7540eadd847d5650c8b52f5ba Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Feb 2018 06:34:13 +0100 Subject: [PATCH 10/16] fixed CS --- .../Compiler/TwigEnvironmentPassTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php index b8fdf1af6a..dfc5e3059d 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php @@ -37,11 +37,11 @@ class TwigEnvironmentPassTest extends TestCase ->with('twig.extension') ->will($this->returnValue(array( 'other_extension' => array( - array() + array(), ), 'twig_bridge_extension' => array( - array() - ) + array(), + ), ))); $otherExtensionDefinitionMock = $this->getMockBuilder(Definition::class) From 8bba882512b6f57545631f5cee96b02523a70967 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 7 Feb 2018 18:55:42 +0100 Subject: [PATCH 11/16] do not mock the container builder or definitions --- .../Compiler/TwigEnvironmentPassTest.php | 64 +++---------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php index dfc5e3059d..0af3fe4b32 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigEnvironmentPassTest.php @@ -12,78 +12,34 @@ namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigEnvironmentPass; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; class TwigEnvironmentPassTest extends TestCase { public function testTwigBridgeExtensionsAreRegisteredFirst() { - $twigDefinition = new Definition('twig'); - - $containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class) - ->setMethods(array('hasDefinition', 'get', 'findTaggedServiceIds', 'getDefinition')) - ->getMock(); - $containerBuilderMock - ->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $containerBuilderMock - ->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.extension') - ->will($this->returnValue(array( - 'other_extension' => array( - array(), - ), - 'twig_bridge_extension' => array( - array(), - ), - ))); - - $otherExtensionDefinitionMock = $this->getMockBuilder(Definition::class) - ->setMethods(array('getClass')) - ->getMock(); - $otherExtensionDefinitionMock - ->expects($this->once()) - ->method('getClass') - ->will($this->returnValue('Foo\\Bar')); - - $twigExtensionDefinitionMock = $this->getMockBuilder(Definition::class) - ->setMethods(array('getClass')) - ->getMock(); - $twigExtensionDefinitionMock - ->expects($this->once()) - ->method('getClass') - ->will($this->returnValue('Symfony\\Bridge\\Twig\\Extension\\Foo')); - - $containerBuilderMock - ->expects($this->exactly(3)) - ->method('getDefinition') - ->withConsecutive(array('twig'), array('other_extension'), array('twig_bridge_extension')) - ->willReturnOnConsecutiveCalls( - $this->returnValue($twigDefinition), - $this->returnValue($otherExtensionDefinitionMock), - $this->returnValue($twigExtensionDefinitionMock) - ); + $container = new ContainerBuilder(); + $twigDefinition = $container->register('twig'); + $container->register('other_extension', 'Foo\Bar') + ->addTag('twig.extension'); + $container->register('twig_bridge_extension', FormExtension::class) + ->addTag('twig.extension'); $twigEnvironmentPass = new TwigEnvironmentPass(); - $twigEnvironmentPass->process($containerBuilderMock); + $twigEnvironmentPass->process($container); $methodCalls = $twigDefinition->getMethodCalls(); $this->assertCount(2, $methodCalls); $twigBridgeExtensionReference = $methodCalls[0][1][0]; $this->assertInstanceOf(Reference::class, $twigBridgeExtensionReference); - /* @var Reference $twigBridgeExtensionReference */ - $this->assertEquals('twig_bridge_extension', $twigBridgeExtensionReference->__toString()); + $this->assertSame('twig_bridge_extension', (string) $twigBridgeExtensionReference); $otherExtensionReference = $methodCalls[1][1][0]; $this->assertInstanceOf(Reference::class, $otherExtensionReference); - /* @var Reference $otherExtensionReference */ - $this->assertEquals('other_extension', $otherExtensionReference->__toString()); + $this->assertSame('other_extension', (string) $otherExtensionReference); } } From a9ab167abfda01b46c1d77a2d85078f860998046 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 9 Feb 2018 08:49:27 +0100 Subject: [PATCH 12/16] backport regression test from 3.4 --- .../Tests/Extractors/PhpDocExtractorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index 6477ba1967..4110c6b8a5 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -74,4 +74,21 @@ class PhpDocExtractorTest extends TestCase array('staticSetter', null, null, null), ); } + + public function testParamTagTypeIsOmitted() + { + $this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\PhpDocExtractors\OmittedParamTagTypeDocBlock', 'omittedType')); + } +} + +class OmittedParamTagTypeDocBlock +{ + /** + * The type is omitted here to ensure that the extractor doesn't choke on missing types. + * + * @param $omittedTagType + */ + public function setOmittedType(array $omittedTagType) + { + } } From 51d9008d682c09a594bda0a8e38652ec9b820ce8 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Fri, 9 Feb 2018 13:42:37 +0100 Subject: [PATCH 13/16] [Security] fix merge of 2.7 into 2.8 + add test case --- .../UsernamePasswordFormAuthenticationListener.php | 10 +++++++--- ...ernamePasswordFormAuthenticationListenerTest.php | 13 +++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index d7802c76d2..f8466278da 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -96,9 +96,13 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL } } - $requestBag = $this->options['post_only'] ? $request->request : $request; - $username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']); - $password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']); + if ($this->options['post_only']) { + $username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']); + $password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']); + } else { + $username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']); + $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); + } if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username))); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 2e99f70e7e..106740e56f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -77,10 +77,11 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase } /** + * @dataProvider postOnlyDataProvider * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * @expectedExceptionMessage The key "_username" must be a string, "array" given. */ - public function testHandleNonStringUsername() + public function testHandleNonStringUsername($postOnly) { $request = Request::create('/login_check', 'POST', array('_username' => array())); $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); @@ -93,7 +94,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase 'foo', new DefaultAuthenticationSuccessHandler($httpUtils), new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), - array('require_previous_session' => false) + array('require_previous_session' => false, 'post_only' => $postOnly) ); $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); @@ -101,6 +102,14 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase $listener->handle($event); } + public function postOnlyDataProvider() + { + return array( + array(true), + array(false), + ); + } + public function getUsernameForLength() { return array( From d195a6f0600fdfb0665f4a7844dc32646f73b1ab Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Feb 2018 13:55:03 +0100 Subject: [PATCH 14/16] [SecurityBundle] Backport test --- ...amePasswordFormAuthenticationListenerTest.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 2e99f70e7e..8634eca017 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -77,14 +77,14 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase } /** + * @dataProvider postOnlyDataProvider * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * @expectedExceptionMessage The key "_username" must be a string, "array" given. */ - public function testHandleNonStringUsername() + public function testHandleNonStringUsername($postOnly) { $request = Request::create('/login_check', 'POST', array('_username' => array())); $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); - $listener = new UsernamePasswordFormAuthenticationListener( new TokenStorage(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), @@ -93,14 +93,20 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase 'foo', new DefaultAuthenticationSuccessHandler($httpUtils), new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), - array('require_previous_session' => false) + array('require_previous_session' => false, 'post_only' => $postOnly) ); - $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); - $listener->handle($event); } + public function postOnlyDataProvider() + { + return array( + array(true), + array(false), + ); + } + public function getUsernameForLength() { return array( From bdf9efc78e7a34543be98b6e3e066c9590bb3fbd Mon Sep 17 00:00:00 2001 From: dsmink Date: Fri, 9 Feb 2018 13:27:46 +0100 Subject: [PATCH 15/16] Env var maps to undefined constant. When I try to use a constant as an environment variable, as described in the blog item, I run into the following problem. Env var "SOME_CONST" maps to undefined constant "App\\Util\\SomeClass::SOME_CONST". The proposed solution works for me, however, I'm not sure if this is the best and conform Symfony standards. Blog: https://symfony.com/blog/new-in-symfony-3-4-advanced-environment-variables --- src/Symfony/Component/DependencyInjection/EnvVarProcessor.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index bf34c593d6..508ebac966 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -110,11 +110,13 @@ class EnvVarProcessor implements EnvVarProcessorInterface } if ('const' === $prefix) { + $env = \str_replace("\\\\","\\", $env); + if (!defined($env)) { throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env)); } - return constant($name); + return constant($env); } if ('base64' === $prefix) { From 99c5b77319dcbfa9ea1378a27c315feba7eeabd6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 9 Feb 2018 16:04:34 +0100 Subject: [PATCH 16/16] fix merge --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3eea9310f5..7ed8c84c6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -133,9 +133,6 @@ before_install: - | # Install extra PHP extensions if [[ ! $skip ]]; then - ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") - tfold ext.apcu tpecl apcu-4.0.11 apcu.so - elif [[ ! $skip && $PHP = 7.* ]]; then # install libsodium if [[ ! -e ~/php-ext/$(php -r "echo basename(ini_get('extension_dir'));")/libsodium/sodium.so ]]; then sudo add-apt-repository ppa:ondrej/php -y