IpVN   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 3
dl 0
loc 97
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 3
A validate() 0 16 5
A getIpRanges() 0 22 4
A validateIpInRange() 0 12 4
A getIpV4Range() 0 10 2
A getIpV6Range() 0 10 2
A isSupportedVersion() 0 4 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