Completed
Push — master ( 6f8b0e...d86e0b )
by Vuong
01:49
created

IpVN::isSupportedVersion()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * @link https://github.com/phpviet/validation
4
 *
5
 * @copyright (c) PHP Viet
6
 * @license [MIT](https://opensource.org/licenses/MIT)
7
 */
8
9
namespace PHPViet\Validation\Rules;
10
11
use IPLib\Address\AddressInterface as IpInterface;
12
use IPLib\Address\Type as IpType;
13
use IPLib\Factory as IpFactory;
14
use Respect\Validation\Exceptions\ComponentException;
15
use Respect\Validation\Rules\AbstractRule;
16
17
/**
18
 * @author Vuong Minh <[email protected]>
19
 *
20
 * @since 1.0.0
21
 */
22
class IpVN extends AbstractRule
23
{
24
    const IPV4 = IpType::T_IPv4;
25
26
    const IPV6 = IpType::T_IPv6;
27
28
    public $version;
29
30
    public function __construct(?int $version = null)
31
    {
32
        if(null !== $version && !$this->isSupportedVersion($version)) {
33
            throw new ComponentException(sprintf('Only versions %d, %d are supported: %d given', self::IPV4, self::IPV6, $version));
34
        }
35
36
        $this->version = $version;
37
    }
38
39
    public function validate($input)
40
    {
41
        if (!$ip = IpFactory::addressFromString($input)) {
42
            return false;
43
        }
44
45
        if (($version = $ip->getAddressType()) !== $this->version && null !== $this->version) {
46
            return false;
47
        }
48
49
        if (!$ranges = $this->getIpRanges($input, $version)) {
50
            return false;
51
        }
52
53
        return $this->validateIpInRange($ip, $ranges);
54
    }
55
56
    protected function getIpRanges(string $ip, int $version): ?array
57
    {
58
        if (self::IPV4 === $version) {
59
            $keys = explode('.', $ip);
60
            $map = static::getIpV4Range();
61
        } else {
62
            $keys = explode(':', $ip);
63
            $map = static::getIpV6Range();
64
        }
65
66
        while (!is_null($key = array_shift($keys))) {
67
            if (isset($map[$key])) {
68
                $map = $map[$key];
69
70
                continue;
71
            }
72
73
            if (isset($map['range'])) {
74
                return $map['range'];
75
            }
76
77
            return null;
78
        }
79
    }
80
81
    protected function validateIpInRange(IpInterface $ip, array $ranges)
82
    {
83
        foreach ($ranges as $range) {
84
            [$begin, $end] = $range;
0 ignored issues
show
Bug introduced by
The variable $begin does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $end does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
85
86
            if (($subnet = IpFactory::rangeFromBoundaries($begin, $end)) && $subnet->contains($ip)) {
87
                return true;
88
            }
89
        }
90
91
        return false;
92
    }
93
94
    protected static function getIpV4Range(): array
95
    {
96
        static $range = null;
97
98
        if (null === $range) {
99
            $range = require __DIR__.'/../../resource/ip-v4-range.php';
100
        }
101
102
        return $range;
103
    }
104
105
    protected static function getIpV6Range(): array
106
    {
107
        static $range = null;
108
109
        if (null === $range) {
110
            $range = require __DIR__.'/../../resource/ip-v6-range.php';
111
        }
112
113
        return $range;
114
    }
115
116
    protected function isSupportedVersion(int $version): bool
117
    {
118
        return self::IPV4 === $version || self::IPV6 === $version;
119
    }
120
121
}
122