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