IPTrait   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 92.93%

Importance

Changes 12
Bugs 0 Features 0
Metric Value
wmc 35
c 12
b 0
f 0
lcom 1
cbo 4
dl 0
loc 248
ccs 92
cts 99
cp 0.9293
rs 9

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getWebRequest() 0 13 4
A attachInitIpEvent() 0 4 1
B enabledIPFields() 0 18 5
A onInitIpAddress() 0 9 4
B getIpAddress() 0 21 7
A getIpv4Address() 0 4 1
A getIpv6Address() 0 9 1
C setIpAddress() 0 23 8
B getIpRules() 0 27 4
1
<?php
2
3
/**
4
 *  _   __ __ _____ _____ ___  ____  _____
5
 * | | / // // ___//_  _//   ||  __||_   _|
6
 * | |/ // /(__  )  / / / /| || |     | |
7
 * |___//_//____/  /_/ /_/ |_||_|     |_|
8
 * @link http://vistart.name/
9
 * @copyright Copyright (c) 2016 vistart
10
 * @license http://vistart.name/license/
11
 */
12
13
namespace vistart\Models\traits;
14
15
use vistart\helpers\Ip;
16
use Yii;
17
use yii\base\ModelEvent;
18
use yii\web\Request;
19
20
/**
21
 * Entity features concerning IP address.
22
 * The EntityTrait use this trait by default. If you want to use this trait into
23
 * seperate models, please attach initialization events and merge the IP attributes
24
 * rules.
25
 * @property string|integer|null $ipAddress
26
 * @proeprty array $ipRules
27
 * @version 2.0
28
 * @author vistart <[email protected]>
29
 */
