initCountableLimitProperties()   C
last analyzed

Complexity

Conditions 17
Paths 7

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 21
nc 7
nop 6
dl 0
loc 40
rs 5.2166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule\Trait;
6
7
use InvalidArgumentException;
8
use JetBrains\PhpStorm\ArrayShape;
9
10
/**
11
 * An implementation for {@see CountableLimitInterface} intended to be included in rules. The following arguments need
12
 * to be added in constructor and passed with {@see initLimitProperties()} call:
13
 *
14
 * ```php
15
 * public function __construct(
16
 *     // ...
17
 *     int|null $min = null,
18
 *     int|null $max = null,
19
 *     int|null $exactly = null,
20
 *     string $lessThanMinMessage = 'Less than {min}.',
21
 *     string $greaterThanMinMessage = 'Greater than {max}.',
22
 *     string $greaterThanMinMessage = 'Not exactly {exactly}.',
23
 *     // ...
24
 * ) {
25
 *     // ...
26
 *     $this->initLimitProperties(
27
 *         $min,
28
 *         $max,
29
 *         $exactly,
30
 *         $lessThanMinMessage,
31
 *         $greaterThanMaxMessage,
32
 *         $notExactlyMessage,
33
 *     );
34
 *     // ...
35
 * }
36
 * ```
37
 *
38
 * Also, if a rule implements {@see DumpedRuleInterface}, you can merge limit related options instead of adding it
39
 * manually:
40
 *
41
 * ```php
42
 * public function getOptions(): array
43
 * {
44
 *     return array_merge($this->getLimitOptions(), [
45
 *         // Other rule options.
46
 *     ]);
47
 * }
48
 * ```
49
 *
50
 * Make sure to include {@see CountableLimitHandlerTrait} in according handler as well.
51
 */
