Completed
Push — master ( 8b755d...e62bff )
by vistart
08:43
created

IPTrait::getWebRequest()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.1755

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
ccs 7
cts 9
cp 0.7778
rs 9.2
cc 4
eloc 9
nc 4
nop 0
crap 4.1755
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
    public $requestId = 'request';
88
89
    /**
90
     * 
91
     * @return \yii\web\Request
92
     */
93 38
    protected function getWebRequest()
94
    {
95 38
        $requestId = $this->requestId;
96 38
        if (!empty($requestId) && is_string($requestId)) {
97 38
            $request = Yii::$app->$requestId;
98 38
        } else {
99
            $request = Yii::$app->request;
100
        }
101 38
        if ($request instanceof \yii\web\Request) {
102 38
            return $request;
103
        }
104
        return null;
105
    }
106
107
    /**
108
     * Attach `onInitGuidAttribute` event.
109
     * @param string $eventName
110
     */
111 38
    protected function attachInitIpEvent($eventName)
112
    {
113 38
        $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...
114 38
    }
115
116
    /**
117
     * Initialize ip attributes.
118
     * This method is ONLY used for being triggered by event. DO NOT call,
119
     * override or modify it directly, unless you know the consequences.
120
     * @param \yii\base\Event $event
121
     * @since 1.1
122
     */
123 38
    public function onInitIpAddress($event)
124
    {
125 38
        $sender = $event->sender;
126
        /* @var $sender \vistart\Models\models\BaseEntityModel */
127 38
        $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...
128 38
        if ($sender->enableIP && $request && empty($sender->ipAddress)) {
129 38
            $sender->ipAddress = $request->userIP;
130 38
        }
131 38
    }
132
133
    /**
134
     * Return the IP address.
135
     * The IP address is converted from ipAttribute*.
136
     * If you disable($this->enableIP = false) the IP feature, this method will
137
     * return null, or return the significantly IP address(Colon hexadecimal of
138
     * IPv6 or Dotted decimal of IPv4).
139
     * @return string|integer|null
140
     */
141 38
    public function getIpAddress()
142
    {
143 38
        if (!$this->enableIP) {
144
            return null;
145
        }
146 38
        if ($this->enableIP & static::$ipAll) {
147 38
            $ipTypeAttribute = $this->ipTypeAttribute;
148 38
            if ($this->$ipTypeAttribute == Ip::IPv4) {
149 1
                return $this->getIpv4Address();
150
            }
151 38
            if ($this->$ipTypeAttribute == Ip::IPv6) {
152 1
                return $this->getIpv6Address();
153
            }
154 38
        } else
155
        if ($this->enableIP & static::$ipv4) {
156
            return $this->getIpv4Address();
157
        } else
158
        if ($this->enableIP & static::$ipv6) {
159
            return $this->getIpv6Address();
160
        }
161 38
        return null;
162
    }
163
164
    /**
165
     * Get the IPv4 address.
166
     * @return string
167
     */
168 1
    private function getIpv4Address()
169
    {
170 1
        $ipAttribute1 = $this->ipAttribute1;
171 1
        return Ip::long2ip($this->$ipAttribute1);
172
    }
173
174
    /**
175
     * Get the IPv6 address.
176
     * @return string
177
     */
178 1
    private function getIpv6Address()
179
    {
180 1
        $ipAttribute1 = $this->ipAttribute1;
181 1
        $ipAttribute2 = $this->ipAttribute2;
182 1
        $ipAttribute3 = $this->ipAttribute3;
183 1
        $ipAttribute4 = $this->ipAttribute4;
184 1
        return Ip::LongtoIPv6(Ip::populateIPv6([
185 1
                    $this->$ipAttribute1,
186 1
                    $this->$ipAttribute2,
187 1
                    $this->$ipAttribute3,
188 1
                    $this->$ipAttribute4
189 1
        ]));
190
    }
191
192
    /**
193
     * Convert the IP address to integer, and store it(them) to ipAttribute*.
194
     * If you disable($this->enableIP = false) the IP feature, this method will
195
     * be skipped(return null).
196
     * @param string $ipAddress the significantly IP address.
197
     * @return string|integer|null Integer when succeeded to convert.
198
     */
199 38
    public function setIpAddress($ipAddress)
200
    {
201 38
        if (!$ipAddress || !$this->enableIP) {
202 38
            return null;
203
        }
204 1
        $ipType = Ip::judgeIPtype($ipAddress);
205 1
        if ($ipType == Ip::IPv4 && $this->enableIP & static::$ipv4) {
206 1
            $ipAttribute1 = $this->ipAttribute1;
207 1
            $this->$ipAttribute1 = Ip::ip2long($ipAddress);
208 1
        } else
209 1
        if ($ipType == Ip::IPv6 && $this->enableIP & static::$ipv6) {
210 1
            $ips = Ip::splitIPv6(Ip::IPv6toLong($ipAddress));
211 1
            $ipAttribute1 = $this->ipAttribute1;
212 1
            $ipAttribute2 = $this->ipAttribute2;
213 1
            $ipAttribute3 = $this->ipAttribute3;
214 1
            $ipAttribute4 = $this->ipAttribute4;
215 1
            $this->$ipAttribute1 = bindec($ips[0]);
216 1
            $this->$ipAttribute2 = bindec($ips[1]);
217 1
            $this->$ipAttribute3 = bindec($ips[2]);
218 1
            $this->$ipAttribute4 = bindec($ips[3]);
219 1
        } else {
220 1
            return 0;
221
        }
222 1
        if ($this->enableIP & static::$ipAll) {
223 1
            $ipTypeAttribute = $this->ipTypeAttribute;
224 1
            $this->$ipTypeAttribute = $ipType;
225 1
        }
226 1
        return $ipType;
227
    }
228
229
    /**
230
     * Get the rules associated with ip attributes.
231
     * @return array
232
     */
233 8
    public function getIpRules()
234
    {
235 8
        $rules = [];
236 8
        if ($this->enableIP & static::$ipv6) {
237
            $rules = [
238 6
                [[$this->ipAttribute1,
239 6
                    $this->ipAttribute2,
240 6
                    $this->ipAttribute3,
241 6
                    $this->ipAttribute4],
242 6
                    'number', 'integerOnly' => true, 'min' => 0
243 6
                ],
244 6
            ];
245 6
        }
246 8
        if ($this->enableIP & static::$ipv4) {
247
            $rules = [
248 6
                [[$this->ipAttribute1],
249 6
                    'number', 'integerOnly' => true, 'min' => 0
250 6
                ],
251 6
            ];
252 6
        }
253 8
        if ($this->enableIP & static::$ipAll) {
254 6
            $rules[] = [
255 6
                [$this->ipTypeAttribute], 'in', 'range' => [Ip::IPv4, Ip::IPv6],
256
            ];
257 6
        }
258 8
        return $rules;
259
    }
260
}
261