1
+ <?php
2
+
3
+ namespace ProgrammatorDev \YetAnotherPhpValidator \Rule ;
4
+
5
+ use Egulias \EmailValidator \EmailValidator ;
6
+ use Egulias \EmailValidator \Validation \NoRFCWarningsValidation ;
7
+ use ProgrammatorDev \YetAnotherPhpValidator \Exception \EmailException ;
8
+ use ProgrammatorDev \YetAnotherPhpValidator \Exception \UnexpectedOptionException ;
9
+ use ProgrammatorDev \YetAnotherPhpValidator \Exception \UnexpectedTypeException ;
10
+
11
+ class Email extends AbstractRule implements RuleInterface
12
+ {
13
+ public const MODE_HTML5 = 'html5 ' ;
14
+ public const MODE_HTML5_ALLOW_NO_TLD = 'html5-allow-no-tld ' ;
15
+ public const MODE_STRICT = 'strict ' ;
16
+
17
+ private const EMAIL_MODES = [
18
+ self ::MODE_HTML5 ,
19
+ self ::MODE_HTML5_ALLOW_NO_TLD ,
20
+ self ::MODE_STRICT
21
+ ];
22
+
23
+ private const EMAIL_PATTERNS = [
24
+ self ::MODE_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])?)+$/ ' ,
25
+ self ::MODE_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])?)*$/ '
26
+ ];
27
+
28
+ // Using array to bypass unallowed callable type in properties
29
+ private array $ normalizer ;
30
+
31
+ public function __construct (
32
+ private readonly string $ mode = self ::MODE_HTML5 ,
33
+ ?callable $ normalizer = null ,
34
+ private readonly string $ message = 'The {{ name }} value is not a valid email address, {{ value }} given. '
35
+ )
36
+ {
37
+ $ this ->normalizer ['callable ' ] = $ normalizer ;
38
+ }
39
+
40
+ public function assert (mixed $ value , ?string $ name = null ): void
41
+ {
42
+ if (!\in_array ($ this ->mode , self ::EMAIL_MODES , true )) {
43
+ throw new UnexpectedOptionException ('mode ' , self ::EMAIL_MODES , $ this ->mode );
44
+ }
45
+
46
+ if (!\is_string ($ value )) {
47
+ throw new UnexpectedTypeException ('string ' , get_debug_type ($ value ));
48
+ }
49
+
50
+ if ($ this ->normalizer ['callable ' ] !== null ) {
51
+ $ value = ($ this ->normalizer ['callable ' ])($ value );
52
+ }
53
+
54
+ if ($ this ->mode === self ::MODE_STRICT ) {
55
+ $ emailValidator = new EmailValidator ();
56
+
57
+ if (!$ emailValidator ->isValid ($ value , new NoRFCWarningsValidation ())) {
58
+ throw new EmailException (
59
+ message: $ this ->message ,
60
+ parameters: [
61
+ 'value ' => $ value ,
62
+ 'name ' => $ name ,
63
+ 'mode ' => $ this ->mode
64
+ ]
65
+ );
66
+ }
67
+ }
68
+ else if (!\preg_match (self ::EMAIL_PATTERNS [$ this ->mode ], $ value )) {
69
+ throw new EmailException (
70
+ message: $ this ->message ,
71
+ parameters: [
72
+ 'value ' => $ value ,
73
+ 'name ' => $ name ,
74
+ 'mode ' => $ this ->mode
75
+ ]
76
+ );
77
+ }
78
+ }
79
+ }
0 commit comments