IpVN::getIpRanges()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.568
c 0
b 0
f 0
cc 4
nc 6
nop 2
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\Factory as IpFactory;
12
use IPLib\Address\Type as IpType;
13
use Respect\Validation\Rules\AbstractRule;
14
use IPLib\Address\AddressInterface as IpInterface;
15
use Respect\Validation\Exceptions\ComponentException;
16
17
/**
18
 * @author Vuong Minh <[email protected]>
19
 * @since 1.0.0
20
 */
21
class IpVN extends AbstractRule
22
{
23
    const IPV4 = IpType::T_IPv4;
24
25
    const IPV6 = IpType::T_IPv6;
26
27
    public $version;
28
29
    public function __construct(?int $version = null)
30
    {
31
        if (null !== $version && ! $this->isSupportedVersion($version)) {
32
            throw new ComponentException(sprintf('Only versions %d, %d are supported: %d given', self::IPV4, self::IPV6, $version));
33
        }
34
35
        $this->version = $version;
36
    }
37
38
    public function validate($input): bool
39
    {
40
        if (! $ip = IpFactory::addressFromString($input)) {
41
            return false;
42
        }
43
44
        if (($version = $ip->getAddressType()) !== $this->version && null !== $this->version) {
45
            return false;
46
        }
47
48
        if (! $ranges = $this->getIpRanges($input, $version)) {
49
            return false;
50
        }
51
52
        return $this->validateIpInRange($ip, $ranges);
53
    }
54
55
    protected function getIpRanges(string $ip, int $version): ?array
56
    {
57
        if (self::IPV4 === $version) {
58
            $keys = explode('.', $ip);
59
            $map = static::getIpV4Range();
60
        } else {
61
            $keys = explode(':', $ip);
62
            $map = static::getIpV6Range();
63
        }
64
65
        while (! is_null($key = array_shift($keys))) {
66
            if (isset($map[$key])) {
67
                $map = $map[$key];
68
69
                continue;
70
            }
71
72
            return $map['range'] ?? null;
73
        }
74
75
        return null;
76
    }
77
78
    protected function validateIpInRange(IpInterface $ip, array $ranges): bool
79
    {
80
        foreach ($ranges as $range) {
81
            [$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...
82
83
            if (($subnet = IpFactory::rangeFromBoundaries($begin, $end)) && $subnet->contains($ip)) {
84
                return true;
85
            }
86
        }
87
88
        return false;
89
    }
90
91
    protected static function getIpV4Range(): array
92
    {
93
        static $range = null;
94
95
        if (null === $range) {
96
            $range = require __DIR__.'/../../resources/ip-v4-range.php';
97
        }
98
99
        return $range;
100
    }
101
102
    protected static function getIpV6Range(): array
103
    {
104
        static $range = null;
105
106
        if (null === $range) {
107
            $range = require __DIR__.'/../../resources/ip-v6-range.php';
108
        }
109
110
        return $range;
111
    }
112
113
    protected function isSupportedVersion(int $version): bool
114
    {
115
        return self::IPV4 === $version || self::IPV6 === $version;
116
    }
117
}
118