Test Failed
Push — master ( 567732...2e549a )
by Alexander
02:18
created

Compare::getOperator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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