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
propertyhive / includes / class-ph-licenses.php

class-ph-licenses.php in Property Hive 2.3.1, at includes/class-ph-licenses.php

1,078 lines 32.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 /**
8 * Licenses Controller
9 *
10 * Property Hive Licenses Class which handles the storing and checking of licenses
11 *
12 * @class PH_Licenses
13 * @version 1.0.0
14 * @package PropertyHive/Classes/Licenses
15 * @category Class
16 * @author PropertyHive
17 */
18 class PH_Licenses {
19
20 /** @var PH_Licenses The single instance of the class */
21 protected static $_instance = null;
22
23 private $pro_license_status = array();
24
25 /**
26 * Main PH_Licenses Instance.
27 *
28 * Ensures only one instance of PH_Licenses is loaded or can be loaded.
29 *
30 * @since 1.0.0
31 * @static
32 * @return PH_Licenses Main instance
33 */
34 public static function instance() {
35 if ( is_null( self::$_instance ) ) {
36 self::$_instance = new self();
37 }
38 return self::$_instance;
39 }
40
41 /**
42 * Cloning is forbidden.
43 *
44 * @since 1.0.0
45 */
46 public function __clone() {
47 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
48 }
49
50 /**
51 * Unserializing instances of this class is forbidden.
52 *
53 * @since 1.0.0
54 */
55 public function __wakeup() {
56 _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'propertyhive' ), '1.0.0' );
57 }
58
59 /**
60 * Constructor for the licenses class
61 *
62 */
63 public function __construct() {
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 );
67 }
68
69 public function ph_check_add_on_can_be_used( $can, $slug )
70 {
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 }
84 }
85
86 // Check we have the right kind of license key to operate this add on
87
88 $license_type = $this->get_license_type();
89
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 }
99
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();
103
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 }
122
123 return $can;
124 }
125
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' )
131 {
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 }
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();
151
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', '' ) );
207 $data['url'] = home_url();
208
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 );
447 }
448
449 return $data;
450 }
451
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;
462 }
463
464 update_option( 'propertyhive_last_license_check', time() );
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
471 $request = wp_remote_post( 'http://license.wp-property-hive.com/check-license.php', array(
472 'method' => 'POST',
473 'timeout' => 20,
474 'redirection' => 1,
475 'httpversion' => '1.1',
476 'blocking' => true,
477 'body' => $data,
478 'user-agent' => 'PH/' . PH_VERSION . '; ' . get_bloginfo( 'url' )
479 ) );
480
481 if ( is_wp_error( $request ) )
482 {
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' );
484 return false;
485 }
486
487 if ( 200 !== wp_remote_retrieve_response_code( $request ) || '' === wp_remote_retrieve_body( $request ) )
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 {
496 update_option( 'propertyhive_license_key_details', $body, 'no' );
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 }
502 }
503
504 public function get_current_license()
505 {
506 $license = get_option( 'propertyhive_license_key_details', array() );
507
508 if ( !is_array( $license ) ) { $license = array(); }
509
510 return $license;
511 }
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 }
1078