Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Validator] UID Constraint. #36407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 1 src/Symfony/Component/Validator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ CHANGELOG
* allow to define a reusable set of constraints by extending the `Compound` constraint
* added `Sequentially` constraint, to sequentially validate a set of constraints (any violation raised will prevent further validation of the nested constraints)
* added the `divisibleBy` option to the `Count` constraint
* added `Uid` constraint and `UidValidator`

5.0.0
-----
Expand Down
95 changes: 95 additions & 0 deletions 95 src/Symfony/Component/Validator/Constraints/Uid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?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\Uid\AbstractUid;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\InvalidArgumentException;
use Symfony\Component\Validator\Exception\LogicException;

/**
* @Annotation
*/
class Uid extends Constraint
{
const INVALID_UID_ERROR = '34fd666d-3eb6-4f82-9965-fa7decd445d0';

protected static $errorNames = [
self::INVALID_UID_ERROR => 'INVALID_UID_ERROR',
];

public const UUID_V1 = 'UUID_V1';
public const UUID_V3 = 'UUID_V3';
public const UUID_V4 = 'UUID_V4';
public const UUID_V5 = 'UUID_V5';
public const UUID_V6 = 'UUID_V6';
public const ULID = 'ULID';

/**
* @var string[]
*
* @internal
*/
public static $availableTypes = [
self::UUID_V1,
self::UUID_V3,
self::UUID_V4,
self::UUID_V5,
self::UUID_V6,
self::ULID,
];

public $message = 'This value is not valid.';

/**
* @var int[]
*/
public $types = [
self::UUID_V1,
self::UUID_V3,
self::UUID_V4,
self::UUID_V5,
self::UUID_V6,
self::ULID,
];

public $normalizer;

public function __construct($options = null)
{
if (!class_exists(AbstractUid::class)) {
throw new LogicException('Unable to use the UID Constraint, as Symfony Uid component is not installed.');
}

if (\is_array($options) && \array_key_exists('types', $options)) {
if (!\is_array($options['types'])) {
throw new InvalidArgumentException('The "types" parameter should be an array.');
}
array_map(function ($value) {
if (!\in_array($value, self::$availableTypes, true)) {
throw new InvalidArgumentException('The "types" parameter is not valid.');
}
}, $options['types']);
}

parent::__construct($options);

if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', get_debug_type($this->normalizer)));
}
}

public function getDefaultOption()
{
return 'types';
}
}
72 changes: 72 additions & 0 deletions 72 src/Symfony/Component/Validator/Constraints/UidValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?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\Uid\Ulid;
use Symfony\Component\Uid\UuidV1;
use Symfony\Component\Uid\UuidV3;
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Uid\UuidV5;
use Symfony\Component\Uid\UuidV6;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;

class UidValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Uid) {
throw new UnexpectedTypeException($constraint, Uid::class);
}

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

if (!\is_string($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
throw new UnexpectedValueException($value, 'string');
}

$value = (string) $value;

foreach ($constraint->types as $type) {
if (Uid::UUID_V1 === $type && UuidV1::isValid($value)) {
return;
}
if (Uid::UUID_V3 === $type && UuidV3::isValid($value)) {
return;
}
if (Uid::UUID_V4 === $type && UuidV4::isValid($value)) {
return;
}
if (Uid::UUID_V5 === $type && UuidV5::isValid($value)) {
return;
}
if (Uid::UUID_V6 === $type && UuidV6::isValid($value)) {
return;
}
if (Uid::ULID === $type && Ulid::isValid($value)) {
return;
}
}

$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setCode(Uid::INVALID_UID_ERROR)
->addViolation();
}
}
44 changes: 44 additions & 0 deletions 44 src/Symfony/Component/Validator/Tests/Constraints/UidTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Symfony\Component\Validator\Tests\Constraints;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Constraints\Uid;

class UidTest extends TestCase
{
public function testNotArrayTypesTriggersException()
{
$this->expectException('Symfony\Component\Validator\Exception\InvalidArgumentException');
$this->expectExceptionMessage('The "types" parameter should be an array.');
$uid = new Uid(['types' => 'foo']);
}

public function testInvalidTypeTriggerException()
{
$this->expectException('Symfony\Component\Validator\Exception\InvalidArgumentException');
$this->expectExceptionMessage('The "types" parameter is not valid.');
$uid = new Uid(['types' => ['foo']]);
}

public function testNormalizerCanBeSet()
{
$email = new Uid(['normalizer' => 'trim']);

$this->assertEquals('trim', $email->normalizer);
}

public function testInvalidNormalizerThrowsException()
{
$this->expectException('Symfony\Component\Validator\Exception\InvalidArgumentException');
$this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).');
new Uid(['normalizer' => 'Unknown Callable']);
}

public function testInvalidNormalizerObjectThrowsException()
{
$this->expectException('Symfony\Component\Validator\Exception\InvalidArgumentException');
$this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).');
new Uid(['normalizer' => new \stdClass()]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Uid;
use Symfony\Component\Validator\Constraints\UidValidator;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;

class UidValidatorTest extends ConstraintValidatorTestCase
{
protected function createValidator()
{
return new UidValidator();
}

public function testNullIsValid()
{
$this->validator->validate(null, new Uid());

$this->assertNoViolation();
}

public function testEmptyStringIsValid()
{
$this->validator->validate('', new Uid());

$this->assertNoViolation();
}

public function testValidUids()
{
$this->validator->validate('9b7541de-6f87-11ea-ab3c-9da9a81562fc', new Uid());
$this->validator->validate('e576629b-ff34-3642-9c08-1f5219f0d45b', new Uid());
$this->validator->validate('4126dbc1-488e-4f6e-aadd-775dcbac482e', new Uid());
$this->validator->validate('18cdf3d3-ea1b-5b23-a9c5-40abd0e2df22', new Uid());
$this->validator->validate('1ea6ecef-eb9a-66fe-b62b-957b45f17e43', new Uid());
$this->validator->validate('01E4BYF64YZ97MDV6RH0HAMN6X', new Uid());

$this->assertNoViolation();
}

public function testInvalidUid()
{
$value = 'foo';

$constraint = new Uid([
'message' => 'myMessage',
]);

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

$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$value.'"')
->setCode(Uid::INVALID_UID_ERROR)
->assertRaised();
}

public function testInvalidUidForTypes()
{
$value = '9b7541de-6f87-11ea-ab3c-9da9a81562fc';

$constraint = new Uid([
'message' => 'myMessage',
'types' => [Uid::UUID_V3],
]);

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

$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$value.'"')
->setCode(Uid::INVALID_UID_ERROR)
->assertRaised();
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.