Skip to content

Commit

Permalink
[Validator] Add IsFinite constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-a committed Jul 13, 2023
1 parent 80f1096 commit e1434ba
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Component/Validator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CHANGELOG

* Allow single integer for the `versions` option of the `Uuid` constraint
* Allow single constraint to be passed to the `constraints` option of the `When` constraint
* Add `Finite` constraint

6.3
---
Expand Down
40 changes: 40 additions & 0 deletions src/Symfony/Component/Validator/Constraints/IsFinite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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\Validator\Constraint;

/**
* @Annotation
*
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Guillaume Aveline <guillaume@codr.fr>
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class IsFinite extends Constraint
{
public const NOT_FINITE_ERROR = '5f809eb0-78b9-492d-ad37-5a5188390415';

protected const ERROR_NAMES = [
self::NOT_FINITE_ERROR => 'NOT_FINITE_ERROR',
];

public $message = 'This value should be finite.';

public function __construct(array $options = [], array $groups = null, mixed $payload = null, string $message = null)
{
parent::__construct($options, $groups, $payload);

$this->message = $message ?? $this->message;
}
}
42 changes: 42 additions & 0 deletions src/Symfony/Component/Validator/Constraints/IsFiniteValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?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\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
* @author Guillaume Aveline <guillaume@codr.fr>
*/
class IsFiniteValidator extends ConstraintValidator
{
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof IsFinite) {
throw new UnexpectedTypeException($constraint, IsFinite::class);
}

if (null === $value) {
return;
}

if (is_numeric($value) && is_finite($value)) {
return;
}

$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(IsFinite::NOT_FINITE_ERROR)
->addViolation();
}
}
47 changes: 47 additions & 0 deletions src/Symfony/Component/Validator/Tests/Constraints/IsFiniteTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?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\Tests\Constraints;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Constraints\IsFinite;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;

class IsFiniteTest extends TestCase
{
public function testAttributes()
{
$metadata = new ClassMetadata(FiniteDummy::class);
$loader = new AnnotationLoader();
self::assertTrue($loader->loadClassMetadata($metadata));

[$bConstraint] = $metadata->properties['b']->getConstraints();
self::assertSame('myMessage', $bConstraint->message);
self::assertSame(['Default', 'FiniteDummy'], $bConstraint->groups);

[$cConstraint] = $metadata->properties['c']->getConstraints();
self::assertSame(['my_group'], $cConstraint->groups);
self::assertSame('some attached data', $cConstraint->payload);
}
}

class FiniteDummy
{
#[IsFinite]
private $a;

#[IsFinite(message: 'myMessage')]
private $b;

#[IsFinite(groups: ['my_group'], payload: 'some attached data')]
private $c;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?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\Tests\Constraints;

use Symfony\Component\Validator\Constraints\IsFinite;
use Symfony\Component\Validator\Constraints\IsFiniteValidator;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;

class IsFiniteValidatorTest extends ConstraintValidatorTestCase
{
protected function createValidator(): IsFiniteValidator
{
return new IsFiniteValidator();
}

public function testNullIsValid()
{
$constraint = new IsFinite();

$this->validator->validate(null, $constraint);

$this->assertNoViolation();
}

/**
* @dataProvider getValidValues
*/
public function testValidValues(mixed $value)
{
$constraint = new IsFinite();

$this->validator->validate($value, $constraint);

$this->assertNoViolation();
}

public static function getValidValues(): array
{
return [
[0],
['0'],
[1.5],
['1.5'],
['12345'],
];
}

/**
* @dataProvider getInvalidValues
*/
public function testInvalidValues(mixed $value, string $valueAsString)
{
$constraint = new IsFinite([
'message' => 'myMessage',
]);

$this->validator->validate($value, $constraint);

$this->buildViolation('myMessage')
->setParameter('{{ value }}', $valueAsString)
->setCode(IsFinite::NOT_FINITE_ERROR)
->assertRaised();
}

public static function getInvalidValues(): array
{
$object = new \stdClass();
$object->foo = 'bar';

return [
[\NAN, 'NAN'],
[\INF, 'INF'],
['', '""'],
['foo', '"foo"'],
[['foo' => 'bar'], 'array'],
[$object, 'object'],
];
}
}

0 comments on commit e1434ba

Please sign in to comment.