Complex classes like GravityView_View 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 GravityView_View, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class GravityView_View extends Gamajo_Template_Loader { |
||
24 | |||
25 | /** |
||
26 | * Prefix for filter names. |
||
27 | * @var string |
||
28 | */ |
||
29 | protected $filter_prefix = 'gravityview'; |
||
30 | |||
31 | /** |
||
32 | * Directory name where custom templates for this plugin should be found in the theme. |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $theme_template_directory = 'gravityview'; |
||
36 | |||
37 | /** |
||
38 | * Reference to the root directory path of this plugin. |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $plugin_directory = GRAVITYVIEW_DIR; |
||
42 | |||
43 | /** |
||
44 | * Store templates locations that have already been located |
||
45 | * @var array |
||
46 | */ |
||
47 | protected $located_templates = array(); |
||
48 | |||
49 | /** |
||
50 | * The name of the template, like "list", "table", or "datatables" |
||
51 | * @var string |
||
52 | */ |
||
53 | protected $template_part_slug = ''; |
||
54 | |||
55 | /** |
||
56 | * The name of the file part, like "body" or "single" |
||
57 | * @var string |
||
58 | */ |
||
59 | protected $template_part_name = ''; |
||
60 | |||
61 | /** |
||
62 | * @var int Gravity Forms form ID |
||
63 | */ |
||
64 | protected $form_id = NULL; |
||
65 | |||
66 | /** |
||
67 | * @var int View ID |
||
68 | * @todo: this needs to be public until extensions support 1.7+ |
||
69 | */ |
||
70 | public $view_id = NULL; |
||
71 | |||
72 | /** |
||
73 | * @var array Fields for the form |
||
74 | */ |
||
75 | protected $fields = array(); |
||
76 | |||
77 | /** |
||
78 | * @var string Current screen. Defaults to "directory" or "single" |
||
79 | */ |
||
80 | protected $context = 'directory'; |
||
81 | |||
82 | /** |
||
83 | * @var int|null If in embedded post or page, the ID of it |
||
84 | */ |
||
85 | protected $post_id = NULL; |
||
86 | |||
87 | /** |
||
88 | * @var array Gravity Forms form array at ID $form_id |
||
89 | */ |
||
90 | protected $form = NULL; |
||
91 | |||
92 | /** |
||
93 | * @var array Configuration for the View |
||
94 | */ |
||
95 | protected $atts = array(); |
||
96 | |||
97 | /** |
||
98 | * @var array Entries for the current result. Single item in array for single entry View |
||
99 | */ |
||
100 | protected $entries = array(); |
||
101 | |||
102 | /** |
||
103 | * @var int Total entries count for the current result. |
||
104 | */ |
||
105 | protected $total_entries = 0; |
||
106 | |||
107 | /** |
||
108 | * @var string The label to display back links |
||
109 | */ |
||
110 | protected $back_link_label = ''; |
||
111 | |||
112 | /** |
||
113 | * @var array Array with `offset` and `page_size` keys |
||
114 | */ |
||
115 | protected $paging = array(); |
||
116 | |||
117 | /** |
||
118 | * @var array Array with `sort_field` and `sort_direction` keys |
||
119 | */ |
||
120 | protected $sorting = array(); |
||
121 | |||
122 | /** |
||
123 | * @var bool Whether to hide the results until a search is performed |
||
124 | * @since 1.5.4 |
||
125 | */ |
||
126 | protected $hide_until_searched = false; |
||
127 | |||
128 | /** |
||
129 | * Current entry in the loop |
||
130 | * @var array |
||
131 | */ |
||
132 | protected $_current_entry = array(); |
||
133 | |||
134 | /** |
||
135 | * @var array |
||
136 | */ |
||
137 | protected $_current_field = array(); |
||
138 | |||
139 | /** |
||
140 | * @var GravityView_View |
||
141 | */ |
||
142 | static $instance = NULL; |
||
143 | |||
144 | /** |
||
145 | * Construct the view object |
||
146 | * @param array $atts Associative array to set the data of |
||
147 | */ |
||
148 | 58 | function __construct( $atts = array() ) { |
|
149 | |||
150 | 58 | $atts = wp_parse_args( $atts, array( |
|
151 | 58 | 'form_id' => NULL, |
|
152 | 'view_id' => NULL, |
||
153 | 'fields' => NULL, |
||
154 | 'context' => NULL, |
||
155 | 'post_id' => NULL, |
||
156 | 'form' => NULL, |
||
157 | 'atts' => NULL, |
||
158 | ) ); |
||
159 | |||
160 | 58 | foreach ($atts as $key => $value) { |
|
161 | 58 | if( is_null( $value ) ) { |
|
162 | 58 | continue; |
|
163 | } |
||
164 | 3 | $this->{$key} = $value; |
|
165 | } |
||
166 | |||
167 | |||
168 | // Add granular overrides |
||
169 | 58 | add_filter( $this->filter_prefix . '_get_template_part', array( $this, 'add_id_specific_templates' ), 10, 3 ); |
|
170 | |||
171 | // widget logic |
||
172 | 58 | add_action( 'gravityview/template/before', array( $this, 'render_widget_hooks' ) ); |
|
173 | 58 | add_action( 'gravityview/template/after', array( $this, 'render_widget_hooks' ) ); |
|
174 | |||
175 | /** |
||
176 | * Clear the current entry after the loop is done |
||
177 | * @since 1.7.3 |
||
178 | */ |
||
179 | 58 | add_action( 'gravityview_footer', array( $this, 'clearCurrentEntry' ), 500 ); |
|
180 | |||
181 | 58 | self::$instance = &$this; |
|
182 | 58 | } |
|
183 | |||
184 | /** |
||
185 | * @param null $passed_post |
||
186 | * |
||
187 | * @return GravityView_View |
||
188 | */ |
||
189 | 65 | static function getInstance( $passed_post = NULL ) { |
|
197 | |||
198 | /** |
||
199 | * @param string|null $key The key to a specific attribute of the current field |
||
200 | * @return array|mixed|null If $key is set and attribute exists at $key, return that. If not set, return NULL. Otherwise, return current field array |
||
201 | */ |
||
202 | 51 | public function getCurrentField( $key = NULL ) { |
|
203 | |||
204 | 51 | if( !empty( $key ) ) { |
|
205 | if( isset( $this->_current_field[ $key ] ) ) { |
||
206 | return $this->_current_field[ $key ]; |
||
207 | } |
||
208 | return NULL; |
||
209 | } |
||
210 | |||
211 | 51 | return $this->_current_field; |
|
212 | } |
||
213 | |||
214 | public function setCurrentFieldSetting( $key, $value ) { |
||
215 | |||
216 | if( !empty( $this->_current_field ) ) { |
||
217 | $this->_current_field['field_settings'][ $key ] = $value; |
||
218 | } |
||
219 | |||
220 | } |
||
221 | |||
222 | public function getCurrentFieldSetting( $key ) { |
||
231 | |||
232 | /** |
||
233 | * @param array $passed_field |
||
234 | */ |
||
235 | 51 | public function setCurrentField( $passed_field ) { |
|
236 | |||
237 | 51 | $existing_field = $this->getCurrentField(); |
|
238 | |||
239 | 51 | $set_field = wp_parse_args( $passed_field, $existing_field ); |
|
240 | |||
241 | 51 | $this->_current_field = $set_field; |
|
242 | |||
243 | /** |
||
244 | * Backward compatibility |
||
245 | * @deprecated 1.6.2 |
||
246 | */ |
||
247 | 51 | $this->field_data = $set_field; |
|
248 | 51 | } |
|
249 | |||
250 | /** |
||
251 | * @param string|null $key The key to a specific field in the fields array |
||
252 | * @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
||
253 | */ |
||
254 | 24 | public function getAtts( $key = NULL ) { |
|
255 | |||
256 | 24 | if( !empty( $key ) ) { |
|
257 | 2 | if( isset( $this->atts[ $key ] ) ) { |
|
258 | 2 | return $this->atts[ $key ]; |
|
259 | } |
||
260 | return NULL; |
||
261 | } |
||
262 | |||
263 | 24 | return $this->atts; |
|
264 | } |
||
265 | |||
266 | /** |
||
267 | * @param array $atts |
||
268 | */ |
||
269 | 24 | public function setAtts( $atts ) { |
|
270 | 24 | $this->atts = $atts; |
|
271 | 24 | } |
|
272 | |||
273 | /** |
||
274 | * @return array |
||
275 | */ |
||
276 | 60 | public function getForm() { |
|
279 | |||
280 | /** |
||
281 | * @param array $form |
||
282 | */ |
||
283 | 25 | public function setForm( $form ) { |
|
284 | 25 | $this->form = $form; |
|
285 | 25 | } |
|
286 | |||
287 | /** |
||
288 | * @return int|null |
||
289 | */ |
||
290 | 25 | public function getPostId() { |
|
293 | |||
294 | /** |
||
295 | * @param int|null $post_id |
||
296 | */ |
||
297 | 24 | public function setPostId( $post_id ) { |
|
298 | 24 | $this->post_id = $post_id; |
|
299 | 24 | } |
|
300 | |||
301 | /** |
||
302 | * @return string |
||
303 | */ |
||
304 | 57 | public function getContext() { |
|
305 | 57 | return $this->context; |
|
306 | } |
||
307 | |||
308 | /** |
||
309 | * @param string $context |
||
310 | */ |
||
311 | 24 | public function setContext( $context ) { |
|
312 | 24 | $this->context = $context; |
|
313 | 24 | } |
|
314 | |||
315 | /** |
||
316 | * @param string|null $key The key to a specific field in the fields array |
||
317 | * @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
||
318 | */ |
||
319 | 24 | public function getFields( $key = null ) { |
|
320 | |||
321 | 24 | $fields = empty( $this->fields ) ? NULL : $this->fields; |
|
322 | |||
323 | 24 | if( $fields && !empty( $key ) ) { |
|
324 | 1 | $fields = isset( $fields[ $key ] ) ? $fields[ $key ] : NULL; |
|
325 | } |
||
326 | |||
327 | 24 | return $fields; |
|
328 | } |
||
329 | |||
330 | /** |
||
331 | * Get the fields for a specific context |
||
332 | * |
||
333 | * @since 1.19.2 |
||
334 | * |
||
335 | * @param string $context [Optional] "directory", "single", or "edit" |
||
336 | * |
||
337 | * @return array Array of GravityView field layout configurations |
||
338 | */ |
||
339 | 2 | public function getContextFields( $context = '' ) { |
|
340 | |||
341 | 2 | if( '' === $context ) { |
|
342 | 2 | $context = $this->getContext(); |
|
343 | } |
||
344 | |||
345 | 2 | $fields = $this->getFields(); |
|
346 | |||
347 | 2 | foreach ( (array) $fields as $key => $context_fields ) { |
|
348 | |||
349 | // Formatted as `{context}_{template id}-{zone name}`, so we want just the $context to match against |
||
350 | 2 | $matches = explode( '_', $key ); |
|
351 | |||
352 | 2 | if( isset( $matches[0] ) && $matches[0] === $context ) { |
|
353 | 2 | return $context_fields; |
|
354 | } |
||
355 | } |
||
356 | |||
357 | return array(); |
||
358 | } |
||
359 | |||
360 | /** |
||
361 | * @param array $fields |
||
362 | */ |
||
363 | 24 | public function setFields( $fields ) { |
|
364 | 24 | $this->fields = $fields; |
|
365 | 24 | } |
|
366 | |||
367 | /** |
||
368 | * @param string $key The key to a specific field in the fields array |
||
369 | * @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
||
370 | */ |
||
371 | 2 | public function getField( $key ) { |
|
372 | |||
373 | 2 | if( !empty( $key ) ) { |
|
374 | 2 | if( isset( $this->fields[ $key ] ) ) { |
|
375 | 2 | return $this->fields[ $key ]; |
|
376 | } |
||
377 | } |
||
378 | |||
379 | 1 | return NULL; |
|
380 | } |
||
381 | |||
382 | /** |
||
383 | * @param string $key The key to a specific field in the fields array |
||
384 | * @param mixed $value The value to set for the field |
||
385 | */ |
||
386 | public function setField( $key, $value ) { |
||
387 | $this->fields[ $key ] = $value; |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * @return int |
||
392 | */ |
||
393 | 29 | public function getViewId() { |
|
396 | |||
397 | /** |
||
398 | * @param int $view_id |
||
399 | */ |
||
400 | 24 | public function setViewId( $view_id ) { |
|
401 | 24 | $this->view_id = intval( $view_id ); |
|
402 | 24 | } |
|
403 | |||
404 | /** |
||
405 | * @return int |
||
406 | */ |
||
407 | 27 | public function getFormId() { |
|
410 | |||
411 | /** |
||
412 | * @param int $form_id |
||
413 | */ |
||
414 | 24 | public function setFormId( $form_id ) { |
|
415 | 24 | $this->form_id = $form_id; |
|
416 | 24 | } |
|
417 | |||
418 | /** |
||
419 | * @return array |
||
420 | */ |
||
421 | 28 | public function getEntries() { |
|
424 | |||
425 | /** |
||
426 | * @param array $entries |
||
427 | */ |
||
428 | 24 | public function setEntries( $entries ) { |
|
429 | 24 | $this->entries = $entries; |
|
430 | 24 | } |
|
431 | |||
432 | /** |
||
433 | * @return int |
||
434 | */ |
||
435 | 25 | public function getTotalEntries() { |
|
438 | |||
439 | /** |
||
440 | * @param int $total_entries |
||
441 | */ |
||
442 | 25 | public function setTotalEntries( $total_entries ) { |
|
443 | 25 | $this->total_entries = intval( $total_entries ); |
|
444 | 25 | } |
|
445 | |||
446 | /** |
||
447 | * @return array |
||
448 | */ |
||
449 | 25 | public function getPaging() { |
|
458 | |||
459 | /** |
||
460 | * @param array $paging |
||
461 | */ |
||
462 | 25 | public function setPaging( $paging ) { |
|
463 | 25 | $this->paging = $paging; |
|
464 | 25 | } |
|
465 | |||
466 | /** |
||
467 | * Get an array with pagination information |
||
468 | * |
||
469 | * @since 1.13 |
||
470 | * |
||
471 | * @return array { |
||
472 | * @type int $first The starting entry number (counter, not ID) |
||
473 | * @type int $last The last displayed entry number (counter, not ID) |
||
474 | * @type int $total The total number of entries |
||
475 | * } |
||
476 | */ |
||
477 | 2 | public function getPaginationCounts() { |
|
504 | |||
505 | /** |
||
506 | * @return array |
||
507 | */ |
||
508 | 24 | public function getSorting() { |
|
509 | |||
510 | $defaults_params = array( |
||
511 | 24 | 'sort_field' => 'date_created', |
|
512 | 'sort_direction' => 'ASC', |
||
513 | 'is_numeric' => false, |
||
514 | ); |
||
515 | |||
516 | 24 | return wp_parse_args( $this->sorting, $defaults_params ); |
|
517 | } |
||
518 | |||
519 | /** |
||
520 | * @param array $sorting |
||
521 | */ |
||
522 | 30 | public function setSorting( $sorting ) { |
|
523 | 30 | $this->sorting = $sorting; |
|
525 | |||
526 | /** |
||
527 | * @param boolean $do_replace Perform merge tag and shortcode processing on the label. Default: true. |
||
528 | * @since 2.0 |
||
529 | * |
||
530 | * @deprecated Use $template->get_back_label(); |
||
531 | * |
||
532 | * @return string |
||
533 | */ |
||
534 | 25 | public function getBackLinkLabel( $do_replace = true ) { |
|
542 | |||
543 | /** |
||
544 | * @param string $back_link_label |
||
545 | */ |
||
546 | 25 | public function setBackLinkLabel( $back_link_label ) { |
|
549 | |||
550 | /** |
||
551 | * @return boolean |
||
552 | */ |
||
553 | 2 | public function isHideUntilSearched() { |
|
556 | |||
557 | /** |
||
558 | * @param boolean $hide_until_searched |
||
559 | */ |
||
560 | public function setHideUntilSearched( $hide_until_searched ) { |
||
563 | |||
564 | /** |
||
565 | * @return string |
||
566 | */ |
||
567 | 2 | public function getTemplatePartSlug() { |
|
570 | |||
571 | /** |
||
572 | * @param string $template_part_slug |
||
573 | */ |
||
574 | 4 | public function setTemplatePartSlug( $template_part_slug ) { |
|
577 | |||
578 | /** |
||
579 | * @return string |
||
580 | */ |
||
581 | public function getTemplatePartName() { |
||
584 | |||
585 | /** |
||
586 | * @param string $template_part_name |
||
587 | */ |
||
588 | 4 | public function setTemplatePartName( $template_part_name ) { |
|
591 | |||
592 | /** |
||
593 | * Return the current entry. If in the loop, the current entry. If single entry, the currently viewed entry. |
||
594 | * @return array |
||
595 | */ |
||
596 | 57 | public function getCurrentEntry() { |
|
597 | |||
598 | 57 | if( in_array( $this->getContext(), array( 'edit', 'single') ) ) { |
|
599 | 11 | $entries = $this->getEntries(); |
|
600 | 11 | $entry = $entries[0]; |
|
601 | } else { |
||
602 | 55 | $entry = $this->_current_entry; |
|
603 | } |
||
604 | |||
605 | /** @since 1.16 Fixes DataTables empty entry issue */ |
||
606 | 57 | if ( empty( $entry ) && ! empty( $this->_current_field['entry'] ) ) { |
|
607 | 5 | $entry = $this->_current_field['entry']; |
|
608 | } |
||
609 | |||
610 | 57 | return $entry; |
|
611 | } |
||
612 | |||
613 | /** |
||
614 | * @param array $current_entry |
||
615 | * @return void |
||
616 | */ |
||
617 | 25 | public function setCurrentEntry( $current_entry ) { |
|
620 | |||
621 | /** |
||
622 | * Clear the current entry after all entries in the loop have been displayed. |
||
623 | * |
||
624 | * @since 1.7.3 |
||
625 | * @return void |
||
626 | */ |
||
627 | 17 | public function clearCurrentEntry() { |
|
630 | |||
631 | /** |
||
632 | * Render an output zone, as configured in the Admin |
||
633 | * |
||
634 | * @since 1.16.4 Added $echo parameter |
||
635 | * |
||
636 | * @param string $zone The zone name, like 'footer-left' |
||
637 | * @param array $atts |
||
638 | * @param bool $echo Whether to print the output |
||
639 | * |
||
640 | * @deprecated This will never get called in new templates. |
||
641 | * |
||
642 | * @return string|null |
||
643 | */ |
||
644 | 2 | public function renderZone( $zone = '', $atts = array(), $echo = true ) { |
|
720 | |||
721 | /** |
||
722 | * In order to improve lookup times, we store located templates in a local array. |
||
723 | * |
||
724 | * This improves performance by up to 1/2 second on a 250 entry View with 7 columns showing |
||
725 | * |
||
726 | * @inheritdoc |
||
727 | * @see Gamajo_Template_Loader::locate_template() |
||
728 | * @return null|string NULL: Template not found; String: path to template |
||
729 | */ |
||
730 | 2 | function locate_template( $template_names, $load = false, $require_once = true ) { |
|
752 | |||
753 | /** |
||
754 | * Magic Method: Instead of throwing an error when a variable isn't set, return null. |
||
755 | * @param string $name Key for the data retrieval. |
||
756 | * @return mixed|null The stored data. |
||
757 | */ |
||
758 | 3 | public function __get( $name ) { |
|
765 | |||
766 | /** |
||
767 | * Enable overrides of GravityView templates on a granular basis |
||
768 | * |
||
769 | * The loading order is: |
||
770 | * |
||
771 | * - view-[View ID]-table-footer.php |
||
772 | * - form-[Form ID]-table-footer.php |
||
773 | * - page-[ID of post or page where view is embedded]-table-footer.php |
||
774 | * - table-footer.php |
||
775 | * |
||
776 | * @see Gamajo_Template_Loader::get_template_file_names() Where the filter is |
||
777 | * @param array $templates Existing list of templates. |
||
778 | * @param string $slug Name of the template base, example: `table`, `list`, `datatables`, `map` |
||
779 | * @param string $name Name of the template part, example: `body`, `footer`, `head`, `single` |
||
780 | * |
||
781 | * @return array $templates Modified template array, merged with existing $templates values |
||
782 | */ |
||
783 | 22 | function add_id_specific_templates( $templates, $slug, $name ) { |
|
808 | |||
809 | // Load the template |
||
810 | 2 | public function render( $slug, $name, $require_once = true ) { |
|
830 | |||
831 | /** |
||
832 | * Output the widgets on before/after hooks. |
||
833 | * |
||
834 | * @param int|\GV\Template_Context $view_id_or_context The View ID or the context. |
||
835 | * |
||
836 | * @return void |
||
837 | */ |
||
838 | 21 | public function render_widget_hooks( $view_id_or_context ) { |
|
946 | |||
947 | /** |
||
948 | * Include a file inside this context. |
||
949 | * |
||
950 | * @param string $path A path to the legacy template to include. |
||
951 | * |
||
952 | * @return void |
||
953 | */ |
||
954 | 2 | public function _include( $path ) { |
|
959 | |||
960 | } |
||
961 | |||
962 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.