Complex classes like DatasetTrait 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 DatasetTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | trait DatasetTrait { |
||
13 | /** |
||
14 | * @var int |
||
15 | */ |
||
16 | private $offset = 0; |
||
17 | |||
18 | /** |
||
19 | * @var int |
||
20 | */ |
||
21 | private $limit = 0; |
||
22 | |||
23 | /** |
||
24 | * @var string[] |
||
25 | */ |
||
26 | private $order; |
||
27 | |||
28 | /** |
||
29 | * Get the dataset array. |
||
30 | * |
||
31 | * @return array |
||
32 | */ |
||
33 | abstract public function getData(); |
||
34 | |||
35 | 1 | public function getPage() { |
|
43 | |||
44 | 3 | public function setPage($page) { |
|
52 | |||
53 | /** |
||
54 | * Retrieve an external iterator |
||
55 | * @link http://php.net/manual/en/iteratoraggregate.getiterator.php |
||
56 | * @return Traversable Returns a generator of all rows. |
||
57 | */ |
||
58 | 4 | public function getIterator() { |
|
61 | |||
62 | 10 | public function fetchAll($mode = 0, ...$args) { |
|
63 | 10 | if ($mode === 0) { |
|
64 | 1 | return $this->getData(); |
|
65 | } |
||
66 | |||
67 | switch ($mode) { |
||
68 | 9 | case PDO::FETCH_COLUMN: |
|
69 | 3 | $result = $this->fetchArrayColumn(reset($args) ?: 0); |
|
70 | 3 | break; |
|
71 | 6 | case PDO::FETCH_COLUMN | PDO::FETCH_GROUP; |
|
72 | 3 | $result = $this->fetchArrayColumn(0, reset($args) ?: 0, true); |
|
73 | 3 | break; |
|
74 | 3 | case PDO::FETCH_KEY_PAIR: |
|
75 | 3 | $result = $this->fetchArrayColumn(1, 0); |
|
76 | 3 | break; |
|
77 | case PDO::FETCH_UNIQUE: |
||
78 | $result = $this->fetchArrayColumn(null, reset($args) ?: 0); |
||
79 | break; |
||
80 | case PDO::FETCH_OBJ: |
||
81 | $result = array_map(function ($row) { |
||
82 | return (object)$row; |
||
83 | }, $this->getData()); |
||
84 | break; |
||
85 | case PDO::FETCH_ASSOC: |
||
86 | $result = array_map(function ($row) { |
||
87 | return (array)$row; |
||
88 | }, $this->getData()); |
||
89 | break; |
||
90 | default: |
||
91 | // Don't know what to do, return null. |
||
92 | $result = null; |
||
93 | } |
||
94 | 9 | return $result; |
|
95 | } |
||
96 | |||
97 | /** |
||
98 | * Fetch the data and perform a quasi-{@link array_column()} operation on it. |
||
99 | * |
||
100 | * @param string|int|null $columnKey The key or ordinal of the value or **null** to return the entire row. |
||
101 | * @param string|int|null $indexKey The key or ordinal of the index or **null** to not index the data. |
||
102 | * @param bool $grouped If true the result will be grouped by {@link $indexKey} and each value will be an array of rows. |
||
103 | * @return array Returns the array of results. |
||
104 | */ |
||
105 | 9 | public function fetchArrayColumn($columnKey = null, $indexKey = null, $grouped = false) { |
|
106 | 9 | $arr = $this->getData(); |
|
107 | |||
108 | 9 | if (empty($arr)) { |
|
109 | return []; |
||
110 | } |
||
111 | |||
112 | 9 | $firstRow = reset($arr); |
|
113 | |||
114 | 9 | if (is_int($columnKey) || is_int($indexKey)) { |
|
115 | 9 | $i = 0; |
|
116 | 9 | foreach ($firstRow as $name => $value) { |
|
117 | 9 | if ($i === $columnKey) { |
|
118 | 9 | $columnKey = $name; |
|
119 | } |
||
120 | |||
121 | 9 | if ($i === $indexKey) { |
|
122 | 6 | $indexKey = $name; |
|
123 | } |
||
124 | |||
125 | 9 | if (!(is_int($columnKey) || is_int($indexKey))) { |
|
126 | 9 | break; |
|
127 | } |
||
128 | 9 | $i++; |
|
129 | } |
||
130 | } |
||
131 | |||
132 | 9 | if (!$grouped && is_array($firstRow)) { |
|
133 | 2 | return array_column($arr, $columnKey, $indexKey); |
|
134 | } else { |
||
135 | 7 | $result = []; |
|
136 | |||
137 | 7 | foreach ($arr as $i => $row) { |
|
138 | 7 | if (is_array($row) || $row instanceof \ArrayAccess ) { |
|
139 | 4 | $value = $columnKey === null ? $row : $row[$columnKey]; |
|
140 | 4 | $index = $indexKey === null ? $i : $row[$indexKey]; |
|
141 | } else { |
||
142 | 3 | $value = $columnKey === null ? $row : $row->$columnKey; |
|
143 | 3 | $index = $indexKey === null ? $i : $row->$indexKey; |
|
144 | } |
||
145 | |||
146 | 7 | if ($grouped) { |
|
147 | 3 | $result[$index][] = $value; |
|
148 | } else { |
||
149 | 7 | $result[$index] = $value; |
|
150 | } |
||
151 | } |
||
152 | |||
153 | 7 | return $result; |
|
154 | } |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Get the first row of data. |
||
159 | * |
||
160 | * @return mixed|null Returns the first row or **null** if there is no data. |
||
161 | */ |
||
162 | 1 | public function firstRow() { |
|
167 | |||
168 | /** |
||
169 | * Get the number of records queried. |
||
170 | * |
||
171 | * @return int Returns the count. |
||
172 | */ |
||
173 | 11 | public function count() { |
|
176 | |||
177 | /** |
||
178 | * Specify data which should be serialized to JSON |
||
179 | * @link http://php.net/manual/en/jsonserializable.jsonserialize.php |
||
180 | * @return mixed data which can be serialized by <b>json_encode</b>, |
||
181 | * which is a value of any type other than a resource. |
||
182 | * @since 5.4.0 |
||
183 | */ |
||
184 | public function jsonSerialize() { |
||
187 | |||
188 | /** |
||
189 | * Get the offset. |
||
190 | * |
||
191 | * @return int Returns the offset. |
||
192 | */ |
||
193 | 2 | public function getOffset() { |
|
196 | |||
197 | /** |
||
198 | * Set the offset. |
||
199 | * |
||
200 | * @param int $offset |
||
201 | * @return $this |
||
202 | */ |
||
203 | 1 | public function setOffset($offset) { |
|
211 | |||
212 | /** |
||
213 | * Get the limit. |
||
214 | * |
||
215 | * @return int Returns the limit. |
||
216 | */ |
||
217 | 4 | public function getLimit() { |
|
220 | |||
221 | /** |
||
222 | * Set the limit. |
||
223 | * |
||
224 | * @param int $limit |
||
225 | * @return $this |
||
226 | */ |
||
227 | 2 | public function setLimit($limit) { |
|
235 | |||
236 | /** |
||
237 | * Get the sort order. |
||
238 | * |
||
239 | * @return string[] Returns an array of column names, optionally prefixed with "-" to denote descending order. |
||
240 | */ |
||
241 | 4 | public function getOrder() { |
|
244 | |||
245 | /** |
||
246 | * Set the sort order. |
||
247 | * |
||
248 | * @param string ...$columns The column names to sort by, optionally prefixed with "-" to denote descending order. |
||
249 | * @return $this |
||
250 | */ |
||
251 | public function setOrder(...$columns) { |
||
255 | } |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.