PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
2.3.1 2.3.0 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 All 261 releases
← All changes | includes/class-ph-licenses.php +959 -48 1.4.552.3.0 View file →
@@ -19,8 +19,10 @@
19 19
20 20 /** @var PH_Licenses The single instance of the class */
21 21 protected static $_instance = null;
22 22
23 + private $pro_license_status = array();
24 +
23 25 /**
24 26 * Main PH_Licenses Instance.
25 27 *
26 28 * Ensures only one instance of PH_Licenses is loaded or can be loaded.
@@ -41,9 +43,9 @@
41 43 *
42 44 * @since 1.0.0
43 45 */
44 46 public function __clone() {
45 - _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
47 + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
46 48 }
47 49
48 50 /**
49 51 * Unserializing instances of this class is forbidden.
@@ -50,9 +52,9 @@
50 52 *
51 53 * @since 1.0.0
52 54 */
53 55 public function __wakeup() {
54 - _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
56 + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
55 57 }
56 58
57 59 /**
58 60 * Constructor for the licenses class
@@ -59,73 +61,413 @@
59 61 *
60 62 */
61 63 public function __construct() {
62 64 add_action( 'propertyhive_check_licenses', array( $this, 'ph_check_licenses' ) );
65 + add_filter( 'propertyhive_add_on_can_be_used', array( $this, 'ph_check_add_on_can_be_used' ), 10, 2 );
66 + add_filter( 'propertyhive_add_on_can_be_updated', array( $this, 'ph_check_add_on_can_be_updated' ), 10, 2 );
63 67 }
64 68
65 - /**
66 - * Automated check for licenses
67 - *
68 - */
69 - public function ph_check_licenses( $force_check = false )
69 + public function ph_check_add_on_can_be_used( $can, $slug )
70 70 {
71 - // Do a maximum of once per week
72 - $last_send = get_option( 'propertyhive_last_license_check', '' );
73 - if( !$force_check && is_numeric( $last_send ) && $last_send > strtotime( '-1 week' ) ) {
74 - return false;
71 + // Check add on wasn't active before
72 + $pre_pro_add_ons = get_option( 'propertyhive_pre_pro_add_ons', array() );
73 +
74 + if ( !empty($pre_pro_add_ons) )
75 + {
76 + foreach ( $pre_pro_add_ons as $pre_pro_add_on )
77 + {
78 + if ( isset($pre_pro_add_on['slug']) && $pre_pro_add_on['slug'] == $slug )
79 + {
80 + // Yes! This add on was being used pre pro so should still be able to be used without license checks
81 + return true;
82 + }
83 + }
75 84 }
85 +
86 + // Check we have the right kind of license key to operate this add on
76 87
77 - update_option( 'propertyhive_last_license_check', time() );
88 + $license_type = $this->get_license_type();
78 89
79 - // Start be removing what we already know about the license
80 - update_option( 'propertyhive_license_key_details', '', 'no' );
90 + if ( $license_type == 'pro' )
91 + {
92 + if ( get_option('propertyhive_pro_license_key', '') != '' )
93 + {
94 + if ( !$this->is_valid_pro_license_key() )
95 + {
96 + // show warning
97 + return false;
98 + }
81 99
82 - $data = array();
100 + // Valid license. Check this plugin is valid for the purchased type of plan (i.e. map search can't be used with an 'import only' plan)
101 + $feature = get_ph_pro_feature( $slug );
102 + $product_id_and_package = PH()->license->get_pro_license_product_id_and_package();
83 103
84 - // Retrieve current theme info
85 - $theme_data = wp_get_theme();
86 - $theme = $theme_data->Name . ' ' . $theme_data->Version;
104 + if ( isset($product_id_and_package['success']) && $product_id_and_package['success'] === true )
105 + {
106 + if (
107 + isset($feature['plans']) &&
108 + isset($product_id_and_package['package']) &&
109 + in_array($product_id_and_package['package'], $feature['plans'])
110 + )
111 + {
112 +
113 + }
114 + else
115 + {
116 + // show warning
117 + return false;
118 + }
119 + }
120 + }
121 + }
87 122
88 - $data['php_version'] = phpversion();
89 - $data['ph_version'] = PH_VERSION;
90 - $data['wp_version'] = get_bloginfo( 'version' );
91 - $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
123 + return $can;
124 + }
92 125
93 - $data['install_date'] = get_option('propertyhive_install_timestamp', '');
94 - if ( $data['install_date'] != '' && $data['install_date'] != 0 )
126 + public function ph_check_add_on_can_be_updated( $can, $slug )
127 + {
128 + $license_type = $this->get_license_type();
129 +
130 + if ( $license_type == 'old' )
95 131 {
96 - $data['install_date'] = date("jS F Y", $data['install_date']);
132 + $license = get_option( 'propertyhive_license_key_details', array() );
133 +
134 + if ( !is_array( $license ) ) { $license = array(); }
135 +
136 + if ( isset($license['active']) && $license['active'] == '1' && isset($license['expires_at']) && $license['expires_at'] != '' && strtotime($license['expires_at']) > time() )
137 + {
138 + return true;
139 + }
97 140 }
141 + elseif ( $license_type == 'pro' )
142 + {
143 + // get new license information
144 + if ( get_option('propertyhive_pro_license_key', '') != '' )
145 + {
146 + if ( $this->is_valid_pro_license_key() )
147 + {
148 + // Valid license. Check this plugin is valid for the purchased type of plan (i.e. map search can't be used with an 'import only' plan)
149 + $feature = get_ph_pro_feature( $slug );
150 + $product_id_and_package = PH()->license->get_pro_license_product_id_and_package();
98 151
99 - $data['multisite'] = is_multisite();
152 + if ( isset($product_id_and_package['success']) && $product_id_and_package['success'] === true )
153 + {
154 + if (
155 + isset($feature['plans']) &&
156 + isset($product_id_and_package['package']) &&
157 + in_array($product_id_and_package['package'], $feature['plans'])
158 + )
159 + {
160 + return true;
161 + }
162 + }
163 + }
164 + }
165 + }
166 +
167 + return $can;
168 + }
169 +
170 + public function get_license_type()
171 + {
172 + $license_type = get_option( 'propertyhive_license_type', '' );
173 +
174 + if ( $license_type == '' )
175 + {
176 + // We don't know. Let's work it out by seeing if they have a license key
177 + $existing_license_key = get_option( 'propertyhive_license_key', '' );
178 +
179 + if ( $existing_license_key != '' )
180 + {
181 + $license = PH()->license->get_current_license();
182 +
183 + if ( isset($license['active']) && $license['active'] == '1' )
184 + {
185 + return 'old';
186 + }
187 + }
188 + }
189 +
190 + return $license_type; // pro / old
191 + }
192 +
193 + private function get_data_for_license_check()
194 + {
195 + global $wpdb;
196 +
197 + $license_type = $this->get_license_type();
198 +
199 + $data = array();
200 + $data['license_key_type'] = $license_type;
201 + $data['license_key'] = ( $license_type == 'old' ? get_option( 'propertyhive_license_key', '' ) : get_option( 'propertyhive_pro_license_key', '' ) );
100 202 $data['url'] = home_url();
101 - $data['theme'] = $theme;
102 - $data['email'] = get_bloginfo( 'admin_email' );
103 - $data['license_key'] = get_option( 'propertyhive_license_key', '' );
104 203
105 - // Retrieve current plugin information
106 - if( ! function_exists( 'get_plugins' ) ) {
107 - include ABSPATH . '/wp-admin/includes/plugin.php';
204 + if ( get_option( 'propertyhive_data_sharing' ) != 'no' )
205 + {
206 + // Not opted-out
207 +
208 + // Retrieve current theme info
209 + $theme_data = wp_get_theme();
210 + $theme = $theme_data->Name . ' ' . $theme_data->Version;
211 +
212 + $data['php_version'] = phpversion();
213 + $data['ph_version'] = PH_VERSION;
214 + $data['wp_version'] = get_bloginfo( 'version' );
215 + $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) && is_string( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
216 +
217 + $data['install_date'] = get_option('propertyhive_install_timestamp', '');
218 + if ( $data['install_date'] != '' && $data['install_date'] != 0 )
219 + {
220 + $data['install_date'] = gmdate("jS F Y", $data['install_date']);
221 + }
222 +
223 + $data['multisite'] = is_multisite();
224 + $data['theme'] = $theme;
225 + $data['email'] = get_bloginfo( 'admin_email' );
226 +
227 + // Retrieve current plugin information
228 + if ( !function_exists( 'get_plugins' ) ) {
229 + include ABSPATH . '/wp-admin/includes/plugin.php';
230 + }
231 +
232 + $plugins = get_plugins(); // Fetch all plugins with details
233 + $active_plugins = get_option('active_plugins', array());
234 +
235 + $active_plugins_data = [];
236 + $inactive_plugins_data = [];
237 +
238 + // Loop through plugins to separate active and inactive along with version
239 + foreach ($plugins as $plugin_path => $plugin_data)
240 + {
241 + $plugin_info = [
242 + 'name' => isset($plugin_data['Name']) ? $plugin_data['Name'] : '',
243 + 'version' => isset($plugin_data['Version']) ? $plugin_data['Version'] : '',
244 + 'path' => $plugin_path,
245 + ];
246 +
247 + if (in_array($plugin_path, $active_plugins))
248 + {
249 + $active_plugins_data[] = $plugin_info;
250 + }
251 + else
252 + {
253 + $inactive_plugins_data[] = $plugin_info;
254 + }
255 + }
256 +
257 + $data['active_plugins'] = $active_plugins_data;
258 + $data['inactive_plugins'] = $inactive_plugins_data;
259 +
260 + $data['locale'] = get_locale();
261 +
262 + // Import info
263 + $property_import = get_option( 'propertyhive_property_import', array() );
264 + if ( !is_array($property_import) )
265 + {
266 + $property_import = array();
267 + }
268 + $formats = array();
269 + foreach ( $property_import as $import_id => $options )
270 + {
271 + if ( $options['running'] == '1' )
272 + {
273 + if ( $options['format'] == 'xml' )
274 + {
275 + $options['format'] .= ' (' . esc_url($options['xml_url']) . ')';
276 + }
277 + elseif ( $options['format'] == 'csv' )
278 + {
279 + $options['format'] .= ' (' . esc_url($options['csv_url']) . ')';
280 + }
281 + $formats[] = $options['format'];
282 + }
283 + }
284 + $data['property_import_formats'] = $formats;
285 +
286 + // Exports
287 + $formats = array();
288 +
289 + $exports = array(
290 + 'propertyhive_realtimefeed' => array(
291 + 'label' => 'RTDF',
292 + 'field' => 'send_property_api_url',
293 + ),
294 + 'propertyhive_zooplarealtimefeed' => array(
295 + 'label' => 'Zoopla',
296 + 'field' => 'send_property_api_url',
297 + ),
298 + 'propertyhive_blmexport' => array(
299 + 'label' => 'BLM',
300 + 'field' => 'ftp_host',
301 + ),
302 + );
303 +
304 + foreach ( $exports as $option_name => $config )
305 + {
306 + $property_export = get_option( $option_name, array() );
307 +
308 + if ( ! is_array( $property_export ) ) {
309 + continue;
310 + }
311 +
312 + if ( ! isset( $property_export['portals'] ) ) {
313 + continue;
314 + }
315 +
316 + if ( ! is_array( $property_export['portals'] ) ) {
317 + continue;
318 + }
319 +
320 + $portals = isset( $property_export['portals'] ) && is_array( $property_export['portals'] )
321 + ? $property_export['portals']
322 + : array();
323 +
324 + foreach ( $portals as $portal_id => $portal )
325 + {
326 + if ( ! is_array( $portal ) ) {
327 + continue;
328 + }
329 +
330 + if ( ! is_array( $portal ) || ( $portal['mode'] ?? '' ) !== 'live' ) {
331 + continue;
332 + }
333 +
334 + $destination = $portal[ $config['field'] ] ?? '';
335 +
336 + $formats[] = sprintf(
337 + '%s (%s)',
338 + $config['label'],
339 + $destination
340 + );
341 + }
342 + }
343 +
344 + $data['property_export_formats'] = $formats;
345 +
346 + // Locrating
347 + $locrating_settings = get_option( 'propertyhive_locrating', array() );
348 + if ( !empty($locrating_settings) && isset($locrating_settings['enabled']) )
349 + {
350 + $data['locrating_enabled'] = ( $locrating_settings['enabled'] == 1 ? $locrating_settings['enabled'] : 0 );
351 + }
352 +
353 + // Search analytics
354 +
355 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregate current custom-table analytics for the license report; new search events and retention change these counts independently.
356 + $counts = $wpdb->get_row(
357 + "SELECT
358 + COALESCE(
359 + SUM(searched_at >= UTC_TIMESTAMP() - INTERVAL 7 DAY),
360 + 0
361 + ) AS last_7_days,
362 + COALESCE(
363 + SUM(searched_at >= UTC_TIMESTAMP() - INTERVAL 30 DAY),
364 + 0
365 + ) AS last_30_days,
366 + COUNT(*) AS last_90_days
367 + FROM {$wpdb->prefix}ph_search_log
368 + WHERE searched_at >= UTC_TIMESTAMP() - INTERVAL 90 DAY",
369 + ARRAY_A
370 + );
371 +
372 + if ( is_array($counts) )
373 + {
374 + $data['searches_last_7_days'] = (int) ( $counts['last_7_days'] ?? 0 );
375 + $data['searches_last_30_days'] = (int) ( $counts['last_30_days'] ?? 0 );
376 + $data['searches_last_90_days'] = (int) ( $counts['last_90_days'] ?? 0 );
377 + }
378 +
379 + // get counts
380 + $post_types = array('office', 'property', 'contact', 'appraisal', 'viewing', 'offer', 'sale', 'tenancy', 'key_date');
381 + foreach ( $post_types as $post_type )
382 + {
383 + $args = array(
384 + 'post_type' => $post_type,
385 + 'fields' => 'ids',
386 + 'posts_per_page' => 1,
387 + 'post_status' => 'publish'
388 + );
389 + if ( $post_type == 'property' )
390 + {
391 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- On-market state is stored in property metadata; retrieve one ID and use found_posts for the aggregate count.
392 + $args['meta_query'] = array(
393 + array(
394 + 'key' => '_on_market',
395 + 'value' => 'yes'
396 + )
397 + );
398 + }
399 +
400 + $post_query = new WP_Query( $args );
401 +
402 + $data['post_type_count_' . $post_type] = $post_query->found_posts;
403 +
404 + wp_reset_postdata();
405 + }
406 +
407 + $departments = array_keys( ph_get_departments() );
408 + foreach ( $departments as $department )
409 + {
410 + $department_option = 'propertyhive_active_departments_' . str_replace( 'residential-', '', $department );
411 + if ( get_option( $department_option ) != 'yes' )
412 + {
413 + continue;
414 + }
415 +
416 + $args = array(
417 + 'post_type' => 'property',
418 + 'fields' => 'ids',
419 + 'posts_per_page' => 1,
420 + 'post_status' => 'publish',
421 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Department and on-market state use property metadata; retrieve one ID and use found_posts for the opted-in aggregate count.
422 + 'meta_query' => array(
423 + array(
424 + 'key' => '_on_market',
425 + 'value' => 'yes'
426 + ),
427 + array(
428 + 'key' => '_department',
429 + 'value' => $department
430 + )
431 + )
432 + );
433 +
434 + $post_query = new WP_Query( $args );
435 +
436 + $data['property_count_by_department_' . $department] = $post_query->found_posts;
437 +
438 + wp_reset_postdata();
439 + }
440 +
441 + $data = apply_filters( 'propertyhive_license_check_data', $data );
108 442 }
109 443
110 - $plugins = array_keys( get_plugins() );
111 - $active_plugins = get_option( 'active_plugins', array() );
444 + return $data;
445 + }
112 446
113 - foreach ( $plugins as $key => $plugin ) {
114 - if ( in_array( $plugin, $active_plugins ) ) {
115 - // Remove active plugins from list so we can show active and inactive separately
116 - unset( $plugins[ $key ] );
117 - }
447 + /**
448 + * Automated check for licenses
449 + *
450 + */
451 + public function ph_check_licenses( $force_check = false )
452 + {
453 + // Do a maximum of once per week
454 + $last_send = get_option( 'propertyhive_last_license_check', '' );
455 + if( !$force_check && is_numeric( $last_send ) && $last_send > strtotime( '-1 week' ) ) {
456 + return false;
118 457 }
119 458
120 - $data['active_plugins'] = $active_plugins;
121 - $data['inactive_plugins'] = $plugins;
122 - $data['locale'] = get_locale();
459 + update_option( 'propertyhive_last_license_check', time() );
123 460
461 + // Retain last-known license details during outages; replace them only with a valid HTTPS response.
462 + update_option( 'propertyhive_license_key_error', '', 'no' );
463 +
464 + $data = $this->get_data_for_license_check();
465 +
124 466 $request = wp_remote_post( 'http://license.wp-property-hive.com/check-license.php', array(
125 467 'method' => 'POST',
126 468 'timeout' => 20,
127 - 'redirection' => 5,
469 + 'redirection' => 1,
128 470 'httpversion' => '1.1',
129 471 'blocking' => true,
130 472 'body' => $data,
131 473 'user-agent' => 'PH/' . PH_VERSION . '; ' . get_bloginfo( 'url' )
@@ -130,19 +472,29 @@
130 472 'body' => $data,
131 473 'user-agent' => 'PH/' . PH_VERSION . '; ' . get_bloginfo( 'url' )
132 474 ) );
133 475
134 - if ( is_wp_error( $request ) || ( !is_wp_error( $request ) && isset($request['body']) && $request['body'] == '' ) )
476 + if ( is_wp_error( $request ) )
135 477 {
136 - update_option( 'propertyhive_license_key_details', array(), 'no' );
478 + update_option( 'propertyhive_license_key_error', __( 'The license service could not be reached securely. Your saved license details have been retained.', 'propertyhive' ) . ' ' . $request->get_error_message(), 'no' );
137 479 return false;
138 480 }
139 481
140 - $body = unserialize($request['body']);
141 - if ( $body !== FALSE && is_array($body) && !empty($body) )
482 + if ( 200 !== wp_remote_retrieve_response_code( $request ) || '' === wp_remote_retrieve_body( $request ) )
142 483 {
484 + update_option( 'propertyhive_license_key_error', __( 'The license service returned an invalid response.', 'propertyhive' ) . ' ' . wp_remote_retrieve_response_code( $request ), 'no' );
485 + return false;
486 + }
487 +
488 + $body = @unserialize($request['body'], ['allowed_classes' => false]);
489 + if ( $body !== FALSE && is_array($body) )
490 + {
143 491 update_option( 'propertyhive_license_key_details', $body, 'no' );
144 492 }
493 + else
494 + {
495 + update_option( 'propertyhive_license_key_error', __( 'The license service returned invalid license data.', 'propertyhive' ) . ' ' . print_r($body, true), 'no' );
496 + }
145 497 }
146 498
147 499 public function get_current_license()
148 500 {
@@ -151,5 +503,564 @@
151 503 if ( !is_array( $license ) ) { $license = array(); }
152 504
153 505 return $license;
154 506 }
155 -}
507 +
508 + public function is_valid_pro_license_key($force = false)
509 + {
510 + $license = $this->get_current_pro_license($force);
511 + if ( isset($license['success']) && $license['success'] === true )
512 + {
513 + return true;
514 + }
515 +
516 + return false;
517 + }
518 +
519 + public function activate_pro_license_key()
520 + {
521 + $license = $this->get_pro_license_product_id_and_package(true);
522 +
523 + if ( isset($license['success']) && $license['success'] === true )
524 + {
525 + $license_key = get_option( 'propertyhive_pro_license_key', '' );
526 +
527 + $instance_id = get_option( 'propertyhive_pro_instance_id', '' );
528 +
529 + if ( empty($instance_id) )
530 + {
531 + $instance_id = wp_generate_password( 12, false ); // disable specialchars
532 + update_option('propertyhive_pro_instance_id', $instance_id );
533 + }
534 +
535 + $data = array();
536 +
537 + // found API key. It's product ID will be stored in product_id
538 + $url = 'https://wp-property-hive.com/?';
539 + $url .= 'wc-api=wc-am-api&';
540 + $url .= 'wc_am_action=activate&';
541 + $url .= 'instance=' . $instance_id . '&';
542 + $url .= 'object=' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '&';
543 + $url .= 'product_id=' . $license['product_id'] . '&';
544 + $url .= 'api_key=' . $license_key;
545 +
546 + $response = wp_remote_post( $url, array(
547 + 'body' => $data,
548 + ) );
549 +
550 + if ( is_wp_error($response) )
551 + {
552 + $return = array(
553 + 'success' => false,
554 + 'error' => __( 'Failed to activate license status', 'propertyhive' ) . ': ' . $response->get_error_message()
555 + );
556 + return $return;
557 + }
558 +
559 + if ( 200 !== wp_remote_retrieve_response_code( $response ) )
560 + {
561 + $return = array(
562 + 'success' => false,
563 + 'error' => sprintf(
564 + /* translators: %s: HTTP header response code */
565 + __( 'Received response code %s when activating license key status', 'propertyhive' ),
566 + wp_remote_retrieve_response_code( $response )
567 + )
568 + );
569 + return $return;
570 + }
571 +
572 + $result = $response['body'];
573 +
574 + $body = json_decode($result, true);
575 +
576 + if ( json_last_error() !== JSON_ERROR_NONE )
577 + {
578 + $return = array(
579 + 'success' => false,
580 + 'error' => __( 'Failed to decode response when activating license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
581 + );
582 + return $return;
583 + }
584 +
585 + if ( isset($body['success']) )
586 + {
587 + if ( $body['success'] === true )
588 + {
589 + $return = array(
590 + 'success' => true,
591 + );
592 + return $return;
593 + }
594 + else
595 + {
596 + $return = array(
597 + 'success' => false,
598 + 'error' => __( 'Error when activating license key', 'propertyhive' ) . ': ' . $body['error']
599 + );
600 + return $return;
601 + }
602 + }
603 + else
604 + {
605 + $return = array(
606 + 'success' => false,
607 + 'error' => __( 'Something went wrong when trying to activate license key', 'propertyhive' ) . ': ' . wp_json_encode( $body )
608 + );
609 + return $return;
610 + }
611 + }
612 + else
613 + {
614 + return $license;
615 + }
616 + }
617 +
618 + public function deactivate_pro_license_key()
619 + {
620 + $license = $this->get_pro_license_product_id_and_package(true);
621 +
622 + if ( isset($license['success']) && $license['success'] === true )
623 + {
624 + $license_key = get_option( 'propertyhive_pro_license_key', '' );
625 +
626 + $instance_id = get_option( 'propertyhive_pro_instance_id', '' );
627 +
628 + if ( empty($instance_id) )
629 + {
630 + $instance_id = wp_generate_password( 12, false ); // disable specialchars
631 + update_option('propertyhive_pro_instance_id', $instance_id );
632 + }
633 +
634 + $data = array();
635 +
636 + // found API key. It's product ID will be stored in product_id
637 + $url = 'https://wp-property-hive.com/?';
638 + $url .= 'wc-api=wc-am-api&';
639 + $url .= 'wc_am_action=deactivate&';
640 + $url .= 'instance=' . $instance_id . '&';
641 + $url .= 'object=' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '&';
642 + $url .= 'product_id=' . $license['product_id'] . '&';
643 + $url .= 'api_key=' . $license_key;
644 +
645 + $response = wp_remote_post( $url, array(
646 + 'body' => $data,
647 + ) );
648 +
649 + if ( is_wp_error($response) )
650 + {
651 + $return = array(
652 + 'success' => false,
653 + 'error' => __( 'Failed to deactivate license status', 'propertyhive' ) . ': ' . $response->get_error_message()
654 + );
655 + return $return;
656 + }
657 +
658 + if ( 200 !== wp_remote_retrieve_response_code( $response ) )
659 + {
660 + $return = array(
661 + 'success' => false,
662 + 'error' => sprintf(
663 + /* translators: %s: HTTP header response code */
664 + __( 'Received response code %s when deactivating license key status', 'propertyhive' ),
665 + wp_remote_retrieve_response_code( $response )
666 + )
667 + );
668 + return $return;
669 + }
670 +
671 + $result = $response['body'];
672 +
673 + $body = json_decode($result, true);
674 +
675 + if ( json_last_error() !== JSON_ERROR_NONE )
676 + {
677 + $return = array(
678 + 'success' => false,
679 + 'error' => __( 'Failed to decode response when deactivating license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
680 + );
681 + return $return;
682 + }
683 +
684 + if ( isset($body['success']) )
685 + {
686 + if ( $body['success'] === true )
687 + {
688 + $return = array(
689 + 'success' => true,
690 + );
691 + return $return;
692 + }
693 + else
694 + {
695 + $return = array(
696 + 'success' => false,
697 + 'error' => __( 'Error when deactivating license key', 'propertyhive' ) . ': ' . $body['error']
698 + );
699 + return $return;
700 + }
701 + }
702 + else
703 + {
704 + $return = array(
705 + 'success' => false,
706 + 'error' => __( 'Something went wrong when trying to deactivate license key', 'propertyhive' ) . ': ' . wp_json_encode( $body )
707 + );
708 + return $return;
709 + }
710 + }
711 + else
712 + {
713 + return $license;
714 + }
715 + }
716 +
717 + public function get_pro_license_product_id_and_package($force = false)
718 + {
719 + if ( $force !== true )
720 + {
721 + // Not forcing. Get from transient if possible
722 + $pro_license_product_id_and_package = get_transient( 'ph_pro_license_product_id_and_package' );
723 +
724 + if ( $pro_license_product_id_and_package !== false )
725 + {
726 + // return transient value
727 + return $pro_license_product_id_and_package;
728 + }
729 + }
730 +
731 + $license_key = get_option( 'propertyhive_pro_license_key', '' );
732 +
733 + if ( empty($license_key) )
734 + {
735 + $return = array(
736 + 'success' => false,
737 + 'error' => __( 'No license key entered', 'propertyhive' )
738 + );
739 + set_transient( 'ph_pro_license_product_id_and_package', $return, HOUR_IN_SECONDS );
740 + return $return;
741 + }
742 +
743 + $instance_id = get_option( 'propertyhive_pro_instance_id', '' );
744 +
745 + if ( empty($instance_id) )
746 + {
747 + $instance_id = wp_generate_password( 12, false ); // disable specialchars
748 + update_option('propertyhive_pro_instance_id', $instance_id );
749 + }
750 +
751 + $data = $this->get_data_for_license_check();
752 +
753 + $url = 'https://wp-property-hive.com/?';
754 + $url .= 'wc-api=wc-am-api&';
755 + $url .= 'wc_am_action=product_list&';
756 + $url .= 'instance=' . $instance_id . '&';
757 + $url .= 'api_key=' . $license_key;
758 +
759 + $response = wp_remote_post( $url, array(
760 + 'body' => $data,
761 + ) );
762 +
763 + if ( is_wp_error($response) )
764 + {
765 + $return = array(
766 + 'success' => false,
767 + 'error' => __( 'Failed to request license product list', 'propertyhive' ) . ': ' . $response->get_error_message()
768 + );
769 +
770 + $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
771 + if ( !empty($last_known) )
772 + {
773 + set_transient( 'ph_pro_license_product_id_and_package', $last_known, HOUR_IN_SECONDS );
774 + return $last_known;
775 + }
776 +
777 + return $return;
778 + }
779 +
780 + if ( 200 !== wp_remote_retrieve_response_code( $response ) )
781 + {
782 + $return = array(
783 + 'success' => false,
784 + 'error' => sprintf(
785 + /* translators: %s: HTTP header response code */
786 + __( 'Received response code %s when requesting license key product list', 'propertyhive' ),
787 + wp_remote_retrieve_response_code( $response )
788 + )
789 + );
790 +
791 + $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
792 + if ( !empty($last_known) )
793 + {
794 + set_transient( 'ph_pro_license_product_id_and_package', $last_known, HOUR_IN_SECONDS );
795 + return $last_known;
796 + }
797 +
798 + return $return;
799 + }
800 +
801 + $result = $response['body'];
802 +
803 + $body = json_decode($result, true);
804 +
805 + if ( json_last_error() !== JSON_ERROR_NONE )
806 + {
807 + $return = array(
808 + 'success' => false,
809 + 'error' => __( 'Failed to decode response when requesting license key product list. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
810 + );
811 +
812 + $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
813 + if ( !empty($last_known) )
814 + {
815 + set_transient( 'ph_pro_license_product_id_and_package', $last_known, HOUR_IN_SECONDS );
816 + return $last_known;
817 + }
818 +
819 + return $return;
820 + }
821 +
822 + if ( isset($body['success']) )
823 + {
824 + if ( $body['success'] === true )
825 + {
826 + if ( isset($body['data']['product_list']['wc_subs_resources']) && !empty($body['data']['product_list']['wc_subs_resources']) )
827 + {
828 + $package = false;
829 + $product_id = '';
830 +
831 + foreach ( $body['data']['product_list']['wc_subs_resources'] as $resource )
832 + {
833 + if ( isset($resource['product_id']) )
834 + {
835 + if ( in_array($resource['product_id'], array(14492, 14493, 14494)) )
836 + {
837 + $package = 'import';
838 + }
839 + elseif ( in_array($resource['product_id'], array(14495, 14496, 14497)) )
840 + {
841 + $package = 'complete';
842 + }
843 + $product_id = $resource['product_id'];
844 + }
845 + }
846 +
847 + if ( $package !== FALSE )
848 + {
849 + $return = array(
850 + 'success' => true,
851 + 'package' => $package,
852 + 'product_id' => $product_id
853 + );
854 + }
855 + else
856 + {
857 + $return = array(
858 + 'success' => false,
859 + 'error' => __( 'API key exists but unable to establish the plan', 'propertyhive' )
860 + );
861 + }
862 + }
863 + else
864 + {
865 + $return = array(
866 + 'success' => false,
867 + 'error' => __( 'API key doesn\'t appear to belong to any orders', 'propertyhive' ) . ': ' . wp_json_encode( $body )
868 + );
869 + }
870 + }
871 + else
872 + {
873 + $return = array(
874 + 'success' => false,
875 + 'error' => __( 'Error when requesting license key product list', 'propertyhive' ) . ': ' . $body['error']
876 + );
877 + }
878 +
879 + set_transient( 'ph_pro_license_product_id_and_package', $return, HOUR_IN_SECONDS * 3 );
880 + update_option( 'ph_pro_last_known_license_product_id_and_package', $return );
881 + return $return;
882 + }
883 + else
884 + {
885 + $return = array(
886 + 'success' => false,
887 + 'error' => __( 'Something went wrong when requesting license key product list', 'propertyhive' ) . ': ' . wp_json_encode( $body )
888 + );
889 +
890 + $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
891 + if ( !empty($last_known) )
892 + {
893 + set_transient( 'ph_pro_license_product_id_and_package', $last_known, HOUR_IN_SECONDS );
894 + return $last_known;
895 + }
896 +
897 + return $return;
898 + }
899 + }
900 +
901 + public function get_current_pro_license($force = false)
902 + {
903 + if ( $force !== true )
904 + {
905 + // Not forcing. Get from transient if possible
906 + $pro_license_status = get_transient( 'ph_pro_license_status' );
907 +
908 + if ( $pro_license_status !== false )
909 + {
910 + // return transient value
911 + return $pro_license_status;
912 + }
913 + }
914 +
915 + $product_id_and_package = $this->get_pro_license_product_id_and_package($force);
916 +
917 + if ( !isset($product_id_and_package['success']) || ( isset($product_id_and_package['success']) && $product_id_and_package['success'] === false ) )
918 + {
919 + return $product_id_and_package;
920 + }
921 +
922 + $license_key = get_option( 'propertyhive_pro_license_key', '' );
923 +
924 + if ( empty($license_key) )
925 + {
926 + $return = array(
927 + 'success' => false,
928 + 'error' => __( 'No license key entered', 'propertyhive' )
929 + );
930 + set_transient( 'ph_pro_license_status', $return, HOUR_IN_SECONDS );
931 + return $return;
932 + }
933 +
934 + $instance_id = get_option( 'propertyhive_pro_instance_id', '' );
935 +
936 + if ( empty($instance_id) )
937 + {
938 + $instance_id = wp_generate_password( 12, false ); // disable specialchars
939 + update_option('propertyhive_pro_instance_id', $instance_id );
940 + }
941 +
942 + $data = $this->get_data_for_license_check();
943 +
944 + $url = 'https://wp-property-hive.com/?';
945 + $url .= 'wc-api=wc-am-api&';
946 + $url .= 'wc_am_action=status&';
947 + $url .= 'product_id=' . $product_id_and_package['product_id'] . '&';
948 + $url .= 'instance=' . $instance_id . '&';
949 + $url .= 'api_key=' . $license_key;
950 +
951 + $response = wp_remote_post( $url, array(
952 + 'body' => $data,
953 + ) );
954 +
955 + if ( is_wp_error($response) )
956 + {
957 + // error for some reason. Return last known status
958 + $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );
959 + if ( !empty($previous_license_key_status) )
960 + {
961 + set_transient( 'ph_pro_license_status', $previous_license_key_status, HOUR_IN_SECONDS );
962 + return $previous_license_key_status;
963 + }
964 +
965 + $return = array(
966 + 'success' => false,
967 + 'error' => __( 'Failed to request license status', 'propertyhive' ) . ': ' . $response->get_error_message()
968 + );
969 + return $return;
970 + }
971 +
972 + if ( 200 !== wp_remote_retrieve_response_code( $response ) )
973 + {
974 + // error for some reason. Return last known status
975 + $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );
976 + if ( !empty($previous_license_key_status) )
977 + {
978 + set_transient( 'ph_pro_license_status', $previous_license_key_status, HOUR_IN_SECONDS );
979 + return $previous_license_key_status;
980 + }
981 +
982 + $return = array(
983 + 'success' => false,
984 + 'error' => sprintf(
985 + /* translators: %s: HTTP header response code */
986 + __( 'Received response code %s when requesting license key status', 'propertyhive' ),
987 + wp_remote_retrieve_response_code( $response )
988 + )
989 + );
990 +
991 + return $return;
992 + }
993 +
994 + $result = $response['body'];
995 +
996 + $body = json_decode($result, true);
997 +
998 + if ( json_last_error() !== JSON_ERROR_NONE )
999 + {
1000 + $return = array(
1001 + 'success' => false,
1002 + 'error' => __( 'Failed to decode response when requesting license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
1003 + );
1004 +
1005 + // error for some reason. Return last known status
1006 + $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );
1007 + if ( !empty($previous_license_key_status) )
1008 + {
1009 + set_transient( 'ph_pro_license_status', $previous_license_key_status, HOUR_IN_SECONDS );
1010 + return $previous_license_key_status;
1011 + }
1012 +
1013 + return $return;
1014 + }
1015 +
1016 + if ( isset($body['success']) )
1017 + {
1018 + if ( $body['success'] === true )
1019 + {
1020 + if ( isset($body['status_check']) && $body['status_check'] === 'active' )
1021 + {
1022 + $return = array(
1023 + 'success' => true
1024 + );
1025 + }
1026 + else
1027 + {
1028 + $return = array(
1029 + 'success' => false,
1030 + 'error' => __( 'License key inactive', 'propertyhive' )
1031 + );
1032 + }
1033 + }
1034 + else
1035 + {
1036 + $return = array(
1037 + 'success' => false,
1038 + 'error' => __( 'Error when requesting license key status', 'propertyhive' ) . ': ' . $body['error']
1039 + );
1040 + }
1041 +
1042 + update_option( 'propertyhive_pro_license_key_last_checked', time() );
1043 + update_option( 'propertyhive_pro_license_key_status', $return );
1044 +
1045 + set_transient( 'ph_pro_license_status', $return, HOUR_IN_SECONDS * 3 );
1046 + return $return;
1047 + }
1048 + else
1049 + {
1050 + $return = array(
1051 + 'success' => false,
1052 + 'error' => __( 'Something went wrong when requesting license key status', 'propertyhive' ) . ': ' . wp_json_encode( $body )
1053 + );
1054 +
1055 + // error for some reason. Return last known status
1056 + $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );
1057 + if ( !empty($previous_license_key_status) )
1058 + {
1059 + set_transient( 'ph_pro_license_status', $previous_license_key_status, HOUR_IN_SECONDS );
1060 + return $previous_license_key_status;
1061 + }
1062 +
1063 + return $return;
1064 + }
1065 + }
1066 +}