Passed
Pull Request — master (#81)
by Def
04:20
created

Number::isNotNumber()   A

Complexity

Conditions 6
Paths 10

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 3
nc 10
nop 1
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 42
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Yiisoft\Strings\NumericHelper;
8
use Yiisoft\Validator\Rule;
9
use Yiisoft\Validator\Result;
10
use Yiisoft\Validator\DataSetInterface;
11
12
/**
13
 * NumberValidator validates that the attribute value is a number.
14
 *
15
 * The format of the number must match the regular expression specified in [[integerPattern]] or [[numberPattern]].
16
 * Optionally, you may configure the [[max]] and [[min]] properties to ensure the number
17
 * is within certain range.
18
 */
19
class Number extends Rule
20
{
21
    /**
22
     * @var bool whether the attribute value can only be an integer. Defaults to false.
23
     */
24
    private bool $asInteger = false;
25
    /**
26
     * @var int|float upper limit of the number. Defaults to null, meaning no upper limit.
27
     * @see tooBigMessage for the customized message used when the number is too big.
28
     */
29
    private $max;
30
    /**
31
     * @var int|float lower limit of the number. Defaults to null, meaning no lower limit.
32
     * @see tooSmallMessage for the customized message used when the number is too small.
33
     */
34
    private $min;
35
    /**
36
     * @var string user-defined error message used when the value is bigger than {@link $max}.
37
     */
38
    private string $tooBigMessage = 'Value must be no greater than {max}.';
39
    /**
40
     * @var string user-defined error message used when the value is smaller than {@link $min}.
41
     */
42
    private string $tooSmallMessage = 'Value must be no less than {min}.';
43
    /**
44
     * @var string the regular expression for matching integers.
45
     */
46
    private string $integerPattern = '/^\s*[+-]?\d+\s*$/';
47
    /**
48
     * @var string the regular expression for matching numbers. It defaults to a pattern
49
     * that matches floating numbers with optional exponential part (e.g. -1.23e-10).
50
     */
51
    private string $numberPattern = '/^\s*[-+]?\d*\.?\d+([eE][-+]?\d+)?\s*$/';
52
53 32
    protected function validateValue($value, DataSetInterface $dataSet = null): Result
54
    {
55 32
        $result = new Result();
56
57 32
        if (!is_scalar($value)) {
58 5
            $result->addError($this->translateMessage($this->getNotANumberMessage(), ['value' => $value]));
59 5
            return $result;
60
        }
61
62 27
        $pattern = $this->asInteger ? $this->integerPattern : $this->numberPattern;
63
64 27
        if (!preg_match($pattern, NumericHelper::normalize($value))) {
65 9
            $result->addError($this->translateMessage($this->getNotANumberMessage(), ['value' => $value]));
66 24
        } elseif ($this->min !== null && $value < $this->min) {
67 10
            $result->addError($this->translateMessage($this->tooSmallMessage, ['min' => $this->min]));
68 20
        } elseif ($this->max !== null && $value > $this->max) {
69 7
            $result->addError($this->translateMessage($this->tooBigMessage, ['max' => $this->max]));
70
        }
71
72 27
        return $result;
73
    }
74
75 11
    public function integer(): self
76
    {
77 11
        $new = clone $this;
78 11
        $new->asInteger = true;
79 11
        return $new;
80
    }
81
82 15
    public function min($value): self
83
    {
84 15
        $new = clone $this;
85 15
        $new->min = $value;
86 15
        return $new;
87
    }
88
89 14
    public function max($value): self
90
    {
91 14
        $new = clone $this;
92 14
        $new->max = $value;
93 14
        return $new;
94
    }
95
96 1
    public function tooSmallMessage(string $message): self
97
    {
98 1
        $new = clone $this;
99 1
        $new->tooSmallMessage = $message;
100 1
        return $new;
101
    }
102
103
    public function tooBigMessage(string $message): self
104
    {
105
        $new = clone $this;
106
        $new->tooBigMessage = $message;
107
        return $new;
108
    }
109
110 22
    private function getNotANumberMessage(): string
111
    {
112 22
        if ($this->asInteger === true) {
113 9
            return 'Value must be an integer.';
114
        }
115 14
        return 'Value must be a number.';
116
    }
117
118
    /**
119
     * @param mixed $value the data value to be checked.
120
     */
121
    private function isNotNumber($value): bool
0 ignored issues
show
Unused Code introduced by
The method isNotNumber() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
122
    {
123
        return is_array($value)
124
            || (is_object($value) && !method_exists($value, '__toString'))
125
            || (!is_object($value) && !is_scalar($value) && $value !== null);
126
    }
127
128
    /**
129
     * @inheritDoc
130
     * @return string
131
     */
132 4
    public function getName(): string
133
    {
134 4
        return 'number';
135
    }
136
137
    /**
138
     * @inheritDoc
139
     * @return array
140
     */
141 8
    public function getOptions(): array
142
    {
143 8
        return array_merge(
144 8
            ['notANumberMessage' => $this->translateMessage($this->getNotANumberMessage())],
145 8
            $this->asInteger ? ['asInteger' => true] : [],
146 8
            $this->min !== null ? ['min' => $this->min, 'tooSmallMessage' => $this->translateMessage($this->tooSmallMessage, ['min' => $this->min])] : [],
147 8
            $this->max !== null ? ['max' => $this->max, 'tooBigMessage' => $this->translateMessage($this->tooBigMessage, ['max' => $this->max])] : [],
148 8
            parent::getOptions()
149
        );
150
    }
151
}
152