Complex classes like License_Handler 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 License_Handler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class License_Handler { |
||
15 | /** |
||
16 | * @var \GV\Addon_Settings The global addon settings binding. |
||
17 | */ |
||
18 | private $settings; |
||
19 | |||
20 | const name = 'GravityView'; |
||
21 | const author = 'Katz Web Services, Inc.'; |
||
22 | const url = 'https://gravityview.co'; |
||
23 | |||
24 | /** |
||
25 | * Post ID on gravityview.co |
||
26 | * @since 1.15 |
||
27 | */ |
||
28 | const item_id = 17; |
||
29 | |||
30 | /** |
||
31 | * Name of the transient used to store license status for GV |
||
32 | * @since 1.17 |
||
33 | */ |
||
34 | const status_transient_key = 'gravityview_edd-activate_valid'; |
||
35 | |||
36 | /** |
||
37 | * @var string Key used to store active GravityView/Gravity Forms plugin data |
||
38 | * @since 1.15 |
||
39 | */ |
||
40 | const related_plugins_key = 'gravityview_related_plugins'; |
||
41 | |||
42 | /** @var \GV\EDD_SL_Plugin_Updater */ |
||
43 | private $EDD_SL_Plugin_Updater; |
||
44 | |||
45 | /** |
||
46 | * @var \GV\License_Handler |
||
47 | */ |
||
48 | private static $__instance; |
||
49 | |||
50 | 1 | private function __construct( $settings ) { |
|
65 | |||
66 | /** |
||
67 | * @return \GV\License_Handler The global instance. |
||
68 | */ |
||
69 | 2 | public static function get( $settings = null ) { |
|
75 | |||
76 | /** |
||
77 | * Generate the array of settings passed to the EDD license call |
||
78 | * |
||
79 | * @since 1.7.4 |
||
80 | * |
||
81 | * @param string $action The action to send to edd, such as `check_license` |
||
82 | * @param string $license The license key to have passed to EDD |
||
83 | * |
||
84 | * @return array |
||
85 | */ |
||
86 | 1 | private function _get_edd_settings( $action = '', $license = '' ) { |
|
108 | |||
109 | /** |
||
110 | * Include the EDD plugin updater class, if not exists |
||
111 | * |
||
112 | * @since 1.7.4 |
||
113 | * @since 1.21.5.3 Changed visibility of method to public |
||
114 | * |
||
115 | * @return void |
||
116 | */ |
||
117 | 1 | public function setup_edd() { |
|
129 | |||
130 | /** |
||
131 | * Perform the call to EDD based on the AJAX call or passed data |
||
132 | * |
||
133 | * @since 1.7.4 |
||
134 | * |
||
135 | * @param array $array { |
||
136 | * @type string $license The license key |
||
137 | * @type string $edd_action The EDD action to perform, like `check_license` |
||
138 | * @type string $field_id The ID of the field to check |
||
139 | * @type boolean $update Whether to update plugin settings. Prevent updating the data by setting an `update` key to false |
||
140 | * @type string $format If `object`, return the object of the license data. Else, return the JSON-encoded object |
||
141 | * } |
||
142 | * @param boolean $cap_check Require `gravityview_edit_settings` capability from current user. |
||
143 | * |
||
144 | * @return mixed|string|void |
||
145 | */ |
||
146 | 1 | public function license_call( $array = array(), $cap_check = true ) { |
|
147 | |||
148 | 1 | $is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX ); |
|
149 | 1 | $data = empty( $array ) ? Utils::_POST( 'data', array() ) : $array; |
|
150 | |||
151 | 1 | $data = wp_parse_args( $data, array( |
|
152 | 1 | 'license' => '', |
|
153 | 'edd_action' => '', |
||
154 | 'field_id' => '', |
||
155 | 'update' => '', |
||
156 | 'format' => 'json', |
||
157 | ) ); |
||
158 | |||
159 | 1 | if ( $is_ajax && empty( $data['license'] ) ) { |
|
160 | die( -1 ); |
||
161 | } |
||
162 | |||
163 | // If the user isn't allowed to edit settings, show an error message |
||
164 | 1 | if ( $cap_check && ! \GVCommon::has_cap( 'gravityview_edit_settings' ) ) { |
|
165 | 1 | $license_data = new \stdClass(); |
|
166 | 1 | $license_data->error = 'capability'; |
|
167 | 1 | $license_data->message = $this->get_license_message( $license_data ); |
|
168 | 1 | $json = json_encode( $license_data ); |
|
169 | } else { |
||
170 | 1 | $license = esc_attr( Utils::get( $data, 'license' ) ); |
|
171 | 1 | $license_data = $this->_license_get_remote_response( $data, $license ); |
|
172 | |||
173 | // Empty is returned when there's an error. |
||
174 | 1 | if ( empty( $license_data ) ) { |
|
175 | 1 | if ( $is_ajax ) { |
|
176 | exit( json_encode( array() ) ); |
||
177 | } else { // Non-ajax call |
||
178 | 1 | return json_encode( array() ); |
|
179 | } |
||
180 | } |
||
181 | |||
182 | 1 | $license_data->details = $this->license_details( $license_data ); |
|
183 | 1 | $license_data->message = $this->get_license_message( $license_data ); |
|
184 | |||
185 | 1 | $json = json_encode( $license_data ); |
|
186 | |||
187 | 1 | $update_license = Utils::get( $data, 'update' ) || 'gravityview_license' === Utils::_POST('action'); |
|
188 | |||
189 | 1 | $is_check_action_button = ( 'check_license' === Utils::get( $data, 'edd_action' ) && defined( 'DOING_AJAX' ) && DOING_AJAX ); |
|
190 | |||
191 | 1 | if ( $is_check_action_button ) { |
|
192 | delete_transient( self::status_transient_key ); |
||
193 | |||
194 | // Failed is the response from trying to de-activate a license and it didn't work. |
||
195 | // This likely happened because people entered in a different key and clicked "Deactivate", |
||
196 | // meaning to deactivate the original key. We don't want to save this response, since it is |
||
197 | // most likely a mistake. |
||
198 | 1 | } else if ( $license_data->license !== 'failed' && $update_license ) { |
|
199 | |||
200 | 1 | if ( ! empty( $data['field_id'] ) ) { |
|
201 | 1 | set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS ); |
|
202 | } |
||
203 | |||
204 | 1 | $this->license_call_update_settings( $license_data, $data ); |
|
205 | } |
||
206 | } |
||
207 | |||
208 | 1 | if ( $is_ajax ) { |
|
209 | exit( $json ); |
||
210 | } else { // Non-ajax call |
||
211 | 1 | return ( Utils::_GET( 'format', Utils::get( $data, 'format' ) ) === 'object' ) ? $license_data : $json; |
|
212 | } |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Generate the status message displayed in the license field |
||
217 | * |
||
218 | * @since 1.7.4 |
||
219 | * @param $license_data |
||
220 | * |
||
221 | * @return string |
||
222 | */ |
||
223 | 2 | private function get_license_message( $license_data ) { |
|
241 | |||
242 | /** |
||
243 | * Allow pure HTML in settings fields |
||
244 | * |
||
245 | * @since 1.17 |
||
246 | * |
||
247 | * @param array $response License response |
||
248 | * |
||
249 | * @return string `html` key of the $field |
||
250 | */ |
||
251 | 2 | public function license_details( $response = array() ) { |
|
298 | |||
299 | /** |
||
300 | * Display possible upgrades for a license |
||
301 | * |
||
302 | * @since 1.17 |
||
303 | * |
||
304 | * @param array $upgrades Array of upgrade paths, returned from the GV website |
||
305 | * |
||
306 | * @return string HTML list of upgrades available for the current license |
||
307 | */ |
||
308 | 1 | private function get_upgrade_html( $upgrades ) { |
|
348 | |||
349 | /** |
||
350 | * Generate the status message box HTML based on the current status |
||
351 | * |
||
352 | * @since 1.7.4 |
||
353 | * @param $message |
||
354 | * @param string $class |
||
355 | * |
||
356 | * @return string |
||
357 | */ |
||
358 | 1 | private function generate_license_box( $message, $class = '' ) { |
|
365 | |||
366 | /** |
||
367 | * Override the text used in the GravityView EDD license Javascript |
||
368 | * |
||
369 | * @param array|null $status Status to get. If empty, get all strings. |
||
370 | * @param object|null $license_data Object with license data |
||
371 | * @return array Modified array of content |
||
372 | */ |
||
373 | 1 | public function strings( $status = NULL, $license_data = null ) { |
|
397 | |||
398 | /** |
||
399 | * URL to direct license renewal, or if license key is not set, then just the account page |
||
400 | * @since 1.13.1 |
||
401 | * @param object|null $license_data Object with license data |
||
402 | * @return string Renewal or account URL |
||
403 | */ |
||
404 | 1 | private function get_license_renewal_url( $license_data ) { |
|
419 | |||
420 | /** |
||
421 | * Perform the call |
||
422 | * |
||
423 | * @return array|\WP_Error |
||
424 | */ |
||
425 | 1 | private function _license_get_remote_response( $data, $license = '' ) { |
|
457 | |||
458 | /** |
||
459 | * Update the license after fetching it |
||
460 | * @param object $license_data |
||
461 | * @return void |
||
462 | */ |
||
463 | 1 | private function license_call_update_settings( $license_data, $data ) { |
|
472 | |||
473 | 2 | public function settings_edd_license_activation( $field, $echo ) { |
|
537 | |||
538 | /** |
||
539 | * When the status transient expires (or is deleted on activation), re-check the status |
||
540 | * |
||
541 | * @since 1.17 |
||
542 | * |
||
543 | * @return void |
||
544 | */ |
||
545 | 1 | public function refresh_license_status() { |
|
567 | |||
568 | /** |
||
569 | * Check the GravityView license information |
||
570 | * |
||
571 | * @since 1.19.3 |
||
572 | * @param bool $force Whether to force checking license, even if AJAX |
||
573 | * |
||
574 | * @return void |
||
575 | */ |
||
576 | 1 | public function check_license() { |
|
624 | |||
625 | /** |
||
626 | * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check. |
||
627 | * |
||
628 | * @since 1.9 |
||
629 | * @access public |
||
630 | * |
||
631 | * @return array |
||
632 | */ |
||
633 | 1 | public function get_site_data() { |
|
634 | 1 | $data = array(); |
|
635 | |||
636 | 1 | $theme_data = wp_get_theme(); |
|
637 | 1 | $theme = $theme_data->Name . ' ' . $theme_data->Version; |
|
638 | |||
639 | 1 | $data['gv_version'] = Plugin::$version; |
|
640 | 1 | $data['php_version'] = phpversion(); |
|
641 | 1 | $data['wp_version'] = get_bloginfo( 'version' ); |
|
642 | 1 | $data['gf_version'] = \GFForms::$version; |
|
643 | 1 | $data['server'] = Utils::get( $_SERVER, 'SERVER_SOFTWARE' ); |
|
644 | 1 | $data['multisite'] = is_multisite(); |
|
645 | 1 | $data['theme'] = $theme; |
|
646 | 1 | $data['url'] = home_url(); |
|
647 | 1 | $data['license_key'] = $this->settings->get( 'license_key' ); |
|
648 | 1 | $data['beta'] = $this->settings->get( 'beta' ); |
|
649 | |||
650 | // View Data |
||
651 | 1 | $gravityview_posts = wp_count_posts( 'gravityview', 'readable' ); |
|
652 | |||
653 | 1 | $data['view_count'] = null; |
|
654 | 1 | $data['view_first'] = null; |
|
655 | 1 | $data['view_latest'] = null; |
|
656 | |||
657 | 1 | if ( $gravityview_posts->publish ) { |
|
658 | 1 | $data['view_count'] = $gravityview_posts->publish; |
|
659 | |||
660 | 1 | $first = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=ASC' ); |
|
661 | 1 | $latest = get_posts( 'numberposts=1&post_type=gravityview&post_status=publish&order=DESC' ); |
|
662 | |||
663 | 1 | if ( $first = array_shift( $first ) ) { |
|
664 | 1 | $data['view_first'] = $first->post_date; |
|
665 | } |
||
666 | 1 | if ( $latest = array_pop( $latest ) ) { |
|
667 | 1 | $data['view_latest'] = $latest->post_date; |
|
668 | } |
||
669 | } |
||
670 | |||
671 | // Form counts |
||
672 | 1 | if ( class_exists( 'GFFormsModel' ) ) { |
|
673 | 1 | $form_data = \GFFormsModel::get_form_count(); |
|
674 | 1 | $data['forms_total'] = Utils::get( $form_data, 'total', 0 ); |
|
675 | 1 | $data['forms_active'] = Utils::get( $form_data, 'active', 0 ); |
|
676 | 1 | $data['forms_inactive'] = Utils::get( $form_data, 'inactive', 0 ); |
|
677 | 1 | $data['forms_trash'] = Utils::get( $form_data, 'inactive', 0 ); |
|
678 | } |
||
679 | |||
680 | // Retrieve current plugin information |
||
681 | 1 | if ( ! function_exists( 'get_plugins' ) ) { |
|
682 | include ABSPATH . '/wp-admin/includes/plugin.php'; |
||
683 | } |
||
684 | |||
685 | 1 | $data['integrations'] = self::get_related_plugins_and_extensions(); |
|
686 | 1 | $data['active_plugins'] = get_option( 'active_plugins', array() ); |
|
687 | 1 | $data['inactive_plugins'] = array(); |
|
688 | 1 | $data['locale'] = get_locale(); |
|
689 | |||
690 | // Validate request on the GV server |
||
691 | 1 | $data['hash'] = 'gv_version.url.locale:' . sha1( $data['gv_version'] . $data['url'] . $data['locale'] ); |
|
692 | |||
693 | 1 | return $data; |
|
694 | } |
||
695 | |||
696 | /** |
||
697 | * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues. |
||
698 | * |
||
699 | * @since 1.15 |
||
700 | * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks |
||
701 | */ |
||
702 | 1 | static public function get_related_plugins_and_extensions( $implode = '<br />' ) { |
|
733 | |||
734 | /** |
||
735 | * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions() |
||
736 | * |
||
737 | * @see get_related_plugins_and_extensions() |
||
738 | * @since 1.15 |
||
739 | */ |
||
740 | 1 | public function flush_related_plugins_transient() { |
|
745 | } |
||
746 |
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.