Passed
Pull Request — master (#222)
by Alexander
02:58
created

Count::validateValue()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 16
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 30
ccs 17
cts 17
cp 1
crap 8
rs 8.4444
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Attribute;
8
use Closure;
9
use Countable;
10
use InvalidArgumentException;
11
use JetBrains\PhpStorm\ArrayShape;
12
use Yiisoft\Validator\Rule\Trait\RuleNameTrait;
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_TRAIT, expecting T_STRING or '{' on line 12 at column 27
Loading history...
13
use Yiisoft\Validator\Rule\Trait\HandlerClassNameTrait;
14
use Yiisoft\Validator\ParametrizedRuleInterface;
15
16
/**
17
 * Validates that the value contains certain number of items. Can be applied to arrays or classes implementing
18
 * {@see Countable} interface.
19
 */
20
#[Attribute(Attribute::TARGET_PROPERTY)]
21
final class Count implements ParametrizedRuleInterface
22
{
23
    use HandlerClassNameTrait;
24
    use RuleNameTrait;
25
26 6
    public function __construct(
27
        /**
28
         * @var int|null minimum number of items. null means no minimum number limit.
29
         *
30
         * @see $tooFewItemsMessage for the customized message for a value with too few items.
31
         */
32
        private ?int $min = null,
33
        /**
34
         * @var int|null maximum number of items. null means no maximum number limit.
35
         *
36
         * @see $tooManyItemsMessage for the customized message for a value wuth too many items.
37
         */
38
        private ?int $max = null,
39
        /**
40
         * @var int|null exact number of items. null means no strict comparison. Mutually exclusive with {@see $min} and
41
         * {@see $max}.
42
         */
43
        private ?int $exactly = null,
44
        /**
45
         * @var string user-defined error message used when the value is neither an array nor implementing
46
         * {@see \Countable} interface.
47
         *
48
         * @see Countable
49
         */
50
        private string $message = 'This value must be an array or implement \Countable interface.',
51
        /**
52
         * @var string user-defined error message used when the number of items is smaller than {@see $min}.
53
         */
54
        private string $tooFewItemsMessage = 'This value must contain at least {min, number} ' .
55
        '{min, plural, one{item} other{items}}.',
56
        /**
57
         * @var string user-defined error message used when the number of items is greater than {@see $max}.
58
         */
59
        private string $tooManyItemsMessage = 'This value must contain at most {max, number} ' .
60
        '{max, plural, one{item} other{items}}.',
61
        /**
62
         * @var string user-defined error message used when the number of items does not equal {@see $exactly}.
63
         */
64
        private string $notExactlyMessage = 'This value must contain exactly {max, number} ' .
65
        '{max, plural, one{item} other{items}}.',
66
        private bool $skipOnEmpty = false,
67
        private bool $skipOnError = false,
68
        private ?Closure $when = null,
69
    ) {
70 6
        if (!$this->min && !$this->max && !$this->exactly) {
71 1
            throw new InvalidArgumentException(
72
                'At least one of these attributes must be specified: $min, $max, $exactly.'
73
            );
74
        }
75
76 5
        if ($this->exactly && ($this->min || $this->max)) {
77 3
            throw new InvalidArgumentException('$exactly is mutually exclusive with $min and $max.');
78
        }
79
80 2
        if ($this->min && $this->max && $this->min === $this->max) {
81 1
            throw new InvalidArgumentException('Use $exactly instead.');
82
        }
83
    }
84
85
    /**
86
     * @return int|null
87
     */
88 18
    public function getMin(): ?int
89
    {
90 18
        return $this->min;
91
    }
92
93
    /**
94
     * @return int|null
95
     */
96 18
    public function getMax(): ?int
97
    {
98 18
        return $this->max;
99
    }
100
101
    /**
102
     * @return int|null
103
     */
104 19
    public function getExactly(): ?int
105
    {
106 19
        return $this->exactly;
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    public function getMessage(): string
113
    {
114
        return $this->message;
115
    }
116
117
    /**
118
     * @return string
119
     */
120 9
    public function getTooFewItemsMessage(): string
121
    {
122 9
        return $this->tooFewItemsMessage;
123
    }
124
125
    /**
126
     * @return string
127
     */
128 2
    public function getTooManyItemsMessage(): string
129
    {
130 2
        return $this->tooManyItemsMessage;
131
    }
132
133
    /**
134
     * @return string
135
     */
136 1
    public function getNotExactlyMessage(): string
137
    {
138 1
        return $this->notExactlyMessage;
139
    }
140
141
    /**
142
     * @return bool
143
     */
144
    public function isSkipOnEmpty(): bool
145
    {
146
        return $this->skipOnEmpty;
147
    }
148
149
    /**
150
     * @return bool
151
     */
152
    public function isSkipOnError(): bool
153
    {
154
        return $this->skipOnError;
155
    }
156
157
    /**
158
     * @return Closure|null
159
     */
160
    public function getWhen(): ?Closure
161
    {
162
        return $this->when;
163
    }
164
165 1
    #[ArrayShape([
166
        'min' => 'int|null',
167
        'max' => 'int|null',
168
        'exactly' => 'int|null',
169
        'message' => 'string[]',
170
        'tooFewItemsMessage' => 'array',
171
        'tooManyItemsMessage' => 'array',
172
        'notExactlyMessage' => 'array',
173
        'skipOnEmpty' => 'bool',
174
        'skipOnError' => 'bool',
175
    ])]
176
    public function getOptions(): array
177
    {
178
        return [
179 1
            'min' => $this->min,
180 1
            'max' => $this->max,
181 1
            'exactly' => $this->exactly,
182
            'message' => [
183 1
                'message' => $this->message,
184
            ],
185
            'tooFewItemsMessage' => [
186 1
                'message' => $this->tooFewItemsMessage,
187 1
                'parameters' => ['min' => $this->min],
188
            ],
189
            'tooManyItemsMessage' => [
190 1
                'message' => $this->tooManyItemsMessage,
191 1
                'parameters' => ['max' => $this->max],
192
            ],
193
            'notExactlyMessage' => [
194 1
                'message' => $this->notExactlyMessage,
195 1
                'parameters' => ['exactly' => $this->exactly],
196
            ],
197 1
            'skipOnEmpty' => $this->skipOnEmpty,
198 1
            'skipOnError' => $this->skipOnError,
199
        ];
200
    }
201
}
202