Passed
Push — master ( cd2db1...fdabae )
by Alexander
02:29
created

Compare::getOperator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
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 2
cts 2
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 RuntimeException;
10
use Yiisoft\Validator\BeforeValidationInterface;
11
use Yiisoft\Validator\Rule\Trait\BeforeValidationTrait;
12
use Yiisoft\Validator\Rule\Trait\RuleNameTrait;
13
use Yiisoft\Validator\SerializableRuleInterface;
14
use Yiisoft\Validator\ValidationContext;
15
16
abstract class Compare implements SerializableRuleInterface, BeforeValidationInterface
17
{
18
    use BeforeValidationTrait;
19
    use RuleNameTrait;
20
21
    /**
22
     * Constant for specifying the comparison as string values.
23
     * No conversion will be done before comparison.
24
     *
25
     * @see $type
26
     */
27
    public const TYPE_STRING = 'string';
28
    /**
29
     * Constant for specifying the comparison as numeric values.
30
     * String values will be converted into numbers before comparison.
31
     *
32
     * @see $type
33
     */
34
    public const TYPE_NUMBER = 'number';
35
36
    private array $validOperators = [
37
        '==' => 1,
38
        '===' => 1,
39
        '!=' => 1,
40
        '!==' => 1,
41
        '>' => 1,
42
        '>=' => 1,
43
        '<' => 1,
44
        '<=' => 1,
45
    ];
46
47 28
    public function __construct(
48
        /**
49
         * @var mixed The constant value to be compared with. When both this property
50
         * and {@see $targetAttribute} are set, this property takes precedence.
51
         */
52
        private $targetValue = null,
53
        /**
54
         * @var string|null The name of the attribute to be compared with. When both this property
55
         * and {@see $targetValue} are set, the {@see $targetValue} takes precedence.
56
         *
57
         * @see $targetValue
58
         */
59
        private ?string $targetAttribute = null,
60
        /**
61
         * @var string|null User-defined error message.
62
         */
63
        private ?string $message = null,
64
        /**
65
         * @var string The type of the values being compared.
66
         */
67
        private string $type = self::TYPE_STRING,
68
        /**
69
         * @var string The operator for comparison. The following operators are supported:
70
         *
71
         * - `==`: check if two values are equal. The comparison is done is non-strict mode.
72
         * - `===`: check if two values are equal. The comparison is done is strict mode.
73
         * - `!=`: check if two values are NOT equal. The comparison is done is non-strict mode.
74
         * - `!==`: check if two values are NOT equal. The comparison is done is strict mode.
75
         * - `>`: check if value being validated is greater than the value being compared with.
76
         * - `>=`: check if value being validated is greater than or equal to the value being compared with.
77
         * - `<`: check if value being validated is less than the value being compared with.
78
         * - `<=`: check if value being validated is less than or equal to the value being compared with.
79
         *
80
         * When you want to compare numbers, make sure to also change @see $type} to
81
         * {@see TYPE_NUMBER}.
82
         */
83
        private string $operator = '==',
84
        private bool $skipOnEmpty = false,
85
        /**
86
         * @var callable
87
         */
88
        private $skipOnEmptyCallback = null,
89
        private bool $skipOnError = false,
90
        /**
91
         * @var Closure(mixed, ValidationContext):bool|null
92
         */
93
        private ?Closure $when = null,
94
    ) {
95 28
        $this->initSkipOnEmptyProperties($skipOnEmpty, $skipOnEmptyCallback);
96
97 28
        if (!isset($this->validOperators[$operator])) {
98
            throw new InvalidArgumentException("Operator \"$operator\" is not supported.");
99
        }
100
    }
101
102 67
    public function getTargetValue(): mixed
103
    {
104 67
        return $this->targetValue;
105
    }
106
107 67
    public function getTargetAttribute(): ?string
108
    {
109 67
        return $this->targetAttribute;
110
    }
111
112 67
    public function getType(): string
113
    {
114 67
        return $this->type;
115
    }
116
117 67
    public function getOperator(): string
118
    {
119 67
        return $this->operator;
120
    }
121
122 82
    public function getMessage(): string
123
    {
124 82
        return $this->message ?? match ($this->operator) {
125 19
            '==', '===' => 'Value must be equal to "{targetValueOrAttribute}".',
126 16
            '!=', '!==' => 'Value must not be equal to "{targetValueOrAttribute}".',
127 8
            '>' => 'Value must be greater than "{targetValueOrAttribute}".',
128 8
            '>=' => 'Value must be greater than or equal to "{targetValueOrAttribute}".',
129 8
            '<' => 'Value must be less than "{targetValueOrAttribute}".',
130 8
            '<=' => 'Value must be less than or equal to "{targetValueOrAttribute}".',
131 82
            default => throw new RuntimeException("Unknown operator: $this->operator."),
132
        };
133
    }
134
135 45
    public function getOptions(): array
136
    {
137
        return [
138 45
            'targetValue' => $this->targetValue,
139 45
            'targetAttribute' => $this->targetAttribute,
140
            'message' => [
141 45
                'message' => $this->getMessage(),
142
                'parameters' => [
143 45
                    'targetValue' => $this->targetValue,
144 45
                    'targetAttribute' => $this->targetAttribute,
145 45
                    'targetValueOrAttribute' => $this->targetValue ?? $this->targetAttribute,
146
                ],
147
            ],
148 45
            'type' => $this->type,
149 45
            'operator' => $this->operator,
150 45
            'skipOnEmpty' => $this->skipOnEmpty,
151 45
            'skipOnError' => $this->skipOnError,
152
        ];
153
    }
154
155 8
    public function getHandlerClassName(): string
156
    {
157 8
        return CompareHandler::class;
158
    }
159
}
160