1<?php
2
3/*
4 * This file is part of Respect/Validation.
5 *
6 * (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
7 *
8 * For the full copyright and license information, please view the "LICENSE.md"
9 * file that was distributed with this source code.
10 */
11
12namespace Respect\Validation\Rules;
13
14use Respect\Validation\Exceptions\ComponentException;
15
16class Length extends AbstractRule
17{
18    public $minValue;
19    public $maxValue;
20    public $inclusive;
21
22    public function __construct($min = null, $max = null, $inclusive = true)
23    {
24        $this->minValue = $min;
25        $this->maxValue = $max;
26        $this->inclusive = $inclusive;
27        $paramValidator = new OneOf(new Numeric(), new NullType());
28        if (!$paramValidator->validate($min)) {
29            throw new ComponentException(
30                sprintf('%s is not a valid numeric length', $min)
31            );
32        }
33
34        if (!$paramValidator->validate($max)) {
35            throw new ComponentException(
36                sprintf('%s is not a valid numeric length', $max)
37            );
38        }
39
40        if (!is_null($min) && !is_null($max) && $min > $max) {
41            throw new ComponentException(
42                sprintf('%s cannot be less than %s for validation', $min, $max)
43            );
44        }
45    }
46
47    public function validate($input)
48    {
49        $length = $this->extractLength($input);
50
51        return $this->validateMin($length) && $this->validateMax($length);
52    }
53
54    protected function extractLength($input)
55    {
56        if (is_string($input)) {
57            return mb_strlen($input, mb_detect_encoding($input));
58        }
59
60        if (is_array($input) || $input instanceof \Countable) {
61            return count($input);
62        }
63
64        if (is_object($input)) {
65            return count(get_object_vars($input));
66        }
67
68        if (is_int($input)) {
69            return strlen((string)$input);
70        }
71
72        return false;
73    }
74
75    protected function validateMin($length)
76    {
77        if (is_null($this->minValue)) {
78            return true;
79        }
80
81        if ($this->inclusive) {
82            return $length >= $this->minValue;
83        }
84
85        return $length > $this->minValue;
86    }
87
88    protected function validateMax($length)
89    {
90        if (is_null($this->maxValue)) {
91            return true;
92        }
93
94        if ($this->inclusive) {
95            return $length <= $this->maxValue;
96        }
97
98        return $length < $this->maxValue;
99    }
100}
101