Passed
Pull Request — master (#477)
by Alexander
13:25 queued 10:58
created

Email::getIncorrectInputMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
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 the 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.
44
         * This property is used 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 a name in the email address (e.g. "John Smith <[email protected]>").
56
         * Defaults to `false`.
57
         *
58
         * @see $fullPattern
59
         */
60
        private bool $allowName = false,
61
        /**
62
         * @var bool Whether to check 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 IDN (internationalized domain names) into account.
69
         * 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
        /**
75
         * @var string A message used when the input is incorrect.
76
         *
77
         * You may use the following placeholders in the message:
78
         *
79
         * - `{attribute}`: the label of the attribute being validated.
80
         * - `{value}`: the value of the attribute being validated.
81
         */
82
        private string $incorrectInputMessage = 'The value must have a string type.',
83
        /**
84
         * @var string A message used when the value is not valid.
85
         *
86 3
         * You may use the following placeholders in the message:
87
         *
88
         * - `{attribute}`: the label of the attribute being validated.
89
         * - `{value}`: the value of the attribute being validated.
90
         */
91
        private string $message = 'This value is not a valid email address.',
92
        /**
93
         * @var bool|callable|null Whether to skip this rule if the value validated is empty.
94 1
         *
95
         * @see SkipOnEmptyInterface
96 1
         */
97
        private $skipOnEmpty = null,
98
        /**
99 83
         * @var bool Whether to skip this rule if any of the previous rules gave an error.
100
         */
101 83
        private bool $skipOnError = false,
102
        /**
103
         * @var Closure|null A callable to define a condition for applying the rule.
104 20
         * @psalm-var WhenType
105
         *
106 20
         * @see WhenInterface
107
         */
108
        private Closure|null $when = null,
109 10
    ) {
110
        if ($enableIDN && !function_exists('idn_to_ascii')) {
111 10
            // Tested via separate CI configuration (see ".github/workflows/build.yml").
112
            // @codeCoverageIgnoreStart
113
            throw new RuntimeException('In order to use IDN validation intl extension must be installed and enabled.');
114 48
            // @codeCoverageIgnoreEnd
115
        }
116 48
    }
117
118
    public function getName(): string
119 48
    {
120
        return 'email';
121 48
    }
122
123
    /**
124 94
     * @return string The regular expression used to validate the value.
125
     *
126 94
     * @see $pattern
127
     */
128
    public function getPattern(): string
129 5
    {
130
        return $this->pattern;
131 5
    }
132
133
    /**
134 49
     * @return string The regular expression used to validate email addresses with the name part.
135
     *
136 49
     * @see $fullPattern
137
     */
138
    public function getFullPattern(): string
139 4
    {
140
        return $this->fullPattern;
141
    }
142 4
143 4
    /**
144 4
     * @return string The regular expression used to validate complex emails when {@see $enableIDN} is `true`.
145 4
     *
146 4
     * @see $idnEmailPattern
147 4
     */
148
    public function getIdnEmailPattern(): string
149 4
    {
150
        return $this->idnEmailPattern;
151
    }
152
153 4
    /**
154
     * @return bool Whether to allow a name in the email address (e.g. "John Smith <[email protected]>").
155
     *
156 4
     * @see $allowName
157 4
     */
158
    public function isNameAllowed(): bool
159
    {
160
        return $this->allowName;
161 99
    }
162
163 99
    /**
164
     * @return bool Whether to check email's domain exists and has either an A or MX record.
165
     *
166
     * @see $checkDNS
167
     */
168
    public function shouldCheckDNS(): bool
169
    {
170
        return $this->checkDNS;
171
    }
172
173
    /**
174
     * @return bool Whether validation process should take IDN (internationalized domain names) into account.
175
     *
176
     * @see $enableIDN
177
     */
178
    public function isIDNEnabled(): bool
179
    {
180
        return $this->enableIDN;
181
    }
182
183
    /**
184
     * @return string A message used when the input is incorrect.
185
     *
186
     * @see $incorrectInputMessage
187
     */
188
    public function getIncorrectInputMessage(): string
189
    {
190
        return $this->incorrectInputMessage;
191
    }
192
193
    /**
194
     * @return string A message used when the value is not valid.
195
     *
196
     * @see $message
197
     */
198
    public function getMessage(): string
199
    {
200
        return $this->message;
201
    }
202
203
    public function getOptions(): array
204
    {
205
        return [
206
            'pattern' => $this->pattern,
207
            'fullPattern' => $this->fullPattern,
208
            'idnEmailPattern' => $this->idnEmailPattern,
209
            'allowName' => $this->allowName,
210
            'checkDNS' => $this->checkDNS,
211
            'enableIDN' => $this->enableIDN,
212
            'incorrectInputMessage' => [
213
                'template' => $this->incorrectInputMessage,
214
                'parameters' => [],
215
            ],
216
            'message' => [
217
                'template' => $this->message,
218
                'parameters' => [],
219
            ],
220
            'skipOnEmpty' => $this->getSkipOnEmptyOption(),
221
            'skipOnError' => $this->skipOnError,
222
        ];
223
    }
224
225
    public function getHandler(): string
226
    {
227
        return EmailHandler::class;
228
    }
229
}
230