Passed
Pull Request — master (#175)
by Alexander
02:36
created

Number::min()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A Number::getNotANumberMessage() 0 3 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Attribute;
8
use Yiisoft\Strings\NumericHelper;
9
use Yiisoft\Validator\FormatterInterface;
10
use Yiisoft\Validator\Result;
11
use Yiisoft\Validator\Rule;
12
use Yiisoft\Validator\ValidationContext;
13
14
/**
15
 * NumberValidator validates that the attribute value is a number.
16
 *
17
 * The format of the number must match the regular expression specified in {@see Number::$integerPattern}
18
 * or {@see Number::$numberPattern}. Optionally, you may configure the {@see Number::min()} and {@see Number::max()}
19
 * to ensure the number is within certain range.
20
 */
21
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
22
final class Number extends Rule
23
{
24 39
    public function __construct(
25
        /**
26
         * @var bool whether the attribute value can only be an integer. Defaults to false.
27
         */
28
        private bool $asInteger = false,
29
        /**
30
         * @var float|int lower limit of the number. Defaults to null, meaning no lower limit.
31
         *
32
         * @see tooSmallMessage for the customized message used when the number is too small.
33
         */
34
        private $min = null,
35
        /**
36
         * @var float|int upper limit of the number. Defaults to null, meaning no upper limit.
37
         *
38
         * @see tooBigMessage for the customized message used when the number is too big.
39
         */
40
        private $max = null,
41
        /**
42
         * @var string user-defined error message used when the value is smaller than {@link $min}.
43
         */
44
        private string $tooSmallMessage = 'Value must be no less than {min}.',
45
        /**
46
         * @var string user-defined error message used when the value is bigger than {@link $max}.
47
         */
48
        private string $tooBigMessage = 'Value must be no greater than {max}.',
49
        /**
50
         * @var string the regular expression for matching integers.
51
         */
52
        private string $integerPattern = '/^\s*[+-]?\d+\s*$/',
53
        /**
54
         * @var string the regular expression for matching numbers. It defaults to a pattern
55
         * that matches floating numbers with optional exponential part (e.g. -1.23e-10).
56
         */
57
        private string $numberPattern = '/^\s*[-+]?\d*\.?\d+([eE][-+]?\d+)?\s*$/',
58
        ?FormatterInterface $formatter = null,
59
        bool $skipOnEmpty = false,
60
        bool $skipOnError = false,
61
        /**
62
         * @var callable|null
63
         */
64
        $when = null,
65
    ) {
66 39
        parent::__construct($formatter, $skipOnEmpty, $skipOnError, $when);
67
    }
68
69 39
    protected function validateValue($value, ?ValidationContext $context = null): Result
70
    {
71 39
        $result = new Result();
72
73 39
        if (is_bool($value) || !is_scalar($value)) {
74 5
            $result->addError($this->formatMessage($this->getNotANumberMessage(), ['value' => $value]));
75 5
            return $result;
76
        }
77
78 34
        $pattern = $this->asInteger ? $this->integerPattern : $this->numberPattern;
79
80 34
        if (!preg_match($pattern, NumericHelper::normalize($value))) {
81 9
            $result->addError($this->formatMessage($this->getNotANumberMessage(), ['value' => $value]));
82 31
        } elseif ($this->min !== null && $value < $this->min) {
83 14
            $result->addError($this->formatMessage($this->tooSmallMessage, ['min' => $this->min]));
84 25
        } elseif ($this->max !== null && $value > $this->max) {
85 9
            $result->addError($this->formatMessage($this->tooBigMessage, ['max' => $this->max]));
86
        }
87
88 34
        return $result;
89
    }
90
91 23
    private function getNotANumberMessage(): string
92
    {
93 23
        return $this->asInteger ? 'Value must be an integer.' : 'Value must be a number.';
94
    }
95
96 9
    public function getOptions(): array
97
    {
98 9
        return array_merge(
99 9
            parent::getOptions(),
100
            [
101 9
                'asInteger' => $this->asInteger,
102 9
                'min' => $this->min,
103 9
                'max' => $this->max,
104 9
                'notANumberMessage' => $this->formatMessage($this->getNotANumberMessage()),
105 9
                'tooSmallMessage' => $this->formatMessage($this->tooSmallMessage, ['min' => $this->min]),
106 9
                'tooBigMessage' => $this->formatMessage($this->tooBigMessage, ['max' => $this->max]),
107
            ],
108
        );
109
    }
110
}
111