Completed
Push — master ( da7244...6b72a0 )
by Sam
04:56
created

Toolbox::contractIpv6()   C

Complexity

Conditions 14
Paths 81

Size

Total Lines 67
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 14.0021

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 67
ccs 44
cts 45
cp 0.9778
rs 5.8135
cc 14
eloc 39
nc 81
nop 1
crap 14.0021

How to fix   Long Method    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 Badcow DNS Library.
5
 *
6
 * (c) Samuel Williams <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Badcow\DNS\Ip;
13
14
use Badcow\DNS\Validator;
15
16
class Toolbox
17
{
18
    /**
19
     * Expands an IPv6 address to its full, non-short hand representation.
20
     *
21
     * @param string $ip IPv6 address
22
     * @throws \InvalidArgumentException
23
     *
24
     * @return string
25
     */
26 9
    public static function expandIpv6($ip)
27
    {
28 9
        if (!Validator::validateIpv6Address($ip)) {
29 3
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IPv6 address.', $ip));
30
        }
31
32 9
        $hex = unpack('H*hex', inet_pton($ip));
33 9
        $ip = substr(preg_replace('/([A-f0-9]{4})/', '$1:', $hex['hex']), 0, -1);
34
35 9
        return $ip;
36
    }
37
38
    /**
39
     * This function will expand in incomplete IPv6 address.
40
     * An incomplete IPv6 address is of the form `2001:db8:ffff:abcd`
41
     * i.e. one where there is less than eight hextets.
42
     *
43
     * @param string $ip IPv6 address
44
     * @return string Expanded incomplete IPv6 address
45
     */
46 3
    public static function expandIncompleteIpv6($ip)
47
    {
48 3
        $parts = explode(':', $ip);
49 3
        foreach ($parts as $i => $part) {
50 3
            $parts[$i] = str_pad($part, 4, '0', STR_PAD_LEFT);
51 2
        }
52
53 3
        return implode(':', $parts);
54
    }
55
56
    /**
57
     * Takes a valid IPv6 address and contracts it
58
     * to its shorter version.
59
     *
60
     * E.g.: 2001:0000:0000:acad:0000:0000:0000:0001 -> 2001:0:0:acad::1
61
     *
62
     * Note: If there is more than one set of consecutive hextets, the function
63
     * will favour the larger of the sets. If both sets of zeroes are the same
64
     * the second will be favoured in the omission of zeroes.
65
     *
66
     * E.g.: 2001:0000:0000:ab80:2390:0000:0000:000a -> 2001:0:0:ab80:2390::a
67
     *
68
     * @param string $ip IPv6 address
69
     * @throws \InvalidArgumentException
70
     *
71
     * @return string Contracted IPv6 address
72
     */
73 3
    public static function contractIpv6($ip)
74
    {
75 3
        if (!Validator::validateIpv6Address($ip)) {
76
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IPv6 address.', $ip));
77
        }
78
79 3
        $ip = self::expandIpv6($ip);
80 3
        $hextets = explode(':', $ip);
81 3
        $decimals = [];
82
83 3
        foreach ($hextets as $hextet) {
84 3
            $decimals[] = hexdec($hextet);
85 2
        }
86
87 3
        $zeroes = [];
88 3
        $flag = false;
89
90 3
        foreach ($decimals as $i => $n) {
91 3
            if (0 === $n) {
92 3
                if (true === $flag) {
93 3
                    $arg = end($zeroes);
94 3
                    $arg['n'] += 1;
95 2
                } else {
96 3
                    $flag = true;
97 3
                    $arg = ['i' => $i, 'n' => 1];
98
                }
99
100 3
                $zeroes[$arg['i']] = $arg;
101
102 3
                continue;
103
            }
104
105 3
            $flag = false;
106 2
        }
107
108 3
        $i_0 = -1;
109 3
        $n_0 = 0;
110
111 3
        if (count($zeroes) > 0) {
112 3
            $n = 0;
113 3
            foreach ($zeroes as $arg) {
114 3
                if ($arg['n'] >= $n) {
115 3
                    $i_0 = $arg['i'];
116 3
                    $n_0 = $arg['n'];
117 2
                }
118 2
            }
119 2
        }
120
121 3
        $ip = '';
122
123 3
        foreach ($decimals as $i => $decimal) {
124 3
            if ($i > $i_0 && $i < $i_0 + $n_0) {
125 3
                continue;
126
            }
127
128 3
            if ($i === $i_0) {
129 3
                $ip .= '::';
130 3
                continue;
131
            }
132
133 3
            $ip .= (string) dechex($decimal);
134
135 3
            $ip .= ($i < 7) ? ':' : '';
136 2
        }
137
138 3
        return preg_replace('/\:{3}/', '::', $ip);
139
    }
140
141
    /**
142
     * Creates a reverse IPv4 address.
143
     *
144
     * @param $ip
145
     *
146
     * @return string
147
     */
148 3
    public static function reverseIpv4($ip)
149
    {
150 3
        $parts = array_reverse(explode('.', $ip));
151
152 3
        $address = implode('.', $parts);
153 3
        $address .= '.in-addr.arpa.';
154
155 3
        return $address;
156
    }
157
158
    /**
159
     * Creates a reverse IPv6 address.
160
     *
161
     * @param string $ip
162
     *
163
     * @return string
164
     */
165 3
    public static function reverseIpv6($ip)
166
    {
167
        try {
168 3
            $ip = self::expandIpv6($ip);
169 3
        } catch (\InvalidArgumentException $e) {
170 3
            $ip = self::expandIncompleteIpv6($ip);
171
        }
172
173 3
        $ip = str_replace(':', '', $ip);
174 3
        $ip = strrev($ip);
175 3
        $address = implode('.', str_split($ip));
176 3
        $address .= '.ip6.arpa.';
177
178 3
        return $address;
179
    }
180
}
181