Error::getValuePath()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 5
eloc 9
c 1
b 1
f 1
nc 5
nop 1
dl 0
loc 17
ccs 0
cts 0
cp 0
crap 30
rs 9.6111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator;
6
7
use InvalidArgumentException;
8
use Yiisoft\Translator\IntlMessageFormatter;
9 512
use Yiisoft\Translator\SimpleMessageFormatter;
10
use Yiisoft\Validator\Rule\Callback;
11
12
/**
13
 * A class representing validation error. It's added in a rule handler or via {@see Callback} rule to the {@see Result}
14
 * to form the complete list of errors for a single validation.
15
 */
16
final class Error
17
{
18
    /**
19
     * @param string $message The raw validation error message. Can be a simple text or a template with placeholders enclosed
20
     * in curly braces (`{}`). In the end of the validation it will be translated using configured translator.
21
     * {@see SimpleMessageFormatter} is usually enough, but for more complex translations
22 508
     * {@see IntlMessageFormatter} can be used (requires "intl" PHP extension). Examples:
23
     *
24 508
     * - `'The value must be a string.'` - simple text, works with both {@see SimpleMessageFormatter} and
25
     * {@see IntlMessageFormatter}.
26
     * - `'The value must be "{true}".'` - simple substitution, works with both formatters.
27
     * - `'This value must contain at least {min, number} {min, plural, one{item} other{items}}.' - plural form,
28
     * works with both formatters.
29
     * - `'You are {position, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} in the queue.'` - more
30 501
     * complex syntax, works only with {@see IntlMessageFormatter}, requires "intl".
31
     *
32 501
     * @link https://www.php.net/manual/en/book.intl.php
33
     *
34
     * @param array $parameters  Parameters used for {@see $message} translation - a mapping between parameter
35
     * names and values. Note that only scalar or `null` values are allowed.
36
     *
37
     * @link https://www.php.net/manual/ru/function.is-scalar.php
38 510
     *
39
     * @psalm-param array<string, scalar|null> $parameters
40 510
     *
41 508
     * @param array $valuePath A sequence of keys determining where a value caused the validation error is located
42
     * within a nested structure. Examples of different value paths:
43
     *
44 437
     * ```php
45 437
     * $data = [
46 437
     *     [
47
     *         1,
48
     *         'text', // The value path is [0, 1].
49
     *     ],
50
     *     'post' => [
51
     *         'title' => 'Yii3 Overview 3', // The value path is ['post', 'title'].
52
     *         'files' => [
53
     *             [
54
     *                 'url' => '...', // The value path is ['post', 'files', 0, 'url'].
55
     *             ],
56
     *         ],
57
     *     ],
58
     * ];
59
     * ```
60
     *
61
     * A value without nested structure won't have a path at all (it will be an empty array).
62
     *
63
     * @psalm-param list<int|string> $valuePath
64
     */
65
    public function __construct(
66
        private string $message,
67
        private array $parameters = [],
68
        private array $valuePath = [],
69
    ) {
70
    }
71
72
    /**
73
     * A getter for {@see $message} property. Returns raw (non-translated) validation error message.
74
     *
75
     * @return string A simple text or a template used for translation.
76
     */
77
    public function getMessage(): string
78
    {
79
        return $this->message;
80
    }
81
82
    /**
83
     * A getter for {@see $parameters} property. Returns parameters used for {@see $message} translation.
84
     *
85
     * @return array A mapping between parameter names and values.
86
     *
87
     * @psalm-return array<string, scalar|null>
88
     */
89
    public function getParameters(): array
90
    {
91
        return $this->parameters;
92
    }
93
94
    /**
95
     * A getter for {@see $valuePath} property. Returns a sequence of keys determining where a value caused the
96
     * validation error is located within a nested structure.
97
     *
98
     * @param bool|string|null $escape Symbol that will be escaped with a backslash char (`\`) in path elements.
99
     * When it's null path is returned without escaping.
100
     * Boolean value is deprecated and will be removed in the next major release. Boolean value processed in the following way:
101
     *  - `false` as null,
102
     *  - `true` as dot (`.`).
103
     *
104
     * @return array A list of keys for nested structures or an empty array otherwise.
105
     *
106
     * @psalm-return list<int|string>
107
     */
108
    public function getValuePath(bool|string|null $escape = false): array
109
    {
110
        if ($escape === false || $escape === null) {
111
            return $this->valuePath;
112
        }
113
114
        if ($escape === true) {
115
            $escape = '.';
116
        }
117
118
        if (mb_strlen($escape) !== 1) {
119
            throw new InvalidArgumentException('Escape symbol must be exactly one character.');
120
        }
121
122
        return array_map(
123
            static fn($key): string => str_replace($escape, '\\' . $escape, (string) $key),
124
            $this->valuePath,
125
        );
126
    }
127
}
128