/
Rule.php
130 lines (113 loc) · 3.81 KB
/
Rule.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
declare(strict_types=1);
namespace Yiisoft\Validator;
use Yiisoft\I18n\TranslatorInterface;
/**
* Rule represents a single value validation rule.
*/
abstract class Rule
{
private ?TranslatorInterface $translator = null;
private ?string $translationDomain = null;
private ?string $translationLocale = null;
private bool $skipOnEmpty = false;
private bool $skipOnError = true;
/**
* Validates the value
*
* @param mixed $value value to be validated
* @param DataSetInterface|null $dataSet optional data set that could be used for contextual validation
* @param bool $previousRulesErrored set to true if rule is part of a group of rules and one of the previous validations failed
* @return Result
*/
final public function validate($value, DataSetInterface $dataSet = null, bool $previousRulesErrored = false): Result
{
if ($this->skipOnEmpty && $this->isEmpty($value)) {
return new Result();
}
if ($this->skipOnError && $previousRulesErrored) {
return new Result();
}
return $this->validateValue($value, $dataSet);
}
/**
* Validates the value. The method should be implemented by concrete validation rules.
*
* @param mixed $value value to be validated
* @param DataSetInterface|null $dataSet optional data set that could be used for contextual validation
* @return Result
*/
abstract protected function validateValue($value, DataSetInterface $dataSet = null): Result;
public function withTranslator(TranslatorInterface $translator): self
{
$new = clone $this;
$new->translator = $translator;
return $new;
}
public function withTranslationDomain(string $translation): self
{
$new = clone $this;
$new->translationDomain = $translation;
return $new;
}
public function withTranslationLocale(string $locale): self
{
$new = clone $this;
$new->translationLocale = $locale;
return $new;
}
public function translateMessage(string $message, array $arguments = []): string
{
if ($this->translator === null) {
return $this->formatMessage($message, $arguments);
}
return $this->translator->translate(
$message,
$arguments,
$this->translationDomain ?? 'validators',
$this->translationLocale
);
}
public function skipOnError(bool $value): self
{
$new = clone $this;
$new->skipOnError = $value;
return $new;
}
/**
* @param bool $value if validation should be skipped if value validated is empty
* @return self
*/
public function skipOnEmpty(bool $value): self
{
$new = clone $this;
$new->skipOnEmpty = $value;
return $new;
}
private function formatMessage(string $message, array $arguments = []): string
{
$replacements = [];
foreach ($arguments as $key => $value) {
if (is_array($value)) {
$value = 'array';
} elseif (is_object($value)) {
$value = 'object';
} elseif (is_resource($value)) {
$value = 'resource';
}
$replacements['{' . $key . '}'] = $value;
}
return strtr($message, $replacements);
}
/**
* Checks if the given value is empty.
* A value is considered empty if it is null, an empty array, or an empty string.
* Note that this method is different from PHP empty(). It will return false when the value is 0.
* @param mixed $value the value to be checked
* @return bool whether the value is empty
*/
protected function isEmpty($value): bool
{
return $value === null || $value === [] || $value === '';
}
}