Completed
Push — master ( 780945...6412ad )
by vistart
05:53
created

IPTrait::enabledIPFields()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 16
cts 16
cp 1
rs 8.8571
cc 5
eloc 15
nc 5
nop 0
crap 5
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
18
/**
19
 * Entity features concerning IP address.
20
 * @property string|integer|null $ipAddress
21
 * @proeprty array $ipRules
22
 * @version 2.0
23
 * @author vistart <[email protected]>
24
 */
25
trait IPTrait
26
{
27
28
    /**
29
     * @var integer REQUIRED. Determine whether enabling the IP attributes and
30
     * features, and IP address type if enabled.
31
     * @since 1.1
32
     * @version 2.0
33
     */
34
    public $enableIP = 0x03;
35
36
    /**
37
     * @var integer Disable IP address features.
38
     */
39
    public static $noIp = 0x0;
40
41
    /**
42
     * @var integer Only accept IPv4 address.
43
     */
44
    public static $ipv4 = 0x1;
45
46
    /**
47
     * @var integer Only accept IPv6 address.
48
     */
49
    public static $ipv6 = 0x2;
50
51
    /**
52
     * @var integer Accept IPv4 and IPv6 address. Judge type of IP address
53
     * automatically.
54
     */
55
    public static $ipAll = 0x3;
56
57
    /**
58
     * @var string The attribute name that will receive the beginning 32 bits of
59
     * IPv6, or IPv4. The default value is 'ip_1'.
60
     */
61
    public $ipAttribute1 = 'ip_1';
62
63
    /**
64
     * @var string The attribute name that will receive the 33 - 64 bits of IPv6,
65
     * or 0 of IPv4. The default value is 'ip_2'.
66
     */
67
    public $ipAttribute2 = 'ip_2';
68
69
    /**
70
     * @var string The attribute name that will receive the 65 - 96 bits of IPv6,
71
     * or 0 of IPv4. The default value is 'ip_3'.
72
     */
73
    public $ipAttribute3 = 'ip_3';
74
75
    /**
76
     * @var string The attribute name that will receive the last 32 bits of IPv6,
77
     * or 0 of IPv4. The default value is 'ip_4'.
78
     */
79
    public $ipAttribute4 = 'ip_4';
80
81
    /**
82
     * @var string The attribute name that will receive the type of IP address.
83
     * The default value is 'ip_type'. If you assign $enableIP to $ipAll, this
84
     * attribute is required.
85
     */
86
    public $ipTypeAttribute = 'ip_type';
87
88
    /**
89
     * @var string Request component ID.
90
     */
91
    public $requestId = 'request';
92
93
    /**
94
     * Get web request component. if `$requestId` not specified, Yii::$app->request
95
     * will be taken.
96
     * @return \yii\web\Request
97
     */
98 50
    protected function getWebRequest()
99
    {
100 50
        $requestId = $this->requestId;
101 50
        if (!empty($requestId) && is_string($requestId)) {
102 50
            $request = Yii::$app->$requestId;
103 50
        } else {
104
            $request = Yii::$app->request;
105
        }
106 50
        if ($request instanceof \yii\web\Request) {
107 50
            return $request;
108
        }
109
        return null;
110
    }
111
112
    /**
113
     * Attach `onInitGuidAttribute` event.
114
     * @param string $eventName
115
     */
116 50
    protected function attachInitIpEvent($eventName)
117
    {
118 50
        $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...
119 50
    }
120
121
    /**
122
     * Initialize ip attributes.
123
     * This method is ONLY used for being triggered by event. DO NOT call,
124
     * override or modify it directly, unless you know the consequences.
125
     * @param \yii\base\Event $event
126
     * @since 1.1
127
     */
128 50
    public function onInitIpAddress($event)
129
    {
130 50
        $sender = $event->sender;
131
        /* @var $sender \vistart\Models\models\BaseEntityModel */
132 50
        $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...
133 50
        if ($sender->enableIP && $request && empty($sender->ipAddress)) {
134 50
            $sender->ipAddress = $request->userIP;
135 50
        }
136 50
    }
137
138
    /**
139
     * Return the IP address.
140
     * The IP address is converted from ipAttribute*.
141
     * If you disable($this->enableIP = false) the IP feature, this method will
142
     * return null, or return the significantly IP address(Colon hexadecimal of
143
     * IPv6 or Dotted decimal of IPv4).
144
     * @return string|integer|null
145
     */
146 50
    public function getIpAddress()
147
    {
148 50
        if (!$this->enableIP) {
149
            return null;
150
        }
151 50
        if ($this->enableIP & static::$ipAll) {
152 50
            $ipTypeAttribute = $this->ipTypeAttribute;
153 50
            if ($this->$ipTypeAttribute == Ip::IPv4) {
154 1
                return $this->getIpv4Address();
155
            }
156 50
            if ($this->$ipTypeAttribute == Ip::IPv6) {
157 1
                return $this->getIpv6Address();
158
            }
159 50
        } else
160
        if ($this->enableIP & static::$ipv4) {
161
            return $this->getIpv4Address();
162
        } else
163
        if ($this->enableIP & static::$ipv6) {
164
            return $this->getIpv6Address();
165
        }
166 50
        return null;
167
    }
168
169
    /**
170
     * Get the IPv4 address.
171
     * @return string
172
     */
173 1
    private function getIpv4Address()
174
    {
175 1
        $ipAttribute1 = $this->ipAttribute1;
176 1
        return Ip::long2ip($this->$ipAttribute1);
177
    }
178
179
    /**
180
     * Get the IPv6 address.
181
     * @return string
182
     */
183 1
    private function getIpv6Address()
184
    {
185 1
        $ipAttribute1 = $this->ipAttribute1;
186 1
        $ipAttribute2 = $this->ipAttribute2;
187 1
        $ipAttribute3 = $this->ipAttribute3;
188 1
        $ipAttribute4 = $this->ipAttribute4;
189 1
        return Ip::LongtoIPv6(Ip::populateIPv6([
190 1
                    $this->$ipAttribute1,
191 1
                    $this->$ipAttribute2,
192 1
                    $this->$ipAttribute3,
193 1
                    $this->$ipAttribute4
194 1
        ]));
195
    }
196
197
    /**
198
     * Convert the IP address to integer, and store it(them) to ipAttribute*.
199
     * If you disable($this->enableIP = false) the IP feature, this method will
200
     * be skipped(return null).
201
     * @param string $ipAddress the significantly IP address.
202
     * @return string|integer|null Integer when succeeded to convert.
203
     */
204 50
    public function setIpAddress($ipAddress)
205
    {
206 50
        if (!$ipAddress || !$this->enableIP) {
207 50
            return null;
208
        }
209 1
        $ipType = Ip::judgeIPtype($ipAddress);
210 1
        if ($ipType == Ip::IPv4 && $this->enableIP & static::$ipv4) {
211 1
            $ipAttribute1 = $this->ipAttribute1;
212 1
            $this->$ipAttribute1 = Ip::ip2long($ipAddress);
213 1
        } else
214 1
        if ($ipType == Ip::IPv6 && $this->enableIP & static::$ipv6) {
215 1
            $ips = Ip::splitIPv6(Ip::IPv6toLong($ipAddress));
216 1
            $ipAttribute1 = $this->ipAttribute1;
217 1
            $ipAttribute2 = $this->ipAttribute2;
218 1
            $ipAttribute3 = $this->ipAttribute3;
219 1
            $ipAttribute4 = $this->ipAttribute4;
220 1
            $this->$ipAttribute1 = bindec($ips[0]);
221 1
            $this->$ipAttribute2 = bindec($ips[1]);
222 1
            $this->$ipAttribute3 = bindec($ips[2]);
223 1
            $this->$ipAttribute4 = bindec($ips[3]);
224 1
        } else {
225 1
            return 0;
226
        }
227 1
        if ($this->enableIP & static::$ipAll) {
228 1
            $ipTypeAttribute = $this->ipTypeAttribute;
229 1
            $this->$ipTypeAttribute = $ipType;
230 1
        }
231 1
        return $ipType;
232
    }
233
234
    /**
235
     * Get the rules associated with ip attributes.
236
     * @return array
237
     */
238 15
    public function getIpRules()
239
    {
240 15
        $rules = [];
241 15
        if ($this->enableIP & static::$ipv6) {
242
            $rules = [
243 11
                [[$this->ipAttribute1,
244 11
                    $this->ipAttribute2,
245 11
                    $this->ipAttribute3,
246 11
                    $this->ipAttribute4],
247 11
                    'number', 'integerOnly' => true, 'min' => 0
248 11
                ],
249 11
            ];
250 11
        }
251 15
        if ($this->enableIP & static::$ipv4) {
252
            $rules = [
253 11
                [[$this->ipAttribute1],
254 11
                    'number', 'integerOnly' => true, 'min' => 0
255 11
                ],
256 11
            ];
257 11
        }
258 15
        if ($this->enableIP & static::$ipAll) {
259 11
            $rules[] = [
260 11
                [$this->ipTypeAttribute], 'in', 'range' => [Ip::IPv4, Ip::IPv6],
261
            ];
262 11
        }
263 15
        return $rules;
264
    }
265
266 13
    public function enabledIPFields()
267
    {
268 13
        $fields = [];
269 13
        switch ($this->enableIP) {
270 13
            case static::$ipAll:
271 12
                $fields[] = $this->ipTypeAttribute;
272 13
            case static::$ipv6:
273 12
                $fields[] = $this->ipAttribute2;
274 12
                $fields[] = $this->ipAttribute3;
275 12
                $fields[] = $this->ipAttribute4;
276 13
            case static::$ipv4:
277 12
                $fields[] = $this->ipAttribute1;
278 13
            case static::$noIp:
279 13
            default:
280 13
                break;
281 13
        }
282 13
        return $fields;
283
    }
284
}
285