diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md index 20f38b3422..2f51e38874 100644 --- a/CHANGELOG-4.4.md +++ b/CHANGELOG-4.4.md @@ -7,6 +7,28 @@ in 4.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.4.0...v4.4.1 +* 4.4.10 (2020-06-12) + + * bug #37227 [DependencyInjection][CheckTypeDeclarationsPass] Handle unresolved parameters pointing to environment variables (fancyweb) + * bug #37103 [Form] switch the context when validating nested forms (xabbuh) + * bug #37182 [HttpKernel] Fix regression where Store does not return response body correctly (mpdude) + * bug #37193 [DependencyInjection][CheckTypeDeclarationsPass] Always resolve parameters (fancyweb) + * bug #37191 [HttpClient] fix offset computation for data chunks (nicolas-grekas) + * bug #37177 [Ldap] fix refreshUser() ignoring extra_fields (arkste) + * bug #37181 [Mailer] Remove an internal annot (fabpot) + * bug #36913 [FrameworkBundle] fix type annotation on ControllerTrait::addFlash() (ThomasLandauer) + * bug #37162 [Mailer] added the reply-to addresses to the API SES transport request. (ribeiropaulor) + * bug #37167 [Mime] use fromString when creating a new Address (fabpot) + * bug #37169 [Cache] fix forward compatibility with Doctrine DBAL 3 (xabbuh) + * bug #37159 [Mailer] Fixed generator bug when creating multiple transports using Transport::fromDsn (atailouloute) + * bug #37048 [HttpClient] fix monitoring timeouts when other streams are active (nicolas-grekas) + * bug #37085 [Form] properly cascade validation to child forms (xabbuh) + * bug #37095 [PhpUnitBridge] Fix undefined index when output of "composer show" cannot be parsed (nicolas-grekas) + * bug #37092 [PhpUnitBridge] fix undefined var on version 3.4 (nicolas-grekas) + * bug #37065 [HttpClient] Throw JsonException instead of TransportException on empty response in Response::toArray() (jeroennoten) + * bug #37077 [WebProfilerBundle] Move ajax clear event listener initialization on loadToolbar (Bruno BOUTAREL) + * bug #37049 [Serializer] take into account the context when preserving empty array objects (xabbuh) + * 4.4.9 (2020-05-31) * bug #37008 [Security] Fixed AbstractToken::hasUserChanged() (wouterj) diff --git a/CHANGELOG-5.0.md b/CHANGELOG-5.0.md index cbd366b3c7..1836adff61 100644 --- a/CHANGELOG-5.0.md +++ b/CHANGELOG-5.0.md @@ -7,6 +7,28 @@ in 5.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.0.0...v5.0.1 +* 5.0.10 (2020-06-12) + + * bug #37227 [DependencyInjection][CheckTypeDeclarationsPass] Handle unresolved parameters pointing to environment variables (fancyweb) + * bug #37103 [Form] switch the context when validating nested forms (xabbuh) + * bug #37182 [HttpKernel] Fix regression where Store does not return response body correctly (mpdude) + * bug #37193 [DependencyInjection][CheckTypeDeclarationsPass] Always resolve parameters (fancyweb) + * bug #37191 [HttpClient] fix offset computation for data chunks (nicolas-grekas) + * bug #37177 [Ldap] fix refreshUser() ignoring extra_fields (arkste) + * bug #37181 [Mailer] Remove an internal annot (fabpot) + * bug #36913 [FrameworkBundle] fix type annotation on ControllerTrait::addFlash() (ThomasLandauer) + * bug #37162 [Mailer] added the reply-to addresses to the API SES transport request. (ribeiropaulor) + * bug #37167 [Mime] use fromString when creating a new Address (fabpot) + * bug #37169 [Cache] fix forward compatibility with Doctrine DBAL 3 (xabbuh) + * bug #37159 [Mailer] Fixed generator bug when creating multiple transports using Transport::fromDsn (atailouloute) + * bug #37048 [HttpClient] fix monitoring timeouts when other streams are active (nicolas-grekas) + * bug #37085 [Form] properly cascade validation to child forms (xabbuh) + * bug #37095 [PhpUnitBridge] Fix undefined index when output of "composer show" cannot be parsed (nicolas-grekas) + * bug #37092 [PhpUnitBridge] fix undefined var on version 3.4 (nicolas-grekas) + * bug #37065 [HttpClient] Throw JsonException instead of TransportException on empty response in Response::toArray() (jeroennoten) + * bug #37077 [WebProfilerBundle] Move ajax clear event listener initialization on loadToolbar (Bruno BOUTAREL) + * bug #37049 [Serializer] take into account the context when preserving empty array objects (xabbuh) + * 5.0.9 (2020-05-31) * bug #37008 [Security] Fixed AbstractToken::hasUserChanged() (wouterj) diff --git a/composer.json b/composer.json index d6f5c79afa..d8acf3888c 100644 --- a/composer.json +++ b/composer.json @@ -128,7 +128,7 @@ "egulias/email-validator": "~1.2,>=1.2.8|~2.0", "symfony/phpunit-bridge": "^5.0.8", "symfony/security-acl": "~2.8|~3.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "twig/cssinliner-extra": "^2.12", "twig/inky-extra": "^2.12", "twig/markdown-extra": "^2.12" diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 7dad156206..2e5e29eb8d 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -508,14 +508,16 @@ class QuestionHelper extends Helper private function isTty(): bool { - $inputStream = !$this->inputStream && \defined('STDIN') ? STDIN : $this->inputStream; + if (!\defined('STDIN')) { + return true; + } if (\function_exists('stream_isatty')) { - return stream_isatty($inputStream); + return stream_isatty(fopen('php://input', 'r')); } if (\function_exists('posix_isatty')) { - return posix_isatty($inputStream); + return posix_isatty(fopen('php://input', 'r')); } return true; diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 9afad24357..677d027766 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Tests\Helper; +use Symfony\Component\Console\Application; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\FormatterHelper; @@ -21,6 +22,7 @@ use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Terminal; +use Symfony\Component\Console\Tester\ApplicationTester; /** * @group tty @@ -727,21 +729,36 @@ class QuestionHelperTest extends AbstractQuestionHelperTest $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question); } - public function testAskThrowsExceptionFromValidatorEarlyWhenTtyIsMissing() + public function testQuestionValidatorRepeatsThePrompt() { - $this->expectException('Exception'); - $this->expectExceptionMessage('Bar, not Foo'); + $tries = 0; + $application = new Application(); + $application->setAutoExit(false); + $application->register('question') + ->setCode(function ($input, $output) use (&$tries) { + $question = new Question('This is a promptable question'); + $question->setValidator(function ($value) use (&$tries) { + ++$tries; + if (!$value) { + throw new \Exception(); + } - $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); - $output->expects($this->once())->method('writeln'); + return $value; + }); - (new QuestionHelper())->ask( - $this->createStreamableInputInterfaceMock($this->getInputStream('Foo'), true), - $output, - (new Question('Q?'))->setHidden(true)->setValidator(function ($input) { - throw new \Exception("Bar, not $input"); + (new QuestionHelper())->ask($input, $output, $question); + + return 0; }) - ); + ; + + $tester = new ApplicationTester($application); + $tester->setInputs(['', 'not-empty']); + + $statusCode = $tester->run(['command' => 'question'], ['interactive' => true]); + + $this->assertSame(2, $tries); + $this->assertSame($statusCode, 0); } public function testEmptyChoices() diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 97a106a616..9a64428c98 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -12,6 +12,7 @@ namespace Symfony\Component\PropertyInfo\Extractor; use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Types\Context; @@ -88,10 +89,12 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property } foreach ($docBlock->getTagsByName('var') as $var) { - $varDescription = $var->getDescription()->render(); + if ($var && !$var instanceof InvalidTag) { + $varDescription = $var->getDescription()->render(); - if (!empty($varDescription)) { - return $varDescription; + if (!empty($varDescription)) { + return $varDescription; + } } } @@ -142,7 +145,7 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property $types = []; /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ foreach ($docBlock->getTagsByName($tag) as $tag) { - if ($tag && null !== $tag->getType()) { + if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) { $types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType())); } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index 0d3c322067..d352fa12b6 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\PropertyInfo\Tests\Extractor; +use phpDocumentor\Reflection\DocBlock\StandardTagFactory; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; use phpDocumentor\Reflection\Types\Collection; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; @@ -46,6 +48,26 @@ class PhpDocExtractorTest extends TestCase $this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType')); } + public function invalidTypesProvider() + { + return [ + 'pub' => ['pub', null, null], + 'stat' => ['stat', null, null], + 'foo' => ['foo', $this->isPhpDocumentorV5() ? 'Foo.' : null, null], + 'bar' => ['bar', $this->isPhpDocumentorV5() ? 'Bar.' : null, null], + ]; + } + + /** + * @dataProvider invalidTypesProvider + */ + public function testInvalid($property, $shortDescription, $longDescription) + { + $this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property)); + $this->assertSame($shortDescription, $this->extractor->getShortDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property)); + $this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property)); + } + /** * @dataProvider typesWithNoPrefixesProvider */ @@ -94,7 +116,7 @@ class PhpDocExtractorTest extends TestCase ['donotexist', null, null, null], ['staticGetter', null, null, null], ['staticSetter', null, null, null], - ['emptyVar', null, null, null], + ['emptyVar', null, $this->isPhpDocumentorV5() ? 'This should not be removed.' : null, null], ]; } @@ -250,6 +272,16 @@ class PhpDocExtractorTest extends TestCase { $this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DockBlockFallback', $property)); } + + protected function isPhpDocumentorV5() + { + if (class_exists(InvalidTag::class)) { + return true; + } + + return (new \ReflectionMethod(StandardTagFactory::class, 'create')) + ->hasReturnType(); + } } class EmptyDocBlock diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/InvalidDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/InvalidDummy.php new file mode 100644 index 0000000000..0a4cc81f36 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/InvalidDummy.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +/** + * @author Martin Rademacher + */ +class InvalidDummy +{ + /** + * @var + */ + public $pub; + + /** + * @return + */ + public static function getStat() + { + return 'stat'; + } + + /** + * Foo. + * + * @param + */ + public function setFoo($foo) + { + } + + /** + * Bar. + * + * @return + */ + public function getBar() + { + return 'bar'; + } +} diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 1c8eef462e..4c07da473d 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -31,7 +31,7 @@ "symfony/serializer": "^4.4|^5.0", "symfony/cache": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "doctrine/annotations": "~1.7" }, "conflict": {