Complex classes like SelfBlameableTrait 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 SelfBlameableTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | trait SelfBlameableTrait |
||
26 | { |
||
27 | |||
28 | /** |
||
29 | * @var false|string attribute name of which store the parent's guid. |
||
30 | */ |
||
31 | public $parentAttribute = false; |
||
32 | |||
33 | /** |
||
34 | * @var string|array rule name and parameters of parent attribute, as well |
||
35 | * as self referenced ID attribute. |
||
36 | */ |
||
37 | public $parentAttributeRule = ['string', 'max' => 36]; |
||
38 | |||
39 | /** |
||
40 | * @var string self referenced ID attribute. |
||
41 | */ |
||
42 | public $refIdAttribute = 'guid'; |
||
43 | public static $parentNone = 0; |
||
44 | public static $parentParent = 1; |
||
45 | public static $parentTypes = [ |
||
46 | 0 => 'none', |
||
47 | 1 => 'parent', |
||
48 | ]; |
||
49 | public static $onNoAction = 0; |
||
50 | public static $onRestrict = 1; |
||
51 | public static $onCascade = 2; |
||
52 | public static $onSetNull = 3; |
||
53 | public static $onUpdateTypes = [ |
||
54 | 0 => 'on action', |
||
55 | 1 => 'restrict', |
||
56 | 2 => 'cascade', |
||
57 | 3 => 'set null', |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * @var integer indicates the on delete type. default to cascade. |
||
62 | */ |
||
63 | public $onDeleteType = 2; |
||
64 | |||
65 | /** |
||
66 | * @var integer indicates the on update type. default to cascade. |
||
67 | */ |
||
68 | public $onUpdateType = 2; |
||
69 | |||
70 | /** |
||
71 | * @var boolean indicates whether throw exception or not when restriction occured on updating or deleting operation. |
||
72 | */ |
||
73 | public $throwRestrictException = false; |
||
74 | private $localSelfBlameableRules = []; |
||
75 | |||
76 | /** |
||
77 | * Get rules associated with self blameable attribute. |
||
78 | * @return array rules. |
||
79 | */ |
||
80 | 6 | public function getSelfBlameableRules() |
|
81 | { |
||
82 | 6 | if (!is_string($this->parentAttribute)) { |
|
83 | 5 | return []; |
|
84 | } |
||
85 | 1 | if (!empty($this->localSelfBlameableRules) && is_array($this->localSelfBlameableRules)) { |
|
86 | 1 | return $this->localSelfBlameableRules; |
|
87 | } |
||
88 | 1 | if (is_string($this->parentAttributeRule)) { |
|
89 | $this->parentAttributeRule = [$this->parentAttributeRule]; |
||
90 | } |
||
91 | 1 | $this->localSelfBlameableRules = [ |
|
92 | 1 | array_merge([$this->parentAttribute], $this->parentAttributeRule), |
|
93 | ]; |
||
94 | 1 | return $this->localSelfBlameableRules; |
|
95 | } |
||
96 | |||
97 | /** |
||
98 | * Set rules associated with self blameable attribute. |
||
99 | * @param array $rules rules. |
||
100 | */ |
||
101 | 1 | public function setSelfBlameableRules($rules = []) |
|
102 | { |
||
103 | 1 | $this->localSelfBlameableRules = $rules; |
|
104 | 1 | } |
|
105 | |||
106 | /** |
||
107 | * Bear a child. |
||
108 | * @param array $config |
||
109 | * @return static |
||
110 | */ |
||
111 | 9 | public function bear($config = []) |
|
112 | { |
||
113 | 9 | if (isset($config['class'])) { |
|
114 | 9 | unset($config['class']); |
|
115 | 9 | } |
|
116 | 9 | $refIdAttribute = $this->refIdAttribute; |
|
117 | 9 | $config[$this->parentAttribute] = $this->$refIdAttribute; |
|
118 | 9 | return new static($config); |
|
|
|||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Event triggered before deleting itself. |
||
123 | * @param \yii\base\ModelEvent $event |
||
124 | * @return boolean true if parentAttribute not specified. |
||
125 | * @throws \yii\db\IntegrityException throw if $throwRestrictException is true when $onDeleteType is on restrict. |
||
126 | */ |
||
127 | 8 | public function onDeleteChildren($event) |
|
152 | |||
153 | /** |
||
154 | * Event triggered before updating itself. |
||
155 | * @param \yii\base\ModelEvent $event |
||
156 | * @return boolean true if parentAttribute not specified. |
||
157 | * @throws \yii\db\IntegrityException throw if $throwRestrictException is true when $onUpdateType is on restrict. |
||
158 | */ |
||
159 | 4 | public function onUpdateChildren($event) |
|
184 | |||
185 | /** |
||
186 | * Get parent query. |
||
187 | * Or get parent instance if access by magic property. |
||
188 | * @return \yii\db\ActiveQuery |
||
189 | */ |
||
190 | 2 | public function getParent() |
|
194 | |||
195 | /** |
||
196 | * Get children query. |
||
197 | * Or get children instances if access magic property. |
||
198 | * @return \yii\db\ActiveQuery |
||
199 | */ |
||
200 | 3 | public function getChildren() |
|
204 | |||
205 | /** |
||
206 | * Get children which parent attribute point to the my old guid. |
||
207 | * @return static[] |
||
208 | */ |
||
209 | 4 | public function getOldChildren() |
|
213 | |||
214 | /** |
||
215 | * Update all children, not grandchildren. |
||
216 | * If onUpdateType is on cascade, the children will be updated automatically. |
||
217 | * @param mixed $value set guid if false, set empty string if empty() return |
||
218 | * true, otherwise set it to $parentAttribute. |
||
219 | * @return \yii\db\IntegrityException|boolean true if all update operations |
||
220 | * succeeded to execute, or false if anyone of them failed. If not production |
||
221 | * environment or enable debug mode, it will return exception. |
||
222 | * @throws \yii\db\IntegrityException throw if anyone update failed. |
||
223 | */ |
||
224 | 3 | public function updateChildren($value = false) |
|
258 | |||
259 | /** |
||
260 | * Delete all children, not grandchildren. |
||
261 | * If onDeleteType is on cascade, the children will be deleted automatically. |
||
262 | * If onDeleteType is on restrict and contains children, the deletion will |
||
263 | * be restricted. |
||
264 | * @return \yii\db\IntegrityException|boolean true if all delete operations |
||
265 | * succeeded to execute, or false if anyone of them failed. If not production |
||
266 | * environment or enable debug mode, it will return exception. |
||
267 | * @throws \yii\db\IntegrityException throw if anyone delete failed. |
||
268 | */ |
||
269 | 1 | public function deleteChildren() |
|
294 | |||
295 | /** |
||
296 | * Update children's parent attribute. |
||
297 | * Event triggered before updating. |
||
298 | * @param \yii\base\ModelEvent $event |
||
299 | * @return boolean |
||
300 | */ |
||
301 | 9 | public function onParentRefIdChanged($event) |
|
308 | |||
309 | 23 | protected function initSelfBlameableEvents() |
|
314 | } |
||
315 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.