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
Pull Request — master (#923)
by lee
03:57
created

Ip::parseRange()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 11

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 17
cts 17
cp 1
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 17
nc 11
nop 1
crap 11

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of Respect/Validation.
5
 *
6
 * (c) Alexandre Gomes Gaigalas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the "LICENSE.md"
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Respect\Validation\Rules;
15
16
use Respect\Validation\Exceptions\ComponentException;
17
18
class Ip extends AbstractRule
19
{
20
    public $ipOptions;
21
22
    public $networkRange;
23
24 41
    public function __construct($ipOptions = null)
25
    {
26 41
        if (is_int($ipOptions)) {
27 1
            $this->ipOptions = $ipOptions;
28
29 1
            return;
30
        }
31
32 40
        $this->networkRange = $this->parseRange($ipOptions);
33 32
    }
34
35 40
    protected function parseRange($input)
36
    {
37 40
        if (null === $input || '*' == $input || '*.*.*.*' == $input
38 40
            || '0.0.0.0-255.255.255.255' == $input) {
39 9
            return;
40
        }
41
42 31
        $range = ['min' => null, 'max' => null, 'mask' => null];
43
44 31
        if (false !== mb_strpos($input, '-')) {
45 9
            list($range['min'], $range['max']) = explode('-', $input);
46 22
        } elseif (false !== mb_strpos($input, '*')) {
47 11
            $this->parseRangeUsingWildcards($input, $range);
48 11
        } elseif (false !== mb_strpos($input, '/')) {
49 9
            $this->parseRangeUsingCidr($input, $range);
50
        } else {
51 2
            throw new ComponentException('Invalid network range');
52
        }
53
54 26
        if (!$this->verifyAddress($range['min'])) {
55 1
            throw new ComponentException('Invalid network range');
56
        }
57
58 25
        if (isset($range['max']) && !$this->verifyAddress($range['max'])) {
59 2
            throw new ComponentException('Invalid network range');
60
        }
61
62 23
        return $range;
63
    }
64
65 20
    protected function fillAddress(&$input, $char = '*'): void
66
    {
67 20
        while (mb_substr_count($input, '.') < 3) {
68 5
            $input .= '.'.$char;
69
        }
70 20
    }
71
72 11
    protected function parseRangeUsingWildcards($input, &$range): void
73
    {
74 11
        $this->fillAddress($input);
75
76 11
        $range['min'] = strtr($input, '*', '0');
77 11
        $range['max'] = str_replace('*', '255', $input);
78 11
    }
79
80 9
    protected function parseRangeUsingCidr($input, &$range): void
81
    {
82 9
        $input = explode('/', $input);
83 9
        $this->fillAddress($input[0], '0');
84
85 9
        $range['min'] = $input[0];
86 9
        $isAddressMask = false !== mb_strpos($input[1], '.');
87
88 9
        if ($isAddressMask && $this->verifyAddress($input[1])) {
89 2
            $range['mask'] = sprintf('%032b', ip2long($input[1]));
90
91 2
            return;
92
        }
93
94 7
        if ($isAddressMask || $input[1] < 8 || $input[1] > 30) {
95 3
            throw new ComponentException('Invalid network mask');
96
        }
97
98 4
        $range['mask'] = sprintf('%032b', ip2long(long2ip(~(2 ** (32 - $input[1]) - 1))));
99 4
    }
100
101 33
    public function validate($input): bool
102
    {
103 33
        return $this->verifyAddress($input) && $this->verifyNetwork($input);
104
    }
105
106 38
    protected function verifyAddress($address)
107
    {
108 38
        return (bool) filter_var(
109 38
            $address,
110 38
            FILTER_VALIDATE_IP,
111
            [
112 38
                'flags' => $this->ipOptions,
113
            ]
114
        );
115
    }
116
117 27
    protected function verifyNetwork($input)
118
    {
119 27
        if (null === $this->networkRange) {
120 4
            return true;
121
        }
122
123 23
        if (isset($this->networkRange['mask'])) {
124 6
            return $this->belongsToSubnet($input);
125
        }
126
127 17
        $input = sprintf('%u', ip2long($input));
128
129 17
        return bccomp($input, sprintf('%u', ip2long($this->networkRange['min']))) >= 0
130 17
               && bccomp($input, sprintf('%u', ip2long($this->networkRange['max']))) <= 0;
131
    }
132
133 6
    protected function belongsToSubnet($input)
134
    {
135 6
        $range = $this->networkRange;
136 6
        $min = sprintf('%032b', ip2long($range['min']));
137 6
        $input = sprintf('%032b', ip2long($input));
138
139 6
        return ($input & $range['mask']) === ($min & $range['mask']);
140
    }
141
}
142