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 | do_action('gravityview/admin_installer/delete_downloads_data', true ); |
|
192 | |||
193 | 1 | if ( $is_check_action_button ) { |
|
194 | delete_transient( self::status_transient_key ); |
||
195 | |||
196 | // Failed is the response from trying to de-activate a license and it didn't work. |
||
197 | // This likely happened because people entered in a different key and clicked "Deactivate", |
||
198 | // meaning to deactivate the original key. We don't want to save this response, since it is |
||
199 | // most likely a mistake. |
||
200 | 1 | } else if ( $license_data->license !== 'failed' && $update_license ) { |
|
201 | |||
202 | 1 | if ( ! empty( $data['field_id'] ) ) { |
|
203 | 1 | set_transient( self::status_transient_key, $license_data, DAY_IN_SECONDS ); |
|
204 | } |
||
205 | |||
206 | 1 | $this->license_call_update_settings( $license_data, $data ); |
|
207 | } |
||
208 | } |
||
209 | |||
210 | 1 | if ( $is_ajax ) { |
|
211 | exit( $json ); |
||
212 | } else { // Non-ajax call |
||
213 | 1 | return ( Utils::_GET( 'format', Utils::get( $data, 'format' ) ) === 'object' ) ? $license_data : $json; |
|
214 | } |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Generate the status message displayed in the license field |
||
219 | * |
||
220 | * @since 1.7.4 |
||
221 | * @param $license_data |
||
222 | * |
||
223 | * @return string |
||
224 | */ |
||
225 | 2 | private function get_license_message( $license_data ) { |
|
226 | 2 | if ( empty( $license_data ) ) { |
|
227 | 2 | $message = ''; |
|
228 | } else { |
||
229 | 1 | if( ! empty( $license_data->error ) ) { |
|
230 | 1 | $class = 'error'; |
|
231 | 1 | $string_key = $license_data->error; |
|
232 | 1 | } else { $class = $license_data->license; |
|
233 | 1 | $string_key = $license_data->license; |
|
234 | } |
||
235 | |||
236 | 1 | $message = sprintf( '<p><strong>%s: %s</strong></p>', $this->strings( 'status' ), $this->strings( $string_key, $license_data ) ); |
|
237 | |||
238 | 1 | $message = $this->generate_license_box( $message, $class ); |
|
239 | } |
||
240 | |||
241 | 2 | return $message; |
|
242 | } |
||
243 | |||
244 | /** |
||
245 | * Allow pure HTML in settings fields |
||
246 | * |
||
247 | * @since 1.17 |
||
248 | * |
||
249 | * @param array $response License response |
||
250 | * |
||
251 | * @return string `html` key of the $field |
||
252 | */ |
||
253 | 2 | public function license_details( $response = array() ) { |
|
254 | |||
255 | 2 | $response = (array) $response; |
|
256 | |||
257 | 2 | $return = ''; |
|
258 | 2 | $wrapper = '<span class="gv-license-details" aria-live="polite" aria-busy="false">%s</span>'; |
|
259 | |||
260 | 2 | if ( ! empty( $response['license_key'] ) ) { |
|
261 | 1 | $return .= '<h3>' . esc_html__( 'License Details:', 'gravityview' ) . '</h3>'; |
|
262 | |||
263 | 1 | if ( in_array( Utils::get( $response, 'license' ), array( 'invalid', 'deactivated' ) ) ) { |
|
264 | 1 | $return .= $this->strings( $response['license'], $response ); |
|
265 | 1 | } elseif ( ! empty( $response['license_name'] ) ) { |
|
266 | $response_keys = array( |
||
267 | 1 | 'license_name' => '', |
|
268 | 'license_limit' => '', |
||
269 | 'customer_name' => '', |
||
270 | 'customer_email' => '', |
||
271 | 'site_count' => '', |
||
272 | 'expires' => '', |
||
273 | 'upgrades' => '' |
||
274 | ); |
||
275 | |||
276 | // Make sure all the keys are set |
||
277 | 1 | $response = wp_parse_args( $response, $response_keys ); |
|
278 | |||
279 | 1 | $login_link = sprintf( '<a href="%s" class="howto" rel="external">%s</a>', esc_url( sprintf( 'https://gravityview.co/wp-login.php?username=%s', $response['customer_email'] ) ), esc_html__( 'Access your GravityView account', 'gravityview' ) ); |
|
280 | 1 | $local_text = ( ! empty( $response['is_local'] ) ? '<span class="howto">' . __( 'This development site does not count toward license activation limits', 'gravityview' ) . '</span>' : '' ); |
|
281 | 1 | $license_limit = empty( $response['license_limit'] ) ? __( 'Unlimited', 'gravityview' ) : (int) $response['license_limit']; |
|
282 | |||
283 | $details = array( |
||
284 | 1 | 'license' => sprintf( esc_html__( 'License level: %s', 'gravityview' ), esc_html( $response['license_name'] ), esc_html( $response['license_limit'] ) ), |
|
285 | 1 | 'licensed_to' => sprintf( esc_html_x( 'Licensed to: %1$s (%2$s)', '1: Customer name; 2: Customer email', 'gravityview' ), esc_html__( $response['customer_name'], 'gravityview' ), esc_html__( $response['customer_email'], 'gravityview' ) ) . $login_link, |
|
286 | 1 | 'activations' => sprintf( esc_html__( 'Activations: %d of %s sites', 'gravityview' ), intval( $response['site_count'] ), esc_html( $license_limit ) ) . $local_text, |
|
287 | 1 | 'expires' => 'lifetime' === $response['expires'] ? '' : sprintf( esc_html__( 'Renew on: %s', 'gravityview' ), date_i18n( get_option( 'date_format' ), strtotime( $response['expires'] ) - DAY_IN_SECONDS ) ), |
|
288 | 1 | 'upgrade' => $this->get_upgrade_html( $response['upgrades'] ), |
|
289 | ); |
||
290 | |||
291 | 1 | if ( ! empty( $response['error'] ) && 'expired' === $response['error'] ) { |
|
292 | unset( $details['upgrade'] ); |
||
293 | $details['expires'] = '<div class="error inline"><p>' . $this->strings( 'expired', $response ) . '</p></div>'; |
||
294 | } |
||
295 | |||
296 | 1 | $return .= '<ul><li>' . implode( '</li><li>', array_filter( $details ) ) . '</li></ul>'; |
|
297 | } |
||
298 | } |
||
299 | |||
300 | 2 | return sprintf( $wrapper, $return ); |
|
301 | } |
||
302 | |||
303 | /** |
||
304 | * Display possible upgrades for a license |
||
305 | * |
||
306 | * @since 1.17 |
||
307 | * |
||
308 | * @param array $upgrades Array of upgrade paths, returned from the GV website |
||
309 | * |
||
310 | * @return string HTML list of upgrades available for the current license |
||
311 | */ |
||
312 | 1 | private function get_upgrade_html( $upgrades ) { |
|
352 | |||
353 | /** |
||
354 | * Generate the status message box HTML based on the current status |
||
355 | * |
||
356 | * @since 1.7.4 |
||
357 | * @param $message |
||
358 | * @param string $class |
||
359 | * |
||
360 | * @return string |
||
361 | */ |
||
362 | 1 | private function generate_license_box( $message, $class = '' ) { |
|
369 | |||
370 | /** |
||
371 | * Override the text used in the GravityView EDD license Javascript |
||
372 | * |
||
373 | * @param string $status Status to get. If empty, get all strings. |
||
374 | * @param object|array|null $license_data Object with license data, used to generate link to license renewal URL |
||
375 | * @return string Modified array of content |
||
376 | */ |
||
377 | 1 | public function strings( $status = NULL, $license_data = null ) { |
|
408 | |||
409 | /** |
||
410 | * URL to direct license renewal, or if license key is not set, then just the account page |
||
411 | * @since 1.13.1 |
||
412 | * @param object|null $license_data Object with license data |
||
413 | * @return string Renewal or account URL |
||
414 | */ |
||
415 | 1 | private function get_license_renewal_url( $license_data ) { |
|
430 | |||
431 | /** |
||
432 | * Perform the call |
||
433 | * |
||
434 | * @return array|\WP_Error |
||
435 | */ |
||
436 | 1 | private function _license_get_remote_response( $data, $license = '' ) { |
|
468 | |||
469 | /** |
||
470 | * Update the license after fetching it |
||
471 | * @param object $license_data |
||
472 | * @return void |
||
473 | */ |
||
474 | 1 | private function license_call_update_settings( $license_data, $data ) { |
|
483 | |||
484 | 2 | public function settings_edd_license_activation( $field, $echo ) { |
|
548 | |||
549 | /** |
||
550 | * When the status transient expires (or is deleted on activation), re-check the status |
||
551 | * |
||
552 | * @since 1.17 |
||
553 | * |
||
554 | * @return void |
||
555 | */ |
||
556 | 1 | public function refresh_license_status() { |
|
578 | |||
579 | /** |
||
580 | * Check the GravityView license information |
||
581 | * |
||
582 | * @since 1.19.3 |
||
583 | * @param bool $force Whether to force checking license, even if AJAX |
||
584 | * |
||
585 | * @return void |
||
586 | */ |
||
587 | 1 | public function check_license() { |
|
635 | |||
636 | /** |
||
637 | * Retrieves site data (plugin versions, integrations, etc) to be sent along with the license check. |
||
638 | * |
||
639 | * @since 1.9 |
||
640 | * @access public |
||
641 | * |
||
642 | * @return array |
||
643 | */ |
||
644 | 1 | public function get_site_data() { |
|
706 | |||
707 | /** |
||
708 | * Get active GravityView Extensions and Gravity Forms Add-ons to help debug issues. |
||
709 | * |
||
710 | * @since 1.15 |
||
711 | * @return string List of active extensions related to GravityView or Gravity Forms, separated by HTML line breaks |
||
712 | */ |
||
713 | 1 | static public function get_related_plugins_and_extensions( $implode = '<br />' ) { |
|
744 | |||
745 | /** |
||
746 | * When a plugin is activated or deactivated, delete the cached extensions/plugins used by get_related_plugins_and_extensions() |
||
747 | * |
||
748 | * @see get_related_plugins_and_extensions() |
||
749 | * @since 1.15 |
||
750 | */ |
||
751 | 1 | public function flush_related_plugins_transient() { |
|
756 | } |
||
757 |