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