Passed
Pull Request — master (#468)
by Sergei
03:08
created

Email::getHandlerClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Attribute;
8
use Closure;
9
use JetBrains\PhpStorm\Language;
10
use RuntimeException;
11
use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait;
12
use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait;
13
use Yiisoft\Validator\Rule\Trait\WhenTrait;
14
use Yiisoft\Validator\RuleWithOptionsInterface;
15
use Yiisoft\Validator\SkipOnEmptyInterface;
16
use Yiisoft\Validator\SkipOnErrorInterface;
17
use Yiisoft\Validator\WhenInterface;
18
19
use function function_exists;
20
21
/**
22
 * Validates that the value is a valid email address.
23
 *
24
 * @psalm-import-type WhenType from WhenInterface
25
 */
26
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
27
final class Email implements RuleWithOptionsInterface, SkipOnErrorInterface, WhenInterface, SkipOnEmptyInterface
28
{
29
    use SkipOnEmptyTrait;
30
    use SkipOnErrorTrait;
31
    use WhenTrait;
32 3
33
    public function __construct(
34
        #[Language('RegExp')]
35
        /**
36
         * @var string the regular expression used to validate value.
37
         *
38
         * @link https://www.regular-expressions.info/email.html
39
         */
40
        private string $pattern = '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/',
41
        #[Language('RegExp')]
42
        /**
43
         * @var string the regular expression used to validate email addresses with the name part. This property is used
44
         * only when {@see $allowName} is `true`.
45
         *
46
         * @see $allowName
47
         */
48
        private string $fullPattern = '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/',
49
        #[Language('RegExp')]
50
        /**
51
         * @var string the regular expression used to validate complex emails when {@see $enableIDN} is `true`.
52
         */
53
        private string $idnEmailPattern = '/^([a-zA-Z0-9._%+-]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/',
54
        /**
55
         * @var bool whether to allow name in the email address (e.g. "John Smith <[email protected]>"). Defaults
56
         * to `false`.
57
         *
58
         * @see $fullPattern
59
         */
60
        private bool $allowName = false,
61
        /**
62
         * @var bool whether to check whether the email's domain exists and has either an A or MX record.
63
         * Be aware that this check can fail due to temporary DNS problems even if the email address is
64
         * valid and an email would be deliverable. Defaults to `false`.
65
         */
66
        private bool $checkDNS = false,
67
        /**
68
         * @var bool whether validation process should take into account IDN (internationalized domain
69
         * names). Defaults to false meaning that validation of emails containing IDN will always fail.
70
         * Note that in order to use IDN validation you have to install and enable `intl` PHP extension,
71
         * otherwise an exception would be thrown.
72
         */
73
        private bool $enableIDN = false,
74
        private string $incorrectInputMessage = 'The value must have a string type.',
75
        private string $message = 'This value is not a valid email address.',
76
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed in a multi-line function declaration
Loading history...
77
        /**
78
         * @var bool|callable|null
79
         */
80
        private $skipOnEmpty = null,
81
        private bool $skipOnError = false,
82
        /**
83
         * @var WhenType
84
         */
85
        private Closure|null $when = null,
86 3
    ) {
87
        if ($enableIDN && !function_exists('idn_to_ascii')) {
88
            // Tested via separate CI configuration (see ".github/workflows/build.yml").
89
            // @codeCoverageIgnoreStart
90
            throw new RuntimeException('In order to use IDN validation intl extension must be installed and enabled.');
91
            // @codeCoverageIgnoreEnd
92
        }
93
    }
94 1
95
    public function getName(): string
96 1
    {
97
        return 'email';
98
    }
99 83
100
    public function getPattern(): string
101 83
    {
102
        return $this->pattern;
103
    }
104 20
105
    public function getFullPattern(): string
106 20
    {
107
        return $this->fullPattern;
108
    }
109 10
110
    public function getIdnEmailPattern(): string
111 10
    {
112
        return $this->idnEmailPattern;
113
    }
114 48
115
    public function isAllowName(): bool
116 48
    {
117
        return $this->allowName;
118
    }
119 48
120
    public function isCheckDNS(): bool
121 48
    {
122
        return $this->checkDNS;
123
    }
124 94
125
    public function isEnableIDN(): bool
126 94
    {
127
        return $this->enableIDN;
128
    }
129 5
130
    public function getIncorrectInputMessage(): string
131 5
    {
132
        return $this->incorrectInputMessage;
133
    }
134 49
135
    public function getMessage(): string
136 49
    {
137
        return $this->message;
138
    }
139 4
140
    public function getOptions(): array
141
    {
142 4
        return [
143 4
            'pattern' => $this->pattern,
144 4
            'fullPattern' => $this->fullPattern,
145 4
            'idnEmailPattern' => $this->idnEmailPattern,
146 4
            'allowName' => $this->allowName,
147 4
            'checkDNS' => $this->checkDNS,
148
            'enableIDN' => $this->enableIDN,
149 4
            'incorrectInputMessage' => [
150
                'template' => $this->incorrectInputMessage,
151
                'parameters' => [],
152
            ],
153 4
            'message' => [
154
                'template' => $this->message,
155
                'parameters' => [],
156 4
            ],
157 4
            'skipOnEmpty' => $this->getSkipOnEmptyOption(),
158
            'skipOnError' => $this->skipOnError,
159
        ];
160
    }
161 99
162
    public function getHandler(): string
163 99
    {
164
        return EmailHandler::class;
165
    }
166
}
167