Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 708d759

Browse files
renan-tarantonicolas-grekas
authored andcommitted
[Validator] String normalization options for string-based validators
1 parent 29f81b0 commit 708d759

29 files changed

+544
-3
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ CHANGELOG
88
* added UATP cards support to `CardSchemeValidator`
99
* added option `allowNull` to NotBlank constraint
1010
* added `Json` constraint
11-
11+
* added a new `normalizer` option to the string constraints and to the `NotBlank` constraint
12+
1213
4.2.0
1314
-----
1415

src/Symfony/Component/Validator/Constraints/Email.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Egulias\EmailValidator\EmailValidator as StrictEmailValidator;
1515
use Symfony\Component\Validator\Constraint;
16+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1617
use Symfony\Component\Validator\Exception\LogicException;
1718

1819
/**
@@ -73,6 +74,7 @@ class Email extends Constraint
7374
*/
7475
public $strict;
7576
public $mode;
77+
public $normalizer;
7678

7779
public function __construct($options = null)
7880
{
@@ -89,7 +91,7 @@ public function __construct($options = null)
8991
}
9092

9193
if (\is_array($options) && \array_key_exists('mode', $options) && !\in_array($options['mode'], self::$validationModes, true)) {
92-
throw new \InvalidArgumentException('The "mode" parameter value is not valid.');
94+
throw new InvalidArgumentException('The "mode" parameter value is not valid.');
9395
}
9496

9597
parent::__construct($options);
@@ -98,5 +100,9 @@ public function __construct($options = null)
98100
// throw new LogicException(sprintf('The "egulias/email-validator" component is required to use the "%s" constraint in strict mode.', __CLASS__));
99101
@trigger_error(sprintf('Using the "%s" constraint in strict mode without the "egulias/email-validator" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED);
100102
}
103+
104+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
105+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
106+
}
101107
}
102108
}

src/Symfony/Component/Validator/Constraints/EmailValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ public function validate($value, Constraint $constraint)
8181

8282
$value = (string) $value;
8383

84+
if (null !== $constraint->normalizer) {
85+
$value = ($constraint->normalizer)($value);
86+
}
87+
8488
if (null !== $constraint->strict) {
8589
@trigger_error(sprintf('The %s::$strict property is deprecated since Symfony 4.1. Use %s::mode="%s" instead.', Email::class, Email::class, Email::VALIDATION_MODE_STRICT), E_USER_DEPRECATED);
8690

src/Symfony/Component/Validator/Constraints/Ip.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Validator\Constraint;
1515
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
16+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1617

1718
/**
1819
* Validates that a value is a valid IP address.
@@ -72,6 +73,8 @@ class Ip extends Constraint
7273

7374
public $message = 'This is not a valid IP address.';
7475

76+
public $normalizer;
77+
7578
/**
7679
* {@inheritdoc}
7780
*/
@@ -82,5 +85,9 @@ public function __construct($options = null)
8285
if (!\in_array($this->version, self::$versions)) {
8386
throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
8487
}
88+
89+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
90+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
91+
}
8592
}
8693
}

src/Symfony/Component/Validator/Constraints/IpValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public function validate($value, Constraint $constraint)
4343

4444
$value = (string) $value;
4545

