Passed
Pull Request — master (#477)
by
unknown
11:37 queued 08:59
created

Email::getName()   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 RuntimeException;
10
use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait;
11
use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait;
12
use Yiisoft\Validator\Rule\Trait\WhenTrait;
13
use Yiisoft\Validator\RuleWithOptionsInterface;
14
use Yiisoft\Validator\SkipOnEmptyInterface;
15
use Yiisoft\Validator\SkipOnErrorInterface;
16
use Yiisoft\Validator\WhenInterface;
17
18
use function function_exists;
19
20
/**
21
 * Defines validation options to check that the value is a valid email address.
22
 *
23
 * @see EmailHandler
24
 *
25
 * @psalm-import-type WhenType from WhenInterface
26
 */
27
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
28
final class Email implements RuleWithOptionsInterface, SkipOnErrorInterface, WhenInterface, SkipOnEmptyInterface
29
{
30
    use SkipOnEmptyTrait;
31
    use SkipOnErrorTrait;
32 3
    use WhenTrait;
33
34
    /**
35
     * @param string $pattern The regular expression used to validate the value. See {@link https://www.regular-expressions.info/email.html}.
36
     * @param string $fullPattern The regular expression used to validate email addresses with the name part.
37
     * This property is used only when {@see $allowName} is `true`.
38
     * @param string $idnEmailPattern The regular expression used to validate complex emails when {@see $enableIdn} is `true`.
39
     * @param bool $allowName bool Whether to allow a name in the email address (e.g. "John Smith <[email protected]>").
40
     * Defaults to `false`. See {@see $fullPattern}.
41
     * @param bool $checkDns bool Whether to check email's domain exists and has either an A or MX record.
42
     * Be aware that this check can fail due to temporary DNS problems even if the email address is
43
     * valid and an email would be deliverable. Defaults to `false`.
44
     * @param bool $enableIdn Whether validation process should take IDN (internationalized domain names) into account.
45
     * Defaults to `false` meaning that validation of emails containing IDN will always fail.
46
     * Note that in order to use IDN validation you have to install and enable `intl` PHP extension,
47
     * otherwise an exception will be thrown.
48
     * @param string $incorrectInputMessage A message used when the input is incorrect.
49
     *
50
     * You may use the following placeholders in the message:
51
     *
52
     * - `{attribute}`: the label of the attribute being validated.
53
     * - `{type}`: the type of the attribute being validated.
54
     * @param string $message A message used when the value is not valid.
55
     *
56
     * You may use the following placeholders in the message:
57
     *
58
     * - `{attribute}`: the label of the attribute being validated.
59
     * - `{value}`: the value of the attribute being validated.
60
     * @param bool|callable|null $skipOnEmpty Whether to skip this rule if the value validated is empty. See {@see SkipOnEmptyInterface}.
61
     * @param bool $skipOnError Whether to skip this rule if any of the previous rules gave an error. See {@see SkipOnErrorInterface}.
62
     * @param Closure|null $when A callable to define a condition for applying the rule. See {@see WhenInterface}.
63
     * @psalm-param WhenType $when
64
     *
65
     * @throws RuntimeException If there was an attempt to enable IDN ({@see $enableIdn}), but "intl" PHP extension is
66
     * not installed or not enabled.
67
     */
68
    public function __construct(
69
        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])?$/',
70
        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])?>$/',
71
        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})(\]?)$/',
72
        private bool $allowName = false,
73
        private bool $checkDns = false,
74
        private bool $enableIdn = false,
75
        private string $incorrectInputMessage = 'The value must have a string type.',
76
        private string $message = 'This value is not a valid email address.',
77
        private mixed $skipOnEmpty = null,
78
        private bool $skipOnError = false,
79
        private Closure|null $when = null,
80
    ) {
81
        if ($enableIdn && !function_exists('idn_to_ascii')) {
82
            // Tested via separate CI configuration (see ".github/workflows/build.yml").
83
            // @codeCoverageIgnoreStart
84
            throw new RuntimeException('In order to use IDN validation intl extension must be installed and enabled.');
85
            // @codeCoverageIgnoreEnd
86 3
        }
87
    }
88
89
    public function getName(): string
90
    {
91
        return 'email';
92
    }
93
94 1
    /**
95
     * Get the regular expression used to validate the value.
96 1
     *
97
     * @return string The regular expression.
98
     *
99 83
     * @see $pattern
100
     */
101 83
    public function getPattern(): string
102
    {
103
        return $this->pattern;
104 20
    }
105
106 20
    /**
107
     * Get the regular expression used to validate email addresses with the name part.
108
     *
109 10
     * @return string The regular expression.
110
     *
111 10
     * @see $fullPattern
112
     */
113
    public function getFullPattern(): string
114 48
    {
115
        return $this->fullPattern;
116 48
    }
117
118
    /**
119 48
     * Get the regular expression used to validate complex emails when {@see $enableIdn} is `true`.
120
     *
121 48
     * @return string The regular expression.
122
     *
123
     * @see $idnEmailPattern
124 94
     */
125
    public function getIdnEmailPattern(): string
126 94
    {
127
        return $this->idnEmailPattern;
128
    }
129 5
130
    /**
131 5
     * Whether to allow a name in the email address (e.g. "John Smith <[email protected]>").
132
     *
133
     * @return bool Whether to allow a name in the email address.
134 49
     *
135
     * @see $allowName
136 49
     */
137
    public function isNameAllowed(): bool
138
    {
139 4
        return $this->allowName;
140
    }
141
142 4
    /**
143 4
     * Whether to check email's domain exists and has either an A or MX record.
144 4
     *
145 4
     * @return bool Whether to check email's domain exists and has either an A or MX record.
146 4
     *
147 4
     * @see $checkDns
148
     */
149 4
    public function shouldCheckDns(): bool
150
    {
151
        return $this->checkDns;
152
    }
153 4
154
    /**
155
     * Whether validation process should take IDN (internationalized domain names) into account.
156 4
     *
157 4
     * @return bool Whether validation process should take IDN (internationalized domain names) into account.
158
     *
159
     * @see $enableIdn
160
     */
161 99
    public function isIdnEnabled(): bool
162
    {
163 99
        return $this->enableIdn;
164
    }
165
166
    /**
167
     * Get a message used when the input is incorrect.
168
     *
169
     * @return string A message used when the input is incorrect.
170
     *
171
     * @see $incorrectInputMessage
172
     */
173
    public function getIncorrectInputMessage(): string
174
    {
175
        return $this->incorrectInputMessage;
176
    }
177
178
    /**
179
     * Get a message used when the value is not valid.
180
     *
181
     * @return string A message used when the value is not valid.
182
     *
183
     * @see $message
184
     */
185
    public function getMessage(): string
186
    {
187
        return $this->message;
188
    }
189
190
    public function getOptions(): array
191
    {
192
        return [
193
            'pattern' => $this->pattern,
194
            'fullPattern' => $this->fullPattern,
195
            'idnEmailPattern' => $this->idnEmailPattern,
196
            'allowName' => $this->allowName,
197
            'checkDns' => $this->checkDns,
198
            'enableIdn' => $this->enableIdn,
199
            'incorrectInputMessage' => [
200
                'template' => $this->incorrectInputMessage,
201
                'parameters' => [],
202
            ],
203
            'message' => [
204
                'template' => $this->message,
205
                'parameters' => [],
206
            ],
207
            'skipOnEmpty' => $this->getSkipOnEmptyOption(),
208
            'skipOnError' => $this->skipOnError,
209
        ];
210
    }
211
212
    public function getHandler(): string
213
    {
214
        return EmailHandler::class;
215
    }
216
}
217