Passed
Pull Request — master (#468)
by Sergei
03:08
created

Compare::getTargetAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Closure;
8
use InvalidArgumentException;
9
use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait;
10
use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait;
11
use Yiisoft\Validator\Rule\Trait\WhenTrait;
12
use Yiisoft\Validator\RuleWithOptionsInterface;
13
use Yiisoft\Validator\SkipOnEmptyInterface;
14
use Yiisoft\Validator\SkipOnErrorInterface;
15
use Yiisoft\Validator\WhenInterface;
16
17
/**
18
 * @psalm-import-type WhenType from WhenInterface
19
 */
20
abstract class Compare implements RuleWithOptionsInterface, SkipOnEmptyInterface, SkipOnErrorInterface, WhenInterface
21
{
22
    use SkipOnEmptyTrait;
23
    use SkipOnErrorTrait;
24
    use WhenTrait;
25
26
    /**
27
     * Constant for specifying the comparison as string values.
28
     * Values will be converted to strings before comparison.
29
     *
30
     * @see $type
31
     */
32
    public const TYPE_STRING = 'string';
33
    /**
34
     * Constant for specifying the comparison as numeric values.
35
     * Values will be converted to float numbers before comparison.
36
     *
37
     * @see $type
38
     */
39
    public const TYPE_NUMBER = 'number';
40
41
    private array $validOperatorsMap = [
42
        '==' => 1,
43
        '===' => 1,
44
        '!=' => 1,
45
        '!==' => 1,
46
        '>' => 1,
47
        '>=' => 1,
48
        '<' => 1,
49
        '<=' => 1,
50 34
    ];
51
52
    public function __construct(
53
        /**
54
         * @var scalar|null The constant value to be compared with. When both this property and {@see $targetAttribute}
55
         * are set, this property takes precedence.
56
         */
57
        private int|float|string|bool|null $targetValue = null,
58
        /**
59
         * @var string|null The name of the attribute to be compared with. When both this property and
60
         * {@see $targetValue} are set, the {@see $targetValue} takes precedence.
61
         */
62
        private string|null $targetAttribute = null,
63
        private string $incorrectInputMessage = 'The allowed types are integer, float, string, boolean and null.',
64
        private string $incorrectDataSetTypeMessage = 'The attribute value returned from a custom data set must have ' .
65
        'a scalar type.',
66
        /**
67
         * @var string|null User-defined error message.
68
         */
69
        private string|null $message = null,
70
        /**
71
         * @var string The type of the values being compared.
72
         */
73
        private string $type = self::TYPE_STRING,
74
        /**
75
         * @var string The operator for comparison. The following operators are supported:
76
         *
77
         * - `==`: check if two values are equal. The comparison is done in non-strict mode.
78
         * - `===`: check if two values are equal. The comparison is done in strict mode.
79
         * - `!=`: check if two values are NOT equal. The comparison is done in non-strict mode.
80
         * - `!==`: check if two values are NOT equal. The comparison is done in strict mode.
81
         * - `>`: check if value being validated is greater than the value being compared with.
82
         * - `>=`: check if value being validated is greater than or equal to the value being compared with.
83
         * - `<`: check if value being validated is less than the value being compared with.
84
         * - `<=`: check if value being validated is less than or equal to the value being compared with.
85
         *
86
         * When you want to compare numbers, make sure to also change {@see $type} to {@see TYPE_NUMBER}.
87
         */
88
        private string $operator = '==',
89
        /**
90
         * @var bool|callable|null
91
         */
92
        private mixed $skipOnEmpty = null,
93
        private bool $skipOnError = false,
94
        /**
95
         * @var WhenType
96
         */
97 34
        private Closure|null $when = null,
98 1
    ) {
99
        if (!isset($this->validOperatorsMap[$this->operator])) {
100 1
            $wrapInQuotesCallable = static fn (string $operator): string => '"' . $operator . '"';
101 1
            /** @var string[] $validOperators */
102 1
            $validOperators = array_keys($this->validOperatorsMap);
103
            $validOperatorsString = implode(', ', array_map($wrapInQuotesCallable, $validOperators));
104 1
            $message = "Operator \"$operator\" is not supported. The valid operators are: $validOperatorsString.";
105
106
            throw new InvalidArgumentException($message);
107
        }
108 79
    }
109
110 79
    public function getTargetValue(): int|float|string|bool|null
111
    {
112
        return $this->targetValue;
113 79
    }
114
115 79
    public function getTargetAttribute(): string|null
116
    {
117
        return $this->targetAttribute;
118 76
    }
119
120 76
    public function getType(): string
121
    {
122
        return $this->type;
123 76
    }
124
125 76
    public function getOperator(): string
126
    {
127
        return $this->operator;
128 4
    }
129
130 4
    public function getIncorrectInputMessage(): string
131
    {
132
        return $this->incorrectInputMessage;
133 3
    }
134
135 3
    public function getIncorrectDataSetTypeMessage(): string
136
    {
137
        return $this->incorrectDataSetTypeMessage;
138 82
    }
139
140 82
    public function getMessage(): string
141 22
    {
142 15
        return $this->message ?? match ($this->operator) {
143 7
            '==', '===' => 'Value must be equal to "{targetValueOrAttribute}".',
144 7
            '!=', '!==' => 'Value must not be equal to "{targetValueOrAttribute}".',
145 7
            '>' => 'Value must be greater than "{targetValueOrAttribute}".',
146 82
            '>=' => 'Value must be greater than or equal to "{targetValueOrAttribute}".',
147
            '<' => 'Value must be less than "{targetValueOrAttribute}".',
148
            '<=' => 'Value must be less than or equal to "{targetValueOrAttribute}".',
149
        };
150 40
    }
151
152 40
    public function getOptions(): array
153 40
    {
154 40
        $messageParameters = [
155 40
            'targetValue' => $this->targetValue,
156
            'targetAttribute' => $this->targetAttribute,
157
            'targetValueOrAttribute' => $this->targetValue ?? $this->targetAttribute,
158
        ];
159 40
160 40
        return [
161
            'targetValue' => $this->targetValue,
162 40
            'targetAttribute' => $this->targetAttribute,
163
            'incorrectInputMessage' => [
164
                'template' => $this->incorrectInputMessage,
165
                'parameters' => $messageParameters,
166 40
            ],
167
            'incorrectDataSetTypeMessage' => [
168
                'template' => $this->incorrectDataSetTypeMessage,
169
                'parameters' => $messageParameters,
170 40
            ],
171
            'message' => [
172
                'template' => $this->getMessage(),
173 40
                'parameters' => $messageParameters,
174 40
            ],
175 40
            'type' => $this->type,
176 40
            'operator' => $this->operator,
177
            'skipOnEmpty' => $this->getSkipOnEmptyOption(),
178
            'skipOnError' => $this->skipOnError,
179
        ];
180 83
    }
181
182 83
    public function getHandler(): string
183
    {
184
        return CompareHandler::class;
185
    }
186
}
187