46+
if (null !== $constraint->normalizer) {
47+
$value = ($constraint->normalizer)($value);
48+
}
49+
4650
switch ($constraint->version) {
4751
case Ip::V4:
4852
$flag = FILTER_FLAG_IPV4;

src/Symfony/Component/Validator/Constraints/Length.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516
use Symfony\Component\Validator\Exception\MissingOptionsException;
1617

1718
/**
@@ -39,6 +40,7 @@ class Length extends Constraint
3940
public $max;
4041
public $min;
4142
public $charset = 'UTF-8';
43+
public $normalizer;
4244

4345
public function __construct($options = null)
4446
{
@@ -54,5 +56,9 @@ public function __construct($options = null)
5456
if (null === $this->min && null === $this->max) {
5557
throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), ['min', 'max']);
5658
}
59+
60+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
61+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
62+
}
5763
}
5864
}

src/Symfony/Component/Validator/Constraints/LengthValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public function validate($value, Constraint $constraint)
4040

4141
$stringValue = (string) $value;
4242

43+
if (null !== $constraint->normalizer) {
44+
$stringValue = ($constraint->normalizer)($stringValue);
45+
}
46+
4347
if (!$invalidCharset = !@mb_check_encoding($stringValue, $constraint->charset)) {
4448
$length = mb_strlen($stringValue, $constraint->charset);
4549
}

src/Symfony/Component/Validator/Constraints/NotBlank.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516

1617
/**
1718
* @Annotation
@@ -30,4 +31,14 @@ class NotBlank extends Constraint
3031

3132
public $message = 'This value should not be blank.';
3233
public $allowNull = false;
34+
public $normalizer;
35+
36+
public function __construct($options = null)
37+
{
38+
parent::__construct($options);
39+
40+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
41+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
42+
}
43+
}
3344
}

src/Symfony/Component/Validator/Constraints/NotBlankValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ public function validate($value, Constraint $constraint)
3434
return;
3535
}
3636

37+
if (\is_string($value) && null !== $constraint->normalizer) {
38+
$value = ($constraint->normalizer)($value);
39+
}
40+
3741
if (false === $value || (empty($value) && '0' != $value)) {
3842
$this->context->buildViolation($constraint->message)
3943
->setParameter('{{ value }}', $this->formatValue($value))

src/Symfony/Component/Validator/Constraints/Regex.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516

1617
/**
1718
* @Annotation
@@ -31,6 +32,16 @@ class Regex extends Constraint
3132
public $pattern;
3233
public $htmlPattern;
3334
public $match = true;
35+
public $normalizer;
36+
37+
public function __construct($options = null)
38+
{
39+
parent::__construct($options);
40+
41+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
42+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
43+
}
44+
}
3445

3546
/**
3647
* {@inheritdoc}

src/Symfony/Component/Validator/Constraints/RegexValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public function validate($value, Constraint $constraint)
4343

4444
$value = (string) $value;
4545

46+
if (null !== $constraint->normalizer) {
47+
$value = ($constraint->normalizer)($value);
48+
}
49+
4650
if ($constraint->match xor preg_match($constraint->pattern, $value)) {
4751
$this->context->buildViolation($constraint->message)
4852
->setParameter('{{ value }}', $this->formatValue($value))

src/Symfony/Component/Validator/Constraints/Url.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516

1617
/**
1718
* @Annotation
@@ -105,6 +106,7 @@ class Url extends Constraint
105106
*/
106107
public $checkDNS = self::CHECK_DNS_TYPE_NONE;
107108
public $relativeProtocol = false;
109+
public $normalizer;
108110

109111
public function __construct($options = null)
110112
{
@@ -118,5 +120,9 @@ public function __construct($options = null)
118120
}
119121

120122
parent::__construct($options);
123+
124+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
125+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
126+
}
121127
}
122128
}

src/Symfony/Component/Validator/Constraints/UrlValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public function validate($value, Constraint $constraint)
6262
return;
6363
}
6464

65+
if (null !== $constraint->normalizer) {
66+
$value = ($constraint->normalizer)($value);
67+
}
68+
6569
$pattern = $constraint->relativeProtocol ? str_replace('(%s):', '(?:(%s):)?', static::PATTERN) : static::PATTERN;
6670
$pattern = sprintf($pattern, implode('|', $constraint->protocols));
6771

src/Symfony/Component/Validator/Constraints/Uuid.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\InvalidArgumentException;
1516

