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
Idableprovides a methodequalsIdthat 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.