DBBinaryIP::nullValue()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace LeKoala\CommonExtensions\FieldType;
4
5
use Exception;
6
use SilverStripe\ORM\DB;
7
use SilverStripe\ORM\FieldType\DBField;
8
9
/**
10
 * A field to store ip address in binary formats
11
 *
12
 * @link https://stackoverflow.com/questions/22636912/store-both-ipv4-and-ipv6-address-in-a-single-column
13
 * @link https://www.php.net/manual/en/function.inet-pton.php
14
 * @link https://www.php.net/manual/en/function.inet-ntop.php
15
 * @link https://github.com/S1lentium/IPTools/blob/master/src/IP.php
16
 */
17
class DBBinaryIP extends DBField
18
{
19
    const IP_V4 = 'IPv4';
20
    const IP_V6 = 'IPv6';
21
22
    const IP_V4_MAX_PREFIX_LENGTH = 32;
23
    const IP_V6_MAX_PREFIX_LENGTH = 128;
24
25
    const IP_V4_OCTETS = 4;
26
    const IP_V6_OCTETS = 16;
27
28
    public function requireField()
29
    {
30
        // Use direct sql statement here
31
        $sql = "binary(16)";
32
        DB::require_field($this->tableName, $this->name, $sql);
33
    }
34
35
    /**
36
     * @return string A readable ip address like 127.0.0.1
37
     */
38
    public function Nice()
39
    {
40
        if (!$this->value) {
41
            return $this->nullValue();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\CommonExtensions...DBBinaryIP::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
42
        }
43
        return inet_ntop($this->value);
44
    }
45
46
    /**
47
     * @return string
48
     */
49
    public function BinValue()
50
    {
51
        $binary = array();
52
        foreach (unpack('C*', $this->value) as $char) {
53
            $binary[] = str_pad(decbin($char), 8, '0', STR_PAD_LEFT);
54
        }
55
56
        return implode($binary);
57
    }
58
59
    /**
60
     * @return string
61
     */
62
    public function HexValue()
63
    {
64
        return bin2hex($this->value);
65
    }
66
67
    /**
68
     * @return string
69
     */
70
    public function LongValue()
71
    {
72
        $long = 0;
73
        if ($this->getVersion() === self::IP_V4) {
74
            $long = sprintf('%u', ip2long(inet_ntop($this->value)));
75
        } else {
76
            $octet = self::IP_V6_OCTETS - 1;
77
            foreach ($chars = unpack('C*', $this->value) as $char) {
0 ignored issues
show
Unused Code introduced by
The assignment to $chars is dead and can be removed.
Loading history...
78
                $long = bcadd($long, bcmul($char, bcpow(256, $octet--)));
79
            }
80
        }
81
82
        return $long;
83
    }
84
85
    public function scaffoldFormField($title = null, $params = null)
86
    {
87
        return false;
88
    }
89
90
    public function nullValue()
91
    {
92
        return null;
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    public function getVersion()
99
    {
100
        $version = '';
101
102
        if (filter_var(inet_ntop($this->value), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
103
            $version = self::IP_V4;
104
        } elseif (filter_var(inet_ntop($this->value), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
105
            $version = self::IP_V6;
106
        }
107
108
        return $version;
109
    }
110
111
    /**
112
     * @return int
113
     */
114
    public function getMaxPrefixLength()
115
    {
116
        return $this->getVersion() === self::IP_V4
117
            ? self::IP_V4_MAX_PREFIX_LENGTH
118
            : self::IP_V6_MAX_PREFIX_LENGTH;
119
    }
120
121
    /**
122
     * @return int
123
     */
124
    public function getOctetsCount()
125
    {
126
        return $this->getVersion() === self::IP_V4
127
            ? self::IP_V4_OCTETS
128
            : self::IP_V6_OCTETS;
129
    }
130
131
    /**
132
     * @return string
133
     */
134
    public function getReversePointer()
135
    {
136
        if ($this->getVersion() === self::IP_V4) {
137
            $reverseOctets = array_reverse(explode('.', $this->Nice()));
138
            $reversePointer = implode('.', $reverseOctets) . '.in-addr.arpa';
139
        } else {
140
            $unpacked = unpack('H*hex', $this->value);
141
            $reverseOctets = array_reverse(str_split($unpacked['hex']));
0 ignored issues
show
Bug introduced by
It seems like str_split($unpacked['hex']) can also be of type true; however, parameter $array of array_reverse() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

141
            $reverseOctets = array_reverse(/** @scrutinizer ignore-type */ str_split($unpacked['hex']));
Loading history...
142
            $reversePointer = implode('.', $reverseOctets) . '.ip6.arpa';
143
        }
144
145
        return $reversePointer;
146
    }
147
148
    public function prepValueForDB($value)
149
    {
150
        if (!$value) {
151
            return $this->nullValue();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\CommonExtensions...DBBinaryIP::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
152
        }
153
154
        // String ip contains dots
155
        if (strpos($value, '.') !== false) {
156
            return inet_pton($value);
157
        }
158
        // Strlen 16 = already binary
159
        if (strlen($value) === 16) {
160
            return $value;
161
        }
162
        throw new Exception("$value seems an invalid ip value");
163
    }
164
}
165