Complex classes like IPTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use IPTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | trait IPTrait |
||
29 | { |
||
30 | /** |
||
31 | * @var integer REQUIRED. Determine whether the IP attributes if enabled. |
||
32 | * All the parameters accepted are listed below. |
||
33 | */ |
||
34 | public $enableIP = 0x3; |
||
35 | public static $noIP = 0x0; |
||
36 | public static $ipv4 = 0x1; |
||
37 | public static $ipv6 = 0x2; |
||
38 | public static $ipAll = 0x3; |
||
39 | |||
40 | public $ipAttribute = 'ip'; |
||
41 | public $ipTypeAttribute = 'ip_type'; |
||
42 | public $requestId = 'request'; |
||
43 | |||
44 | 392 | protected function getWebRequest() |
|
45 | { |
||
46 | 392 | $requestId = $this->requestId; |
|
47 | 392 | if (!empty($requestId) && is_string($requestId)) { |
|
48 | 392 | $request = Yii::$app->$requestId; |
|
49 | } else { |
||
50 | 1 | $request = Yii::$app->request; |
|
51 | } |
||
52 | 392 | if ($request instanceof Request) { |
|
53 | 392 | return $request; |
|
54 | } |
||
55 | 1 | return null; |
|
56 | } |
||
57 | |||
58 | 392 | protected function attachInitIPEvent($eventName) |
|
62 | |||
63 | /** |
||
64 | * Initialize IP Attributes. |
||
65 | * This method is ONLY used for being triggered by event. DO NOT call, |
||
66 | * override or modify it directly, unless you know the consequences. |
||
67 | * @param ModelEvent $event |
||
68 | */ |
||
69 | 392 | public function onInitIPAddress($event) |
|
70 | { |
||
71 | 392 | $sender = $event->sender; |
|
72 | 392 | $request = $sender->getWebRequest(); |
|
73 | 392 | if ($sender->enableIP && $request && empty($sender->ipAddress)) { |
|
74 | 392 | $sender->ipAddress = $request->userIP; |
|
75 | } |
||
76 | 392 | } |
|
77 | |||
78 | /** |
||
79 | * Get the IPv4 address. |
||
80 | * @return string |
||
81 | */ |
||
82 | 11 | protected function getIPv4Address() |
|
86 | |||
87 | /** |
||
88 | * Get the IPv6 address. |
||
89 | * @return string |
||
90 | */ |
||
91 | 7 | protected function getIPv6Address() |
|
95 | |||
96 | /** |
||
97 | * |
||
98 | * @param string $ipAddress IPv4 address. |
||
99 | * @return string |
||
100 | */ |
||
101 | 7 | protected function setIPv4Address($ipAddress) |
|
105 | |||
106 | /** |
||
107 | * |
||
108 | * @param string $ipAddress IPv6 address. |
||
109 | * @return string |
||
110 | */ |
||
111 | 3 | protected function setIPv6Address($ipAddress) |
|
115 | |||
116 | /** |
||
117 | * |
||
118 | * @return string |
||
119 | */ |
||
120 | 392 | public function getIPAddress() |
|
143 | |||
144 | /** |
||
145 | * Convert the IP address to integer, and store it(them) to ipAttribute*. |
||
146 | * If you disable($this->enableIP = false) the IP feature, this method will |
||
147 | * be skipped(return null). |
||
148 | * @param string $ipAddress the significantly IP address. |
||
149 | * @return string|integer|null Integer when succeeded to convert. |
||
150 | */ |
||
151 | 392 | public function setIPAddress($ipAddress) |
|
169 | |||
170 | /** |
||
171 | * Get the rules associated with ip attributes. |
||
172 | * @return array |
||
173 | */ |
||
174 | 346 | public function getIPRules() |
|
198 | |||
199 | /** |
||
200 | * @inheritdoc |
||
201 | */ |
||
202 | 136 | public function enabledIPFields() |
|
217 | } |
||
218 |
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
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. 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.