Skip to content

Commit 4ed1913

Browse files
guillemfondinfabpot
authored andcommitted
[Validator] new email validation option to match with w3c official specification
1 parent a9adddb commit 4ed1913

File tree

5 files changed

+50
-0
lines changed

5 files changed

+50
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
6.2
55
---
66

7+
* Add option `Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD` with "html5-allow-no-tld" e-mail validation mode, to match with the W3C official specification
78
* Add method `getCause()` to `ConstraintViolationInterface`
89
* Add the `When` constraint and validator
910
* Deprecate the "loose" e-mail validation mode, use "html5" instead

Constraints/Email.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
2626
class Email extends Constraint
2727
{
28+
public const VALIDATION_MODE_HTML5_ALLOW_NO_TLD = 'html5-allow-no-tld';
2829
public const VALIDATION_MODE_HTML5 = 'html5';
2930
public const VALIDATION_MODE_STRICT = 'strict';
3031
/**
@@ -35,6 +36,7 @@ class Email extends Constraint
3536
public const INVALID_FORMAT_ERROR = 'bd79c0ab-ddba-46cc-a703-a7a4b08de310';
3637

3738
public const VALIDATION_MODES = [
39+
self::VALIDATION_MODE_HTML5_ALLOW_NO_TLD,
3840
self::VALIDATION_MODE_HTML5,
3941
self::VALIDATION_MODE_STRICT,
4042
self::VALIDATION_MODE_LOOSE,

Constraints/EmailValidator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
*/
2525
class EmailValidator extends ConstraintValidator
2626
{
27+
private const PATTERN_HTML5_ALLOW_NO_TLD = '/^[a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/';
2728
private const PATTERN_HTML5 = '/^[a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/';
2829
private const PATTERN_LOOSE = '/^.+\@\S+\.\S+$/';
2930

3031
private const EMAIL_PATTERNS = [
3132
Email::VALIDATION_MODE_LOOSE => self::PATTERN_LOOSE,
3233
Email::VALIDATION_MODE_HTML5 => self::PATTERN_HTML5,
34+
Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD => self::PATTERN_HTML5_ALLOW_NO_TLD,
3335
];
3436

3537
private string $defaultMode;

Tests/Constraints/EmailTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ public function testConstructorStrict()
2626
$this->assertEquals(Email::VALIDATION_MODE_STRICT, $subject->mode);
2727
}
2828

29+
public function testConstructorHtml5AllowNoTld()
30+
{
31+
$subject = new Email(['mode' => Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD]);
32+
33+
$this->assertEquals(Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD, $subject->mode);
34+
}
35+
2936
public function testUnknownModesTriggerException()
3037
{
3138
$this->expectException(InvalidArgumentException::class);

Tests/Constraints/EmailValidatorTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,35 @@ public function getInvalidHtml5Emails()
232232
];
233233
}
234234

235+
/**
236+
* @dataProvider getInvalidAllowNoTldEmails
237+
*/
238+
public function testInvalidAllowNoTldEmails($email)
239+
{
240+
$constraint = new Email([
241+
'message' => 'myMessage',
242+
'mode' => Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD,
243+
]);
244+
245+
$this->validator->validate($email, $constraint);
246+
247+
$this->buildViolation('myMessage')
248+
->setParameter('{{ value }}', '"'.$email.'"')
249+
->setCode(Email::INVALID_FORMAT_ERROR)
250+
->assertRaised();
251+
}
252+
253+
public function getInvalidAllowNoTldEmails()
254+
{
255+
return [
256+
['example bar'],
257+
['example@'],
258+
['example@ bar'],
259+
['example@localhost bar'],
260+
['foo@example.com bar'],
261+
];
262+
}
263+
235264
public function testModeStrict()
236265
{
237266
$constraint = new Email(['mode' => Email::VALIDATION_MODE_STRICT]);
@@ -253,6 +282,15 @@ public function testModeHtml5()
253282
->assertRaised();
254283
}
255284

285+
public function testModeHtml5AllowNoTld()
286+
{
287+
$constraint = new Email(['mode' => Email::VALIDATION_MODE_HTML5_ALLOW_NO_TLD]);
288+
289+
$this->validator->validate('example@example', $constraint);
290+
291+
$this->assertNoViolation();
292+
}
293+
256294
/**
257295
* @group legacy
258296
*/

0 commit comments

Comments
 (0)