Completed
Push — master ( 59b106...2838f8 )
by Peter
03:34
created

IPv4Network   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 220
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 4

Test Coverage

Coverage 72.34%

Importance

Changes 0
Metric Value
wmc 18
c 0
b 0
f 0
lcom 4
cbo 4
dl 0
loc 220
ccs 34
cts 47
cp 0.7234
rs 10

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A fromCIDR() 0 4 1
A fromMask() 0 4 1
A fromString() 0 11 2
A equal() 0 4 1
A contains() 0 4 1
A intersects() 0 4 1
A abuts() 0 4 1
A iterate() 0 10 2
A start() 0 4 1
A end() 0 4 1
A mask() 0 4 1
A cidr() 0 4 1
A startPoint() 0 4 1
A endPoint() 0 4 1
A __toString() 0 4 1
1
<?php
2
3
/**
4
 * GpsLab component.
5
 *
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2016, Peter Gribanov
8
 * @license   http://opensource.org/licenses/MIT
9
 */
10
11
namespace GpsLab\Component\Interval\IPv4Network;
12
13
use GpsLab\Component\Interval\Exception\InvalidIntervalFormatException;
14
use GpsLab\Component\Interval\IntervalInterface;
15
16
class IPv4Network implements IntervalInterface
17
{
18
    /**
19
     * @var string
20
     */
21
    const REGEXP = '/^
22
        \s*
23
        (?<ip>\d{1,3}(?:\.\d{1,3}(?:\.\d{1,3}(?:\.\d{1,3})?)?)?) # IP supported compact format
24
        \/                                                       # separator
25
        (?<cidr>\d{1,2})                                         # CIDR bit
26
        \s*
27
    $/x';
28
29
    /**
30
     * @var IPv4NetworkPoint
31
     */
32
    private $start;
33
34
    /**
35
     * @var IPv4NetworkPoint
36
     */
37
    private $end;
38
39
    /**
40
     * @var IPv4NetworkMask
41
     */
42
    private $mask;
43
44
    /**
45
     * @var IPv4NetworkComparator
46
     */
47
    private $comparator;
48
49
    /**
50
     * @param IPv4NetworkPoint $ip
51
     * @param IPv4NetworkMask $mask
52
     */
53 27
    private function __construct(IPv4NetworkPoint $ip, IPv4NetworkMask $mask)
54
    {
55 27
        $this->start = $ip;
56 27
        $this->mask = $mask;
57 27
        $this->end = new IPv4NetworkPoint(long2ip(
58 27
            $ip->value() + 2 ** (32 - $mask->cidr()) - 1
59 27
        ));
60 27
        $this->comparator = new IPv4NetworkComparator($this);
61 27
    }
62
63
    /**
64
     * @param string $ip
65
     * @param int $cidr
66
     *
67
     * @return IPv4Network
68
     */
69 24
    public static function fromCIDR($ip, $cidr)
70
    {
71 24
        return new self(new IPv4NetworkPoint($ip), IPv4NetworkMask::fromCIDR($cidr));
72
    }
73
74
    /**
75
     * @param string $ip
76
     * @param string $mask
77
     *
78
     * @return IPv4Network
79
     */
80 3
    public static function fromMask($ip, $mask)
81
    {
82 3
        return new self(new IPv4NetworkPoint($ip), IPv4NetworkMask::fromIP($mask));
83
    }
84
85
    /**
86
     * Create network from string.
87
     *
88
     * Example formats of network:
89
     *   10.0.0.0/8
90
     *   172.16.0.0/12
91
     *   192.168.0.0/16
92
     *
93
     * Supported compact format:
94
     *   10/8
95
     *   172.16/12
96
     *   192.168/16
97
     *
98
     * Spaces are ignored in format.
99
     *
100
     * @param string $string
101
     *
102
     * @return self
103
     */
104 21
    public static function fromString($string)
105
    {
106 21
        if (!preg_match(self::REGEXP, $string, $match)) {
107
            throw InvalidIntervalFormatException::create('0.0.0.0/32', $string);
108
        }
109
110
        // fill IP compact format
111 21
        $match['ip'] .= str_repeat('.0', 3 - substr_count($match['ip'], '.'));
112
113 21
        return self::fromCIDR($match['ip'], $match['cidr']);
114
    }
115
116
    /**
117
     * Checks if this network is equal to the specified network.
118
     *
119
     * @param IPv4Network $network
120
     *
121
     * @return bool
122
     */
123
    public function equal(IPv4Network $network)
124
    {
125
        return $this->comparator->equal($network);
126
    }
127
128
    /**
129
     * Does this network contain the specified IP.
130
     *
131
     * @param string $point
132
     *
133
     * @return bool
134
     */
135 6
    public function contains($point)
136
    {
137 6
        return $this->comparator->contains(new IPv4NetworkPoint($point));
138
    }
139
140
    /**
141
     * Does this network intersect the specified network.
142
     *
143
     * @param IPv4Network $network
144
     *
145
     * @return bool
146
     */
147 3
    public function intersects(IPv4Network $network)
148
    {
149 3
        return $this->comparator->intersects($network);
150
    }
151
152
    /**
153
     * Does this network abut with the network specified.
154
     *
155
     * @param IPv4Network $network
156
     *
157
     * @return bool
158
     */
159
    public function abuts(IPv4Network $network)
160
    {
161
        return $this->comparator->abuts($network);
162
    }
163
164
    /**
165
     * @param int $step
166
     *
167
     * @return \Generator
168
     */
169
    public function iterate($step = 1)
170
    {
171
        $end = $this->endPoint()->value();
172
        $ip = $this->startPoint()->value();
173
174
        while ($ip < $end) {
175
            yield long2ip($ip);
176
            $ip += $step;
177
        }
178
    }
179
180
    /**
181
     * @return string
182
     */
183 16
    public function start()
184
    {
185 16
        return (string) $this->start;
186
    }
187
188
    /**
189
     * @return string
190
     */
191 16
    public function end()
192
    {
193 16
        return (string) $this->end;
194
    }
195
196
    /**
197
     * @return IPv4NetworkMask
198
     */
199 22
    public function mask()
200
    {
201 22
        return $this->mask;
202
    }
203
204
    /**
205
     * @return int
206
     */
207 16
    public function cidr()
208
    {
209 16
        return $this->mask->cidr();
210
    }
211
212
    /**
213
     * @return IPv4NetworkPoint
214
     */
215 12
    public function startPoint()
216
    {
217 12
        return $this->start;
218
    }
219
220
    /**
221
     * @return IPv4NetworkPoint
222
     */
223 6
    public function endPoint()
224
    {
225 6
        return $this->end;
226
    }
227
228
    /**
229
     * @return string
230
     */
231 1
    public function __toString()
232
    {
233 1
        return $this->start . '/' . $this->mask->cidr();
234
    }
235
}
236