Passed
Pull Request — master (#474)
by Alexander
02:42
created

ValidationContext::getParameter()   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 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
nc 1
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator;
6
7
use RuntimeException;
8
use Yiisoft\Arrays\ArrayHelper;
9
10
/**
11
 * Validation context that might be taken into account when performing validation.
12
 *
13
 * @psalm-import-type RulesType from ValidatorInterface
14
 */
15
final class ValidationContext
16
{
17
    /**
18
     * @var ValidatorInterface|null A validator instance. `null` means context data was not set
19 827
     * with {@see setContextDataOnce()} yet.
20
     */
21
    private ?ValidatorInterface $validator = null;
22
23
    /**
24
     * @var mixed The raw validated data. `null` means context data was not set with {@see setContextDataOnce()} yet.
25
     */
26
    private mixed $rawData = null;
27 43
28
    /**
29 43
     * @var DataSetInterface|null Data set the attribute belongs to.
30
     * `null` if data set was not set with {@see setDataSet()} yet.
31
     */
32
    private ?DataSetInterface $dataSet = null;
33
34
    /**
35 11
     * @var string|null Validated data set's attribute name. `null` if a single value is validated.
36
     */
37 11
    private ?string $attribute = null;
38
39
    /**
40
     * @var AttributeTranslatorInterface|null Default attribute translator to use if attribute translator is not set.
41
     */
42
    private ?AttributeTranslatorInterface $defaultAttributeTranslator = null;
43 503
44
    /**
45 503
     * @param array $parameters Arbitrary parameters.
46
     * @param AttributeTranslatorInterface|null $attributeTranslator Optional attribute translator instance to use.
47
     * If `null` is provided, or it's not specified, a default translator passed through
48
     * {@see setContextDataOnce()} is used.
49
     */
50
    public function __construct(
51 140
        private array $parameters = [],
52
        private ?AttributeTranslatorInterface $attributeTranslator = null,
53 140
    ) {
54 140
    }
55
56
    /**
57
     * Set context data if it is not set yet.
58
     *
59
     * @param ValidatorInterface $validator A validator instance.
60 3
     * @param AttributeTranslatorInterface $attributeTranslator Attribute translator to use by default. If translator
61
     * is specified via {@see setAttributeTranslator()}, it will be used instead.
62 3
     * @param mixed $rawData The raw validated data.
63
     *
64
     * @internal
65
     *
66
     * @return $this The same instance of validation context.
67
     */
68
    public function setContextDataOnce(
69
        ValidatorInterface $validator,
70
        AttributeTranslatorInterface $attributeTranslator,
71
        mixed $rawData
72
    ): self {
73
        if ($this->validator !== null) {
74
            return $this;
75 6
        }
76
77 6
        $this->validator = $validator;
78
        $this->defaultAttributeTranslator = $attributeTranslator;
79
        $this->rawData = $rawData;
80 503
81
        return $this;
82 503
    }
83
84
    /**
85 786
     * Set attribute translator to use.
86
     *
87 786
     * @param AttributeTranslatorInterface|null $attributeTranslator Attribute translator to use. If `null`,
88
     * translator passed in {@see setContextData()} will be used.
89
     *
90
     * @return $this The same instance of validation context.
91
     */
92
    public function setAttributeTranslator(?AttributeTranslatorInterface $attributeTranslator): self
93
    {
94
        $this->attributeTranslator = $attributeTranslator;
95
        return $this;
96
    }
97
98
    /**
99
     * Validate data in current context.
100
     *
101
     * @param mixed $data Data set to validate. If {@see RulesProviderInterface} instance provided and rules are
102
     * not specified explicitly, they are read from the {@see RulesProviderInterface::getRules()}.
103
     * @param callable|iterable|object|string|null $rules Rules to apply. If specified, rules are not read from data set
104
     * even if it is an instance of {@see RulesProviderInterface}.
105
     *
106
     * @psalm-param RulesType $rules
107
     *
108
     * @throws RuntimeException If validator is not set in validation context.
109
     *
110
     * @return Result Validation result.
111
     */
112
    public function validate(mixed $data, callable|iterable|object|string|null $rules = null): Result
113
    {
114
        $this->requireValidator();
115
116
        $currentDataSet = $this->dataSet;
117
        $currentAttribute = $this->attribute;
118
119
        $result = $this->validator->validate($data, $rules, $this);
0 ignored issues
show
Bug introduced by
The method validate() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
        /** @scrutinizer ignore-call */ 
120
        $result = $this->validator->validate($data, $rules, $this);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
120
121
        $this->dataSet = $currentDataSet;
122
        $this->attribute = $currentAttribute;
123
124
        return $result;
125
    }
126
127
    /**
128
     * Get the raw validated data.
129
     *
130
     * @throws RuntimeException If validator is not set in validation context.
131
     *
132
     * @return mixed The raw validated data.
133
     */
134
    public function getRawData(): mixed
135
    {
136
        $this->requireValidator();
137
        return $this->rawData;
138
    }
139
140
    /**
141
     * Get the data set the attribute belongs to.
142
     *
143
     * @return DataSetInterface Data set the attribute belongs to.
144
     */
145
    public function getDataSet(): DataSetInterface
146
    {
147
        if ($this->dataSet === null) {
148
            throw new RuntimeException('Data set in validation context is not set.');
149
        }
150
151
        return $this->dataSet;
152
    }
153
154
    /**
155
     * Set the data set the attribute belongs to.
156
     *
157
     * @param DataSetInterface $dataSet Data set the attribute belongs to.
158
     *
159
     * @return $this The same instance of validation context.
160
     *
161
     * @internal
162
     */
163
    public function setDataSet(DataSetInterface $dataSet): self
164
    {
165
        $this->dataSet = $dataSet;
166
        return $this;
167
    }
168
169
    /**
170
     * Get validated data set's attribute name.
171
     *
172
     * @return string|null Validated data set's attribute name. `null` if a single value is validated.
173
     */
174
    public function getAttribute(): ?string
175
    {
176
        return $this->attribute;
177
    }
178
179
    /**
180
     * Get translated attribute name.
181
     *
182
     * @return string|null Translated attribute name. `null` if a single value is validated and there is nothing
183
     * to translate.
184
     */
185
    public function getTranslatedAttribute(): ?string
186
    {
187
        if ($this->attribute === null) {
188
            return null;
189
        }
190
191
        if ($this->attributeTranslator !== null) {
192
            return $this->attributeTranslator->translate($this->attribute);
193
        }
194
195
        if ($this->defaultAttributeTranslator !== null) {
196
            return $this->defaultAttributeTranslator->translate($this->attribute);
197
        }
198
199
        return $this->attribute;
200
    }
201
202
    /**
203
     * Set the name of the attribute validated.
204
     *
205
     * @param string|null $attribute Validated attribute name. Null if a single value is validated.
206
     *
207
     * @return $this The same instance of validation context.
208
     *
209
     * @internal
210
     */
211
    public function setAttribute(?string $attribute): self
212
    {
213
        $this->attribute = $attribute;
214
        return $this;
215
    }
216
217
    /**
218
     * Get named parameter.
219
     *
220
     * @param string $name Parameter name.
221
     * @param mixed $default Default value to return in case parameter with a given name does not exist.
222
     *
223
     * @return mixed Parameter value.
224
     *
225
     * @see ArrayHelper::getValue()
226
     */
227
    public function getParameter(string $name, mixed $default = null): mixed
228
    {
229
        return ArrayHelper::getValue($this->parameters, $name, $default);
230
    }
231
232
    /**
233
     * Set parameter value.
234
     *
235
     * @param string $name Parameter name.
236
     * @param mixed $value Parameter value.
237
     *
238
     * @return $this The same instance of validation context.
239
     */
240
    public function setParameter(string $name, mixed $value): self
241
    {
242
        $this->parameters[$name] = $value;
243
        return $this;
244
    }
245
246
    /**
247
     * Check whether {@see $attribute} is missing in a {@see $dataSet}.
248
     *
249
     * @return bool Whether {@see $attribute} is missing in a {@see $dataSet}.
250
     */
251
    public function isAttributeMissing(): bool
252
    {
253
        return $this->attribute !== null && !$this->getDataSet()->hasAttribute($this->attribute);
254
    }
255
256
    /**
257
     * Ensure that validator is set in validation context.
258
     *
259
     * @psalm-assert ValidatorInterface $this->validator
260
     *
261
     * @throws RuntimeException If validator is not set in validation context.
262
     */
263
    private function requireValidator(): void
264
    {
265
        if ($this->validator === null) {
266
            throw new RuntimeException('Validator is not set in validation context.');
267
        }
268
    }
269
}
270