Test Failed
Pull Request — master (#222)
by Rustam
02:30
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 19
    use RuleNameTrait;
25
26
    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 19
    ) {
70 1
        if (!$this->min && !$this->max && !$this->exactly) {
71
            throw new InvalidArgumentException(
72
                'At least one of these attributes must be specified: $min, $max, $exactly.'
73
            );
74
        }
75 18
76 3
        if ($this->exactly && ($this->min || $this->max)) {
77
            throw new InvalidArgumentException('$exactly is mutually exclusive with $min and $max.');
78
        }
79 15
80 1
        if ($this->min && $this->max && $this->min === $this->max) {
81
            throw new InvalidArgumentException('Use $exactly instead.');
82
        }
83 14
    }
84
85
    /**
86 19
     * @return int|null
87
     */
88 19
    public function getMin(): ?int
89
    {
90 19
        return $this->min;
91 6
    }
92
93 6
    /**
94
     * @return int|null
95
     */
96 13
    public function getMax(): ?int
97
    {
98 13
        return $this->max;
99 1
    }
100 1
101
    /**
102 1
     * @return int|null
103
     */
104
    public function getExactly(): ?int
105 12
    {
106 3
        return $this->exactly;
107 3
    }
108
109
    /**
110 12
     * @return string
111 2
     */
112 2
    public function getMessage(): string
113
    {
114
        return $this->message;
115 12
    }
116
117
    /**
118 1
     * @return string
119
     */
120 1
    public function getTooFewItemsMessage(): string
121 1
    {
122 1
        return $this->tooFewItemsMessage;
123 1
    }
124 1
125 1
    /**
126 1
     * @return string
127 1
     */
128
    public function getTooManyItemsMessage(): string
129
    {
130
        return $this->tooManyItemsMessage;
131
    }
132
133
    /**
134
     * @return string
135
     */
136
    public function getNotExactlyMessage(): string
137
    {
138
        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
    #[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
            'min' => $this->min,
180
            'max' => $this->max,
181
            'exactly' => $this->exactly,
182
            'message' => [
183
                'message' => $this->message,
184
            ],
185
            'tooFewItemsMessage' => [
186
                'message' => $this->tooFewItemsMessage,
187
                'parameters' => ['min' => $this->min],
188
            ],
189
            'tooManyItemsMessage' => [
190
                'message' => $this->tooManyItemsMessage,
191
                'parameters' => ['max' => $this->max],
192
            ],
193
            'notExactlyMessage' => [
194
                'message' => $this->notExactlyMessage,
195
                'parameters' => ['exactly' => $this->exactly],
196
            ],
197
            'skipOnEmpty' => $this->skipOnEmpty,
198
            'skipOnError' => $this->skipOnError,
199
        ];
200
    }
201
}
202