52
trait CountableLimitTrait
53
{
54
    /**
55
     * @var int|null Minimum limit. Can't be combined with {@see $exactly}.
56
     *
57
     * @see $lessThanMinMessage for related error message.
58
     */
59
    private int|null $min = null;
60
    /**
61
     * @var int|null Maximum limit. Can't be combined with {@see $exactly}.
62
     *
63
     * @see $greaterThanMaxMessage for related error message.
64
     */
65
    private int|null $max = null;
66
    /**
67
     * @var int|null "Exactly" number. A shortcut / replacement for the case when {@see $min} and {@see $max} have the
68
     * same not-null value. Mutually exclusive with both {@see $min} and {@see $max}. `null` means no strict comparison
69
     * so lower / upper limits / both must be set.
70
     *
71
     * @see $notExactlyMessage for related error message.
72
     */
73
    private int|null $exactly = null;
74
    /**
75
     * @var string Validation error message used when a validated value is less than minimum set in {@see $min}.
76
     */
77
    private string $lessThanMinMessage;
78
    /**
79
     * @var string Validation error message used when a validated value is greater than maximum set in {@see $max}.
80
     */
81
    private string $greaterThanMaxMessage;
82
    /**
83
     * @var string Validation error message used when a validated value doesn't exactly match the one set in
84
     * {@see $exactly}.
85
     */
86
    private string $notExactlyMessage;
87
88
    /**
89
     * Initializes countable limit related properties and runs checks for required, mutually exclusive properties and
90
     * their allowed values (including dependency on each other).
91
     *
92
     * @param int|null $min Minimum limit ({@see $min}).
93
     * @param int|null $max Maximum limit ({@see $max}).
94
     * @param int|null $exactly "Exactly" number ({@see $exactly}).
95
     * @param string $lessThanMinMessage "Less than minimum" validation error message ({@see $lessThanMinMessage}).
96
     * @param string $greaterThanMinMessage "Greater than maximum" validation error message
97
     * ({@see $greaterThanMinMessage}).
98
     * @param string $notExactlyMessage "Not exactly" validation error message ({@see $notExactlyMessage}).
99
     */
100
    private function initCountableLimitProperties(
101
        int|null $min,
102
        int|null $max,
103
        int|null $exactly,
104
        string $lessThanMinMessage,
105
        string $greaterThanMinMessage,
106
        string $notExactlyMessage
107
    ): void {
108
        $this->min = $min;
109
        $this->max = $max;
110
        $this->exactly = $exactly;
111
        $this->lessThanMinMessage = $lessThanMinMessage;
112
        $this->greaterThanMaxMessage = $greaterThanMinMessage;
113
        $this->notExactlyMessage = $notExactlyMessage;
114
115
        if ($this->min === null && $this->max === null && $this->exactly === null) {
116
            throw new InvalidArgumentException(
117
                'At least one of these attributes must be specified: $min, $max, $exactly.'
118
            );
119
        }
120
121
        if (($this->min !== null || $this->max !== null) && $this->exactly !== null) {
122
            throw new InvalidArgumentException('$exactly is mutually exclusive with $min and $max.');
123
        }
124
125
        if (
126
            ($this->min !== null && $this->min < 0) ||
127
            ($this->max !== null && $this->max < 0) ||
128
            ($this->exactly !== null && $this->exactly < 0)
129
        ) {
130
            throw new InvalidArgumentException('Only positive or zero values are allowed.');
131
        }
132
133
        if ($this->min !== null && $this->max !== null) {
134
            if ($this->min > $this->max) {
135
                throw new InvalidArgumentException('$min must be lower than $max.');
136
            }
137
138
            if ($this->min === $this->max) {
139
                throw new InvalidArgumentException('Use $exactly instead.');
140
            }
141
        }
142
    }
143
144
    /**
145
     * A getter for {@see $min} property.
146
     *
147
     * @return int|null A number representing minimum boundary. `null` means no lower bound.
148
     */
149
    public function getMin(): int|null
150
    {
151
        return $this->min;
152
    }
153
154
    /**
155
     * A getter for {@see $max property}.
156
     *
157
     * @return int|null A number representing maximum boundary. `null` means no upper bound.
158
     */
159
    public function getMax(): int|null
160
    {
161
        return $this->max;
162
    }
163
164
    /**
165
     * A getter for {@see $exactly} property.
166
     *
167
     * @return int|null A number representing "exactly" value. `null` means no strict comparison so lower / upper limits /
168
     * both must be set.
169
     */
170
    public function getExactly(): int|null
171
    {
172
        return $this->exactly;
173
    }
174
175
    /**
176
     * A getter for {@see $lessThanMinMessage} property.
177
     *
178
     * @return string Validation error message.
179
     */
180
    public function getLessThanMinMessage(): string
181
    {
182
        return $this->lessThanMinMessage;
183
    }
184
185
    /**
186
     * A getter for {@see $greaterThanMaxMessage} property.
187
     *
188
     * @return string Validation error message.
189
     */
190
    public function getGreaterThanMaxMessage(): string
191
    {
192
        return $this->greaterThanMaxMessage;
193
    }
194
195
    /**
196
     * A getter for {@see $notExactlyMessage} property.
197
     *
198
     * @return string Validation error message.
199
     */
200
    public function getNotExactlyMessage(): string
201
    {
202
        return $this->notExactlyMessage;
203
    }
204
205
    /**
206
     * Limit related options intended to be merged with other rule options.
207
     *
208
     * @return array<string, mixed> A map between property name and property value.
209
     */
210
    #[ArrayShape([
211
        'min' => 'int|null',
212
        'max' => 'int|null',
213
        'exactly' => 'int|null',
214
        'lessThanMinMessage' => 'array',
215
        'greaterThanMaxMessage' => 'array',
216
        'notExactlyMessage' => 'array',
217
    ])]
218
    private function getLimitOptions(): array
219
    {
220
        return [
221
            'min' => $this->min,
222
            'max' => $this->max,
223
            'exactly' => $this->exactly,
224
            'lessThanMinMessage' => [
225
                'template' => $this->lessThanMinMessage,
226
                'parameters' => ['min' => $this->min],
227
            ],
228
            'greaterThanMaxMessage' => [
229
                'template' => $this->greaterThanMaxMessage,
230
                'parameters' => ['max' => $this->max],
231
            ],
232
            'notExactlyMessage' => [
233
                'template' => $this->notExactlyMessage,
234
                'parameters' => ['exactly' => $this->exactly],
235
            ],
236
        ];
237
    }
238
}
239