Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Push — master ( 77a1c0...f3db91 )
by Michele
27s queued 11s
created

Subnet::getSize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 7
Ratio 87.5 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 7
loc 8
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace IPLib\Range;
4
5
use IPLib\Address\AddressInterface;
6
use IPLib\Address\IPv4;
7
use IPLib\Address\IPv6;
8
use IPLib\Address\Type as AddressType;
9
use IPLib\Factory;
10
11
/**
12
 * Represents an address range in subnet format (eg CIDR).
13
 *
14
 * @example 127.0.0.1/32
15
 * @example ::/8
16
 */
17
class Subnet extends AbstractRange
18
{
19
    /**
20
     * Starting address of the range.
21
     *
22
     * @var \IPLib\Address\AddressInterface
23
     */
24
    protected $fromAddress;
25
26
    /**
27
     * Final address of the range.
28
     *
29
     * @var \IPLib\Address\AddressInterface
30
     */
31
    protected $toAddress;
32
33
    /**
34
     * Number of the same bits of the range.
35
     *
36
     * @var int
37
     */
38
    protected $networkPrefix;
39
40
    /**
41
     * The type of the range of this IP range.
42
     *
43
     * @var int|null
44
     */
45
    protected $rangeType;
46
47
    /**
48
     * The 6to4 address IPv6 address range.
49
     *
50
     * @var self|null
51
     */
52
    private static $sixToFour;
53
54
    /**
55
     * Initializes the instance.
56
     *
57
     * @param \IPLib\Address\AddressInterface $fromAddress
58
     * @param \IPLib\Address\AddressInterface $toAddress
59
     * @param int $networkPrefix
60
     *
61
     * @internal
62
     */
63 590
    public function __construct(AddressInterface $fromAddress, AddressInterface $toAddress, $networkPrefix)
64
    {
65 590
        $this->fromAddress = $fromAddress;
66 590
        $this->toAddress = $toAddress;
67 590
        $this->networkPrefix = $networkPrefix;
68 590
    }
69
70
    /**
71
     * {@inheritdoc}
72
     *
73
     * @see \IPLib\Range\RangeInterface::__toString()
74
     */
75 125
    public function __toString()
76
    {
77 125
        return $this->toString();
78
    }
79
80
    /**
81
     * Try get the range instance starting from its string representation.
82
     *
83
     * @param string|mixed $range
84
     * @param bool $supportNonDecimalIPv4 set to true to support parsing non decimal (that is, octal and hexadecimal) IPv4 addresses
85
     *
86
     * @return static|null
87
     */
88 667
    public static function fromString($range, $supportNonDecimalIPv4 = false)
89
    {
90 667
        if (!is_string($range)) {
91 3
            return null;
92
        }
93 664
        $parts = explode('/', $range);
94 664
        if (count($parts) !== 2) {
95 118
            return null;
96
        }
97 546
        $address = Factory::addressFromString($parts[0], true, true, $supportNonDecimalIPv4);
98 546
        if ($address === null) {
99 3
            return null;
100
        }
101 543
        if (!preg_match('/^[0-9]{1,9}$/', $parts[1])) {
102 2
            return null;
103
        }
104 541
        $networkPrefix = (int) $parts[1];
105 541
        $addressBytes = $address->getBytes();
106 541
        $totalBytes = count($addressBytes);
107 541
        $numDifferentBits = $totalBytes * 8 - $networkPrefix;
108 541
        if ($numDifferentBits < 0) {
109 2
            return null;
110
        }
111 539
        $numSameBytes = $networkPrefix >> 3;
112 539
        $sameBytes = array_slice($addressBytes, 0, $numSameBytes);
113 539
        $differentBytesStart = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 0);
114 539
        $differentBytesEnd = ($totalBytes === $numSameBytes) ? array() : array_fill(0, $totalBytes - $numSameBytes, 255);
115 539
        $startSameBits = $networkPrefix % 8;
116 539
        if ($startSameBits !== 0) {
117 373
            $varyingByte = $addressBytes[$numSameBytes];
118 373
            $differentBytesStart[0] = $varyingByte & bindec(str_pad(str_repeat('1', $startSameBits), 8, '0', STR_PAD_RIGHT));
119 373
            $differentBytesEnd[0] = $differentBytesStart[0] + bindec(str_repeat('1', 8 - $startSameBits));
120
        }
121
122 539
        return new static(
123 539
            Factory::addressFromBytes(array_merge($sameBytes, $differentBytesStart)),
124 539
            Factory::addressFromBytes(array_merge($sameBytes, $differentBytesEnd)),
125 539
            $networkPrefix
126
        );
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     *
132
     * @see \IPLib\Range\RangeInterface::toString()
133
     */
134 360
    public function toString($long = false)
135
    {
136 360
        return $this->fromAddress->toString($long) . '/' . $this->networkPrefix;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     *
142
     * @see \IPLib\Range\RangeInterface::getAddressType()
143
     */
144 508
    public function getAddressType()
145
    {
146 508
        return $this->fromAddress->getAddressType();
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     *
152
     * @see \IPLib\Range\RangeInterface::getStartAddress()
153
     */
154 85
    public function getStartAddress()
155
    {
156 85
        return $this->fromAddress;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     *
162
     * @see \IPLib\Range\RangeInterface::getEndAddress()
163
     */
164 5
    public function getEndAddress()
165
    {
166 5
        return $this->toAddress;
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     *
172
     * @see \IPLib\Range\RangeInterface::getComparableStartString()
173
     */
174 480
    public function getComparableStartString()
175
    {
176 480
        return $this->fromAddress->getComparableString();
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     *
182
     * @see \IPLib\Range\RangeInterface::getComparableEndString()
183
     */
184 479
    public function getComparableEndString()
185
    {
186 479
        return $this->toAddress->getComparableString();
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     *
192
     * @see \IPLib\Range\RangeInterface::asSubnet()
193
     */
194 56
    public function asSubnet()
195
    {
196 56
        return $this;
197
    }
198
199
    /**
200
     * Get the pattern (asterisk) representation (if applicable) of this range.
201
     *
202
     * @return \IPLib\Range\Pattern|null return NULL if this range can't be represented by a pattern notation
203
     */
204 56
    public function asPattern()
205
    {
206 56
        $address = $this->getStartAddress();
207 56
        $networkPrefix = $this->getNetworkPrefix();
208 56
        switch ($address->getAddressType()) {
209 View Code Duplication
            case AddressType::T_IPv4:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
210 18
                return $networkPrefix % 8 === 0 ? new Pattern($address, $address, 4 - $networkPrefix / 8) : null;
211 View Code Duplication
            case AddressType::T_IPv6:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212 38
                return $networkPrefix % 16 === 0 ? new Pattern($address, $address, 8 - $networkPrefix / 16) : null;
213
        }
214
    }
215
216
    /**
217
     * Get the 6to4 address IPv6 address range.
218
     *
219
     * @return self
220
     */
221 72
    public static function get6to4()
222
    {
223 72
        if (self::$sixToFour === null) {
224 1
            self::$sixToFour = self::fromString('2002::/16');
225
        }
226
227 72
        return self::$sixToFour;
228
    }
229
230
    /**
231
     * Get subnet prefix.
232
     *
233
     * @return int
234
     */
235 236
    public function getNetworkPrefix()
236
    {
237 236
        return $this->networkPrefix;
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     *
243
     * @see \IPLib\Range\RangeInterface::getSubnetMask()
244
     */
245 19
    public function getSubnetMask()
246
    {
247 19
        if ($this->getAddressType() !== AddressType::T_IPv4) {
248 1
            return null;
249
        }
250 18
        $bytes = array();
251 18
        $prefix = $this->getNetworkPrefix();
252 18
        while ($prefix >= 8) {
253 10
            $bytes[] = 255;
254 10
            $prefix -= 8;
255
        }
256 18
        if ($prefix !== 0) {
257 13
            $bytes[] = bindec(str_pad(str_repeat('1', $prefix), 8, '0'));
258
        }
259 18
        $bytes = array_pad($bytes, 4, 0);
260
261 18
        return IPv4::fromBytes($bytes);
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     *
267
     * @see \IPLib\Range\RangeInterface::getReverseDNSLookupName()
268
     */
269 24
    public function getReverseDNSLookupName()
270
    {
271 24
        switch ($this->getAddressType()) {
272 View Code Duplication
            case AddressType::T_IPv4:
273 9
                $unitSize = 8; // bytes
274 9
                $maxUnits = 4;
275 9
                $isHex = false;
276 9
                $rxUnit = '\d+';
277 9
                break;
278 View Code Duplication
            case AddressType::T_IPv6:
279 15
                $unitSize = 4; // nibbles
280 15
                $maxUnits = 32;
281 15
                $isHex = true;
282 15
                $rxUnit = '[0-9A-Fa-f]';
283 15
                break;
284
        }
285 24
        $totBits = $unitSize * $maxUnits;
286 24
        $prefixUnits = (int) ($this->networkPrefix / $unitSize);
287 24
        $extraBits = ($totBits - $this->networkPrefix) % $unitSize;
288 24
        if ($extraBits !== 0) {
289 5
            $prefixUnits += 1;
290
        }
291 24
        $numVariants = 1 << $extraBits;
292 24
        $result = array();
293 24
        $unitsToRemove = $maxUnits - $prefixUnits;
294 24
        $initialPointer = preg_replace("/^(({$rxUnit})\.){{$unitsToRemove}}/", '', $this->getStartAddress()->getReverseDNSLookupName());
295 24
        $chunks = explode('.', $initialPointer, 2);
296 24
        for ($index = 0; $index < $numVariants; $index++) {
297 24
            if ($index !== 0) {
298 5
                $chunks[0] = $isHex ? dechex(1 + hexdec($chunks[0])) : (string) (1 + (int) $chunks[0]);
299
            }
300 24
            $result[] = implode('.', $chunks);
301
        }
302
303 24
        return $result;
304
    }
305
306
    /**
307
     * {@inheritdoc}
308
     *
309
     * @see \IPLib\Range\RangeInterface::getSize()
310
     */
311 View Code Duplication
    public function getSize()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
312
    {
313
        $fromAddress = $this->fromAddress;
314
        $maxPrefix = $fromAddress::getNumberOfBits();
315
        $prefix = $this->getNetworkPrefix();
316
317
        return pow(2, ($maxPrefix - $prefix));
318
    }
319
}
320