diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 7f600ec3af..6c557a777e 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -430,8 +430,6 @@ class Command * This feature should be used only when creating a long process command, * like a daemon. * - * PHP 5.5+ or the proctitle PECL library is required - * * @return $this */ public function setProcessTitle(string $title) diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php index 930470ecfd..55164d6509 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php @@ -429,18 +429,6 @@ class ErrorHandler } $scope = $this->scopedErrors & $type; - if (4 < $numArgs = \func_num_args()) { - $context = $scope ? (func_get_arg(4) ?: []) : []; - } else { - $context = []; - } - - if (isset($context['GLOBALS']) && $scope) { - $e = $context; // Whatever the signature of the method, - unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 - $context = $e; - } - if (false !== strpos($message, "@anonymous\0")) { $logMessage = $this->parseAnonymousClass($message); } else { @@ -502,6 +490,8 @@ class ErrorHandler // `return trigger_error($e, E_USER_ERROR);` allows this error handler // to make $e get through the __toString() barrier. + $context = 4 < \func_num_args() ? (func_get_arg(4) ?: []) : []; + foreach ($context as $e) { if ($e instanceof \Throwable && $e->__toString() === $message) { self::$toStringException = $e; diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 81a71d1e66..c92abf1383 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -397,7 +397,7 @@ EOF protected function computeFallbackLocales(string $locale) { if (null === $this->parentLocales) { - $parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true); + $this->parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true); } $locales = []; @@ -410,7 +410,7 @@ EOF } while ($locale) { - $parent = $parentLocales[$locale] ?? null; + $parent = $this->parentLocales[$locale] ?? null; if ($parent) { $locale = 'root' !== $parent ? $parent : null; diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php index 4674f8b35a..eb09e5a4b2 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php @@ -18,6 +18,7 @@ class EntityParent implements EntityInterfaceA protected $firstName; private $internal; private $data = 'Data'; + private $child; /** * @NotNull @@ -28,4 +29,9 @@ class EntityParent implements EntityInterfaceA { return 'Data'; } + + public function getChild() + { + return $this->child; + } } diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index ef69a5bc00..1ebe1534ab 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -21,6 +21,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Required; +use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\Context\ExecutionContextFactory; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -28,6 +29,7 @@ use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB; use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods; use Symfony\Component\Validator\Validator\RecursiveValidator; use Symfony\Component\Validator\Validator\ValidatorInterface; @@ -144,6 +146,31 @@ class RecursiveValidatorTest extends AbstractTest $this->assertInstanceOf(IsTrue::class, $violations->get(1)->getConstraint()); } + public function testValidConstraintOnGetterReturningNull() + { + $metadata = new ClassMetadata(EntityParent::class); + $metadata->addGetterConstraint('child', new Valid()); + + $this->metadataFactory->addMetadata($metadata); + + $violations = $this->validator->validate(new EntityParent()); + + $this->assertCount(0, $violations); + } + + public function testNotNullConstraintOnGetterReturningNull() + { + $metadata = new ClassMetadata(EntityParent::class); + $metadata->addGetterConstraint('child', new NotNull()); + + $this->metadataFactory->addMetadata($metadata); + + $violations = $this->validator->validate(new EntityParent()); + + $this->assertCount(1, $violations); + $this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint()); + } + public function testAllConstraintValidateAllGroupsForNestedConstraints() { $this->metadata->addPropertyConstraint('data', new All(['constraints' => [ diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index 75d8e50175..eaa1309fd0 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -630,6 +630,10 @@ class RecursiveContextualValidator implements ContextualValidatorInterface if ($value instanceof LazyProperty) { $value = $value->getPropertyValue(); + + if (null === $value) { + return; + } } if (\is_array($value)) {