Skip to content

Commit

Permalink
bug #51761 [Validator] Fix registering "is_valid()" for `#[Expression…
Browse files Browse the repository at this point in the history
…]` (nicolas-grekas)

This PR was merged into the 6.4 branch.

Discussion
----------

[Validator] Fix registering "is_valid()" for `#[Expression]`

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | #50438
| License       | MIT
| Doc PR        | -

`@bendavies` can you please confirm this fixes the issue for you?

Commits
-------

b24d9a0 [Validator] Fix registering "is_valid()" for `#[Expression]`
  • Loading branch information
nicolas-grekas committed Sep 27, 2023
2 parents 88a1c21 + b24d9a0 commit 751dedd
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
use Symfony\Component\Translation\Translator;
use Symfony\Component\Uid\Factory\UuidFactory;
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use Symfony\Component\Validator\ObjectInitializerInterface;
Expand Down Expand Up @@ -1664,6 +1665,10 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
if (!class_exists(ExpressionLanguage::class)) {
$container->removeDefinition('validator.expression_language');
}

if (!class_exists(ExpressionLanguageProvider::class)) {
$container->removeDefinition('validator.expression_language_provider');
}
}

private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Validator\Constraints\EmailValidator;
use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
use Symfony\Component\Validator\Constraints\ExpressionValidator;
use Symfony\Component\Validator\Constraints\NoSuspiciousCharactersValidator;
use Symfony\Component\Validator\Constraints\NotCompromisedPasswordValidator;
Expand Down Expand Up @@ -82,11 +83,16 @@

->set('validator.expression_language', ExpressionLanguage::class)
->args([service('cache.validator_expression_language')->nullOnInvalid()])
->call('registerProvider', [
service('validator.expression_language_provider')->ignoreOnInvalid(),
])

->set('cache.validator_expression_language')
->parent('cache.system')
->tag('cache.pool')

->set('validator.expression_language_provider', ExpressionLanguageProvider::class)

->set('validator.email', EmailValidator::class)
->args([
abstract_arg('Default mode'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions(): array
{
return [
new ExpressionFunction('is_valid', function (...$arguments) {
return sprintf(
'0 === $context->getValidator()->inContext($context)->validate(%s)->getViolations()->count()',
implode(', ', $arguments)
);
}, function (array $variables, ...$arguments): bool {
return 0 === $variables['context']->getValidator()->inContext($variables['context'])->validate(...$arguments)->getViolations()->count();
}),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
Expand All @@ -22,15 +20,14 @@
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@symfony.com>
*/
class ExpressionValidator extends ConstraintValidator implements ExpressionFunctionProviderInterface
class ExpressionValidator extends ConstraintValidator
{
private ExpressionLanguage $expressionLanguage;

public function __construct(ExpressionLanguage $expressionLanguage = null)
{
if ($expressionLanguage) {
$this->expressionLanguage = clone $expressionLanguage;
$this->expressionLanguage->registerProvider($this);
$this->expressionLanguage = $expressionLanguage;
}
}

Expand All @@ -56,25 +53,11 @@ public function validate(mixed $value, Constraint $constraint)
}
}

public function getFunctions(): array
{
return [
new ExpressionFunction('is_valid', function (...$arguments) {
return sprintf(
'0 === $context->getValidator()->inContext($context)->validate(%s)->getViolations()->count()',
implode(', ', $arguments)
);
}, function (array $variables, ...$arguments): bool {
return 0 === $variables['context']->getValidator()->inContext($variables['context'])->validate(...$arguments)->getViolations()->count();
}),
];
}

private function getExpressionLanguage(): ExpressionLanguage
{
if (!isset($this->expressionLanguage)) {
$this->expressionLanguage = new ExpressionLanguage();
$this->expressionLanguage->registerProvider($this);
$this->expressionLanguage->registerProvider(new ExpressionLanguageProvider());
}

return $this->expressionLanguage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Validator\Constraints\Expression;
use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
use Symfony\Component\Validator\Constraints\ExpressionValidator;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
Expand Down Expand Up @@ -359,10 +360,8 @@ public function testIsValidExpressionInvalid()
*/
public function testCompileIsValid(string $expression, array $names, string $expected)
{
$provider = new ExpressionValidator();

$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->registerProvider($provider);
$expressionLanguage->registerProvider(new ExpressionLanguageProvider());

$result = $expressionLanguage->compile($expression, $names);

Expand Down

0 comments on commit 751dedd

Please sign in to comment.