30
trait IPTrait
31
{
32
33
    /**
34
     * @var integer REQUIRED. Determine whether enabling the IP attributes and
35
     * features, and IP address type if enabled.
36
     * @since 1.1
37
     * @version 2.0
38
     */
39
    public $enableIP = 0x03;
40
41
    /**
42
     * @var integer Disable IP address features.
43
     */
44
    public static $noIp = 0x0;
45
46
    /**
47
     * @var integer Only accept IPv4 address.
48
     */
49
    public static $ipv4 = 0x1;
50
51
    /**
52
     * @var integer Only accept IPv6 address.
53
     */
54
    public static $ipv6 = 0x2;
55
56
    /**
57
     * @var integer Accept IPv4 and IPv6 address. Judge type of IP address
58
     * automatically.
59
     */
60
    public static $ipAll = 0x3;
61
62
    /**
63
     * @var string The attribute name that will receive the beginning 32 bits of
64
     * IPv6, or IPv4. The default value is 'ip_1'.
65
     */
66
    public $ipAttribute1 = 'ip_1';
67
68
    /**
69
     * @var string The attribute name that will receive the 33 - 64 bits of IPv6,
70
     * or 0 of IPv4. The default value is 'ip_2'.
71
     */
72
    public $ipAttribute2 = 'ip_2';
73
74
    /**
75
     * @var string The attribute name that will receive the 65 - 96 bits of IPv6,
76
     * or 0 of IPv4. The default value is 'ip_3'.
77
     */
78
    public $ipAttribute3 = 'ip_3';
79
80
    /**
81
     * @var string The attribute name that will receive the last 32 bits of IPv6,
82
     * or 0 of IPv4. The default value is 'ip_4'.
83
     */
84
    public $ipAttribute4 = 'ip_4';
85
86
    /**
87
     * @var string The attribute name that will receive the type of IP address.
88
     * The default value is 'ip_type'. If you assign $enableIP to $ipAll, this
89
     * attribute is required.
90
     */
91
    public $ipTypeAttribute = 'ip_type';
92
93
    /**
94
     * @var string Request component ID.
95
     */
96
    public $requestId = 'request';
97
98
    /**
99
     * Get web request component. if `$requestId` not specified, Yii::$app->request
100
     * will be taken.
101
     * @return Request
102
     */
103 62
    protected function getWebRequest()
104
    {
105 62
        $requestId = $this->requestId;
106 62
        if (!empty($requestId) && is_string($requestId)) {
107 62
            $request = Yii::$app->$requestId;
108 62
        } else {
109
            $request = Yii::$app->request;
110
        }
111 62
        if ($request instanceof Request) {
112 62
            return $request;
113
        }
114
        return null;
115
    }
116
117
    /**
118
     * Attach `onInitGuidAttribute` event.
119
     * @param string $eventName
120
     */
121 62
    protected function attachInitIpEvent($eventName)
122
    {
123 62
        $this->on($eventName, [$this, 'onInitIpAddress']);
0 ignored issues
show
Bug introduced by
It seems like on() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
124 62
    }
125
126
    /**
127
     * Initialize ip attributes.
128
     * This method is ONLY used for being triggered by event. DO NOT call,
129
     * override or modify it directly, unless you know the consequences.
130
     * @param ModelEvent $event
131
     * @since 1.1
132
     */
133 62
    public function onInitIpAddress($event)
134
    {
135 62
        $sender = $event->sender;
136
        /* @var $sender \vistart\Models\models\BaseEntityModel */
137 62
        $request = $sender->getWebRequest();
0 ignored issues
show
Bug introduced by
The method getWebRequest() cannot be called from this context as it is declared protected in class vistart\Models\traits\IPTrait.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
138 62
        if ($sender->enableIP && $request && empty($sender->ipAddress)) {
139 62
            $sender->ipAddress = $request->userIP;
140 62
        }
141 62
    }
142
143
    /**
144
     * Return the IP address.
145
     * The IP address is converted from ipAttribute*.
146
     * If you disable($this->enableIP = false) the IP feature, this method will
147
     * return null, or return the significantly IP address(Colon hexadecimal of
148
     * IPv6 or Dotted decimal of IPv4).
149
     * @return string|integer|null
150
     */
151 62
    public function getIpAddress()
152
    {
153 62
        if (!$this->enableIP) {
154
            return null;
155
        }
156 62
        if ($this->enableIP & static::$ipAll) {
157 62
            if ($this->{$this->ipTypeAttribute} == Ip::IPv4) {
158 1
                return $this->getIpv4Address();
159
            }
160 62
            if ($this->{$this->ipTypeAttribute} == Ip::IPv6) {
161 1
                return $this->getIpv6Address();
162
            }
163 62
        } else
164
        if ($this->enableIP & static::$ipv4) {
165
            return $this->getIpv4Address();
166
        } else
167
        if ($this->enableIP & static::$ipv6) {
168
            return $this->getIpv6Address();
169
        }
170 62
        return null;
171
    }
172
173
    /**
174
     * Get the IPv4 address.
175
     * @return string
176
     */
177 1
    private function getIpv4Address()
178
    {
179 1
        return Ip::long2ip($this->{$this->ipAttribute1});
180
    }
181
182
    /**
183
     * Get the IPv6 address.
184
     * @return string
185
     */
186 1
    private function getIpv6Address()
187
    {
188 1
        return Ip::LongtoIPv6(Ip::populateIPv6([
189 1
                    $this->{$this->ipAttribute1},
190 1
                    $this->{$this->ipAttribute2},
191 1
                    $this->{$this->ipAttribute3},
192 1
                    $this->{$this->ipAttribute4}
193 1
        ]));
194
    }
195
196
    /**
197
     * Convert the IP address to integer, and store it(them) to ipAttribute*.
198
     * If you disable($this->enableIP = false) the IP feature, this method will
199
     * be skipped(return null).
200
     * @param string $ipAddress the significantly IP address.
201
     * @return string|integer|null Integer when succeeded to convert.
202
     */
203 62
    public function setIpAddress($ipAddress)
204
    {
205 62
        if (!$ipAddress || !$this->enableIP) {
206 62
            return null;
207
        }
208 1
        $ipType = Ip::judgeIPtype($ipAddress);
209 1
        if ($ipType == Ip::IPv4 && $this->enableIP & static::$ipv4) {
210 1
            $this->{$this->ipAttribute1} = Ip::ip2long($ipAddress);
211 1
        } else
212 1
        if ($ipType == Ip::IPv6 && $this->enableIP & static::$ipv6) {
213 1
            $ips = Ip::splitIPv6(Ip::IPv6toLong($ipAddress));
214 1
            $this->{$this->ipAttribute1} = bindec($ips[0]);
215 1
            $this->{$this->ipAttribute2} = bindec($ips[1]);
216 1
            $this->{$this->ipAttribute3} = bindec($ips[2]);
217 1
            $this->{$this->ipAttribute4} = bindec($ips[3]);
218 1
        } else {
219 1
            return 0;
220
        }
221 1
        if ($this->enableIP & static::$ipAll) {
222 1
            $this->{$this->ipTypeAttribute} = $ipType;
223 1
        }
224 1
        return $ipType;
225
    }
226
227
    /**
228
     * Get the rules associated with ip attributes.
229
     * @return array
230
     */
231 17
    public function getIpRules()
232
    {
233 17
        $rules = [];
234 17
        if ($this->enableIP & static::$ipv6) {
235
            $rules = [
236 13
                [[$this->ipAttribute1,
237 13
                    $this->ipAttribute2,
238 13
                    $this->ipAttribute3,
239 13
                    $this->ipAttribute4],
240 13
                    'number', 'integerOnly' => true, 'min' => 0
241 13
                ],
242 13
            ];
243 13
        }
244 17
        if ($this->enableIP & static::$ipv4) {
245
            $rules = [
246 13
                [[$this->ipAttribute1],
247 13
                    'number', 'integerOnly' => true, 'min' => 0
248 13
                ],
249 13
            ];
250 13
        }
251 17
        if ($this->enableIP & static::$ipAll) {
252 13
            $rules[] = [
253 13
                [$this->ipTypeAttribute], 'in', 'range' => [Ip::IPv4, Ip::IPv6],
254
            ];
255 13
        }
256 17
        return $rules;
257
    }
258
259 16
    public function enabledIPFields()
260
    {
261 16
        $fields = [];
262 16
        switch ($this->enableIP) {
263 16
            case static::$ipAll:
264 15
                $fields[] = $this->ipTypeAttribute;
265 16
            case static::$ipv6:
266 15
                $fields[] = $this->ipAttribute2;
267 15
                $fields[] = $this->ipAttribute3;
268 15
                $fields[] = $this->ipAttribute4;
269 16
            case static::$ipv4:
270 15
                $fields[] = $this->ipAttribute1;
271 16
            case static::$noIp:
272 16
            default:
273 16
                break;
274 16
        }
275 16
        return $fields;
276
    }
277
}
278