Complex classes like Column 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 Column, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | abstract class Column extends FilterableColumn |
||
21 | { |
||
22 | |||
23 | /** |
||
24 | * @var array |
||
25 | */ |
||
26 | protected $replacements = []; |
||
27 | |||
28 | /** |
||
29 | * @var Renderer|NULL |
||
30 | */ |
||
31 | protected $renderer; |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | protected $template; |
||
37 | |||
38 | /** |
||
39 | * @var bool|string |
||
40 | */ |
||
41 | protected $sortable = FALSE; |
||
42 | |||
43 | /** |
||
44 | * @var bool |
||
45 | */ |
||
46 | protected $sortable_reset_pagination = FALSE; |
||
47 | |||
48 | /** |
||
49 | * @var null|callable |
||
50 | */ |
||
51 | protected $sortable_callback = NULL; |
||
52 | |||
53 | /** |
||
54 | * @var array |
||
55 | */ |
||
56 | protected $sort; |
||
57 | |||
58 | /** |
||
59 | * @var bool |
||
60 | */ |
||
61 | protected $template_escaping = TRUE; |
||
62 | |||
63 | /** |
||
64 | * @var string |
||
65 | */ |
||
66 | protected $align; |
||
67 | |||
68 | /** |
||
69 | * @var array |
||
70 | */ |
||
71 | protected $template_variables = []; |
||
72 | |||
73 | /** |
||
74 | * @var callable |
||
75 | */ |
||
76 | protected $editable_callback; |
||
77 | |||
78 | /** |
||
79 | * Cached html elements |
||
80 | * @var array |
||
81 | */ |
||
82 | protected $el_cache = []; |
||
83 | |||
84 | |||
85 | /** |
||
86 | * Render row item into template |
||
87 | * @param Row $row |
||
88 | * @return mixed |
||
89 | */ |
||
90 | public function render(Row $row) |
||
91 | { |
||
92 | /** |
||
93 | * Renderer function may be used |
||
94 | */ |
||
95 | try { |
||
96 | return $this->useRenderer($row); |
||
97 | } catch (DataGridColumnRendererException $e) { |
||
|
|||
98 | /** |
||
99 | * Do not use renderer |
||
100 | */ |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Or replacements may be applied |
||
105 | */ |
||
106 | list($do_replace, $replaced) = $this->applyReplacements($row); |
||
107 | if ($do_replace) { |
||
108 | return $replaced; |
||
109 | } |
||
110 | |||
111 | return $this->getColumnValue($row); |
||
112 | } |
||
113 | |||
114 | |||
115 | /** |
||
116 | * Try to render item with custom renderer |
||
117 | * @param Row $row |
||
118 | * @return mixed |
||
119 | */ |
||
120 | public function useRenderer(Row $row) |
||
138 | |||
139 | |||
140 | /** |
||
141 | * Should be column values escaped in latte? |
||
142 | * @param bool $template_escaping |
||
143 | */ |
||
144 | public function setTemplateEscaping($template_escaping = TRUE) |
||
150 | |||
151 | |||
152 | public function isTemplateEscaped() |
||
156 | |||
157 | |||
158 | /** |
||
159 | * Set column sortable or not |
||
160 | * @param bool|string $sortable |
||
161 | */ |
||
162 | public function setSortable($sortable = TRUE) |
||
168 | |||
169 | |||
170 | /** |
||
171 | * Tell whether column is sortable |
||
172 | * @return bool |
||
173 | */ |
||
174 | public function isSortable() |
||
178 | |||
179 | |||
180 | /** |
||
181 | * Shoud be the pagination reseted after sorting? |
||
182 | * @param bool $sortable_reset_pagination |
||
183 | * @return static |
||
184 | */ |
||
185 | public function setSortableResetPagination($sortable_reset_pagination = TRUE) |
||
191 | |||
192 | |||
193 | /** |
||
194 | * DO reset pagination after sorting? |
||
195 | * @return bool |
||
196 | */ |
||
197 | public function sortableResetPagination() |
||
201 | |||
202 | |||
203 | /** |
||
204 | * Set custom ORDER BY clause |
||
205 | * @param callable $sortable_callback |
||
206 | * @return static |
||
207 | */ |
||
208 | public function setSortableCallback(callable $sortable_callback) |
||
214 | |||
215 | |||
216 | /** |
||
217 | * Get custom ORDER BY clause |
||
218 | * @return callable|null |
||
219 | */ |
||
220 | public function getSortableCallback() |
||
224 | |||
225 | |||
226 | /** |
||
227 | * Get column to sort by |
||
228 | * @return string |
||
229 | */ |
||
230 | public function getSortingColumn() |
||
234 | |||
235 | |||
236 | /** |
||
237 | * Get column name |
||
238 | * @return string |
||
239 | */ |
||
240 | public function getColumnName() |
||
244 | |||
245 | |||
246 | /** |
||
247 | * Get column value of row item |
||
248 | * @param Row $row |
||
249 | * @return mixed |
||
250 | */ |
||
251 | public function getColumnValue(Row $row) |
||
252 | { |
||
253 | return $row->getValue($this->column); |
||
254 | } |
||
255 | |||
256 | |||
257 | /** |
||
258 | * @return string |
||
259 | */ |
||
260 | public function getName() |
||
264 | |||
265 | |||
266 | /** |
||
267 | * Set column replacements |
||
268 | * @param array $replacements |
||
269 | * @return Column |
||
270 | */ |
||
271 | public function setReplacement(array $replacements) |
||
277 | |||
278 | |||
279 | /** |
||
280 | * Tell whether columns has replacements |
||
281 | * @return bool |
||
282 | */ |
||
283 | public function hasReplacements() |
||
287 | |||
288 | |||
289 | /** |
||
290 | * Apply replacements |
||
291 | * @param Row $row |
||
292 | * @return array |
||
293 | */ |
||
294 | public function applyReplacements(Row $row) |
||
295 | { |
||
296 | $value = $row->getValue($this->column); |
||
297 | |||
298 | if ((is_scalar($value) || is_null($value)) && isset($this->replacements[$value])) { |
||
299 | return [TRUE, $this->replacements[$value]]; |
||
300 | } |
||
301 | |||
302 | return [FALSE, NULL]; |
||
303 | } |
||
304 | |||
305 | |||
306 | /** |
||
307 | * Set renderer callback and (it may be optional - the condition callback will decide) |
||
308 | * @param callable $renderer |
||
309 | */ |
||
310 | public function setRenderer($renderer, $condition_callback = NULL) |
||
311 | { |
||
312 | if ($this->hasReplacements()) { |
||
313 | throw new DataGridException( |
||
314 | "Use either Column::setReplacement() or Column::setRenderer, not both." |
||
315 | ); |
||
316 | } |
||
317 | |||
318 | if (!is_callable($renderer)) { |
||
319 | throw new DataGridException( |
||
320 | "Renderer (method Column::setRenderer()) must be callable." |
||
321 | ); |
||
322 | } |
||
323 | |||
324 | if (NULL != $condition_callback && !is_callable($condition_callback)) { |
||
325 | throw new DataGridException( |
||
326 | "Renderer (method Column::setRenderer()) must be callable." |
||
327 | ); |
||
328 | } |
||
329 | |||
330 | $this->renderer = new Renderer($renderer, $condition_callback); |
||
331 | |||
332 | return $this; |
||
333 | } |
||
334 | |||
335 | |||
336 | /** |
||
337 | * Set renderer callback just if condition is truthy |
||
338 | * @param callable $renderer |
||
339 | */ |
||
340 | public function setRendererOnCondition($renderer, $condition_callback) |
||
344 | |||
345 | |||
346 | /** |
||
347 | * Return custom renderer callback |
||
348 | * @return Renderer|null |
||
349 | */ |
||
350 | public function getRenderer() |
||
354 | |||
355 | |||
356 | /** |
||
357 | * Column may have its own template |
||
358 | * @param string $template |
||
359 | */ |
||
360 | public function setTemplate($template, array $template_variables = []) |
||
367 | |||
368 | |||
369 | /** |
||
370 | * Column can have variables that will be passed to custom template scope |
||
371 | * @return array |
||
372 | */ |
||
373 | public function getTemplateVariables() |
||
377 | |||
378 | |||
379 | /** |
||
380 | * Tell whether column has its owntemplate |
||
381 | * @return bool |
||
382 | */ |
||
383 | public function hasTemplate() |
||
387 | |||
388 | |||
389 | /** |
||
390 | * Get column template path |
||
391 | * @return string |
||
392 | */ |
||
393 | public function getTemplate() |
||
397 | |||
398 | |||
399 | /** |
||
400 | * Tell whether data source is sorted by this collumn |
||
401 | * @return bool |
||
402 | */ |
||
403 | public function isSortedBy() |
||
407 | |||
408 | |||
409 | /** |
||
410 | * Tell column his sorting options |
||
411 | * @param array $sort |
||
412 | */ |
||
413 | public function setSort(array $sort) |
||
419 | |||
420 | |||
421 | /** |
||
422 | * What sorting will be applied after next click? |
||
423 | * @return array |
||
424 | */ |
||
425 | public function getSortNext() |
||
435 | |||
436 | |||
437 | /** |
||
438 | * Is sorting ascending? |
||
439 | * @return bool |
||
440 | */ |
||
441 | public function isSortAsc() |
||
445 | |||
446 | |||
447 | /** |
||
448 | * Set column alignment |
||
449 | * @param string $align |
||
450 | */ |
||
451 | public function setAlign($align) |
||
457 | |||
458 | |||
459 | /** |
||
460 | * Has column some alignment? |
||
461 | * @return bool [description] |
||
462 | */ |
||
463 | public function hasAlign() |
||
467 | |||
468 | |||
469 | /** |
||
470 | * Get column alignment |
||
471 | * @return string |
||
472 | */ |
||
473 | public function getAlign() |
||
477 | |||
478 | |||
479 | /** |
||
480 | * Set callback that will be called after inline editing |
||
481 | * @param callable $editable_callback |
||
482 | */ |
||
483 | public function setEditableCallback(callable $editable_callback) |
||
489 | |||
490 | |||
491 | /** |
||
492 | * Return callback that is used after inline editing |
||
493 | * @return callable |
||
494 | */ |
||
495 | public function getEditableCallback() |
||
499 | |||
500 | |||
501 | /** |
||
502 | * Is column editable? |
||
503 | * @return bool |
||
504 | */ |
||
505 | public function isEditable() |
||
509 | |||
510 | |||
511 | /** |
||
512 | * Set attributes for both th and td element |
||
513 | * @param array $attrs |
||
514 | * @return static |
||
515 | */ |
||
516 | public function addAttributes(array $attrs) |
||
523 | |||
524 | |||
525 | /** |
||
526 | * Get th/td column element |
||
527 | * @param string $tag th|td |
||
528 | * @param string $key |
||
529 | * @param Row|NULL $row |
||
530 | * @return Html |
||
531 | */ |
||
532 | public function getElementPrototype($tag, $key = NULL, Row $row = NULL) |
||
572 | |||
573 | |||
574 | /** |
||
575 | * Create link to custom destination |
||
576 | * @param string $href |
||
577 | * @param array $params |
||
578 | * @return string |
||
579 | * @throws DataGridHasToBeAttachedToPresenterComponentException |
||
580 | * @throws InvalidArgumentException |
||
581 | */ |
||
582 | protected function createLink($href, $params) |
||
606 | |||
607 | |||
608 | /** |
||
609 | * Get row item params (E.g. action may be called id => $item->id, name => $item->name, ...) |
||
610 | * @param Row $row |
||
611 | * @param array $params_list |
||
612 | * @return array |
||
613 | */ |
||
614 | protected function getItemParams(Row $row, array $params_list) |
||
624 | |||
625 | } |
||
626 |