1617
/**
1718
* @Annotation
@@ -74,4 +75,15 @@ class Uuid extends Constraint
7475
self::V4_RANDOM,
7576
self::V5_SHA1,
7677
];
78+
79+
public $normalizer;
80+
81+
public function __construct($options = null)
82+
{
83+
parent::__construct($options);
84+
85+
if (null !== $this->normalizer && !\is_callable($this->normalizer)) {
86+
throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', \is_object($this->normalizer) ? \get_class($this->normalizer) : \gettype($this->normalizer)));
87+
}
88+
}
7789
}

src/Symfony/Component/Validator/Constraints/UuidValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ public function validate($value, Constraint $constraint)
8181

8282
$value = (string) $value;
8383

84+
if (null !== $constraint->normalizer) {
85+
$value = ($constraint->normalizer)($value);
86+
}
87+
8488
if ($constraint->strict) {
8589
$this->validateStrict($value, $constraint);
8690

src/Symfony/Component/Validator/Tests/Constraints/EmailTest.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,36 @@ public function testConstructorStrict()
3535
}
3636

3737
/**
38-
* @expectedException \InvalidArgumentException
38+
* @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
3939
* @expectedExceptionMessage The "mode" parameter value is not valid.
4040
*/
4141
public function testUnknownModesTriggerException()
4242
{
4343
new Email(['mode' => 'Unknown Mode']);
4444
}
45+
46+
public function testNormalizerCanBeSet()
47+
{
48+
$email = new Email(['normalizer' => 'trim']);
49+
50+
$this->assertEquals('trim', $email->normalizer);
51+
}
52+
53+
/**
54+
* @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
55+
* @expectedExceptionMessage The "normalizer" option must be a valid callable ("string" given).
56+
*/
57+
public function testInvalidNormalizerThrowsException()
58+
{
59+
new Email(['normalizer' => 'Unknown Callable']);
60+
}
61+
62+
/**
63+
* @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
64+
* @expectedExceptionMessage The "normalizer" option must be a valid callable ("stdClass" given).
65+
*/
66+
public function testInvalidNormalizerObjectThrowsException()
67+
{
68+
new Email(['normalizer' => new \stdClass()]);
69+
}
4570
}

src/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ public function getValidEmails()
9494
];
9595
}
9696

97+
/**
98+
* @dataProvider getValidEmailsWithWhitespaces
99+
*/
100+
public function testValidNormalizedEmails($email)
101+
{
102+
$this->validator->validate($email, new Email(['normalizer' => 'trim']));
103+
104+
$this->assertNoViolation();
105+
}
106+
107+
public function getValidEmailsWithWhitespaces()
108+
{
109+
return [
110+
["\x20[email protected]\x20"],
111+
["\x09\x09[email protected]\x09\x09"],
112+
["\x0A{}~!@!@£$%%^&*().!@£$%^&*()\x0A"],
113+
["\x0D\x0D[email protected]\x0D\x0D"],
114+
115+
["[email protected]\x0B\x0B"],
116+
];
117+
}
118+
97119
/**
98120
* @dataProvider getValidEmailsHtml5
99121
*/
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Validator\Tests\Constraints;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Validator\Constraints\Ip;
16+
17+
/**
18+
* @author Renan Taranto <[email protected]>
19+
*/
20+
class IpTest extends TestCase
21+
{
22+
public function testNormalizerCanBeSet()
23+
{
24+
$ip = new Ip(['normalizer' => 'trim']);
25+
26+
$this->assertEquals('trim', $ip->normalizer);
27+
}
28+
29+
/**
30+
* @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
31+
* @expectedExceptionMessage The "normalizer" option must be a valid callable ("string" given).
32+
*/
33+
public function testInvalidNormalizerThrowsException()
34+
{
35+
new Ip(['normalizer' => 'Unknown Callable']);
36+
}
37+
38+
/**
39+
* @expectedException \Symfony\Component\Validator\Exception\InvalidArgumentException
40+
* @expectedExceptionMessage The "normalizer" option must be a valid callable ("stdClass" given).
41+
*/
42+
public function testInvalidNormalizerObjectThrowsException()
43+
{
44+
new Ip(['normalizer' => new \stdClass()]);
45+
}
46+
}

0 commit comments

Comments
 (0)