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 (#1034)
by Henrique
02:29
created

Ip::parseRange()   B

Complexity

Conditions 11
Paths 11

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 11.0245

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 16
cts 17
cp 0.9412
rs 7.3166
c 0
b 0
f 0
cc 11
nc 11
nop 1
crap 11.0245

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 $range;
23
    public $networkRange;
24
25 46
    public function __construct($ipOptions = null)
26
    {
27 46
        if (is_int($ipOptions)) {
28 1
            $this->ipOptions = $ipOptions;
29
30 1
            return;
31
        }
32
33 45
        $this->networkRange = $this->parseRange($ipOptions);
34 37
        $this->range = $this->createRange();
35 37
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 37
    public function createRange(): ?string
41
    {
42 37
        if (!$this->networkRange) {
43 13
            return null;
44
        }
45
46 25
        $range = $this->networkRange;
47 25
        $message = $range['min'];
48
49 25
        if (isset($range['max'])) {
50 19
            $message .= '-'.$range['max'];
51
        } else {
52 6
            $message .= '/'.long2ip((int) $range['mask']);
53
        }
54
55 25
        return $message;
56
    }
57
58 45
    protected function parseRange($input)
59
    {
60 45
        if (null === $input || '*' == $input || '*.*.*.*' == $input
61 45
            || '0.0.0.0-255.255.255.255' == $input) {
62 13
            return;
63
        }
64
65 33
        $range = ['min' => null, 'max' => null, 'mask' => null];
66
67 33
        if (false !== mb_strpos($input, '-')) {
68 9
            list($range['min'], $range['max']) = explode('-', $input);
69 24
        } elseif (false !== mb_strpos($input, '*')) {
70 12
            $this->parseRangeUsingWildcards($input, $range);
71 12
        } elseif (false !== mb_strpos($input, '/')) {
72 9
            $this->parseRangeUsingCidr($input, $range);
73
        } else {
74 3
            throw new ComponentException('Invalid network range');
75
        }
76
77 27
        if (!$this->verifyAddress($range['min'])) {
78
            throw new ComponentException('Invalid network range');
79
        }
80
81 27
        if (isset($range['max']) && !$this->verifyAddress($range['max'])) {
82 2
            throw new ComponentException('Invalid network range');
83
        }
84
85 25
        return $range;
86
    }
87
88 21
    protected function fillAddress(&$input, $char = '*'): void
89
    {
90 21
        while (mb_substr_count($input, '.') < 3) {
91 5
            $input .= '.'.$char;
92
        }
93 21
    }
94
95 12
    protected function parseRangeUsingWildcards($input, &$range): void
96
    {
97 12
        $this->fillAddress($input);
98
99 12
        $range['min'] = strtr($input, '*', '0');
100 12
        $range['max'] = str_replace('*', '255', $input);
101 12
    }
102
103 9
    protected function parseRangeUsingCidr($input, &$range): void
104
    {
105 9
        $input = explode('/', $input);
106 9
        $this->fillAddress($input[0], '0');
107
108 9
        $range['min'] = $input[0];
109 9
        $isAddressMask = false !== mb_strpos($input[1], '.');
110
111 9
        if ($isAddressMask && $this->verifyAddress($input[1])) {
112 2
            $range['mask'] = sprintf('%032b', ip2long($input[1]));
113
114 2
            return;
115
        }
116
117 7
        if ($isAddressMask || $input[1] < 8 || $input[1] > 30) {
118 3
            throw new ComponentException('Invalid network mask');
119
        }
120
121 4
        $range['mask'] = sprintf('%032b', ip2long(long2ip(~(2 ** (32 - $input[1]) - 1))));
122 4
    }
123
124 38
    public function validate($input): bool
125
    {
126 38
        return $this->verifyAddress($input) && $this->verifyNetwork($input);
127
    }
128
129 42
    protected function verifyAddress($address)
130
    {
131 42
        return (bool) filter_var(
132 42
            $address,
133 42
            FILTER_VALIDATE_IP,
134
            [
135 42
                'flags' => $this->ipOptions,
136
            ]
137
        );
138
    }
139
140 31
    protected function verifyNetwork($input)
141
    {
142 31
        if (null === $this->networkRange) {
143 7
            return true;
144
        }
145
146 25
        if (isset($this->networkRange['mask'])) {
147 6
            return $this->belongsToSubnet($input);
148
        }
149
150 19
        $input = sprintf('%u', ip2long($input));
151
152 19
        return bccomp($input, sprintf('%u', ip2long($this->networkRange['min']))) >= 0
153 19
               && bccomp($input, sprintf('%u', ip2long($this->networkRange['max']))) <= 0;
154
    }
155
156 6
    protected function belongsToSubnet($input)
157
    {
158 6
        $range = $this->networkRange;
159 6
        $min = sprintf('%032b', ip2long($range['min']));
160 6
        $input = sprintf('%032b', ip2long($input));
161
162 6
        return ($input & $range['mask']) === ($min & $range['mask']);
163
    }
164
}
165