PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
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 1.4.62 All 260 releases
propertyhive / includes / class-ph-licenses.php

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

1,067 lines 31.6 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 (
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', '' ) );
202 $data['url'] = home_url();
203
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 );
442 }
443
444 return $data;
445 }
446
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;
457 }
458
459 update_option( 'propertyhive_last_license_check', time() );
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
466 $request = wp_remote_post( 'http://license.wp-property-hive.com/check-license.php', array(
467 'method' => 'POST',
468 'timeout' => 20,
469 'redirection' => 1,
470 'httpversion' => '1.1',
471 'blocking' => true,
472 'body' => $data,
473 'user-agent' => 'PH/' . PH_VERSION . '; ' . get_bloginfo( 'url' )
474 ) );
475
476 if ( is_wp_error( $request ) )
477 {
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' );
479 return false;
480 }
481
482 if ( 200 !== wp_remote_retrieve_response_code( $request ) || '' === wp_remote_retrieve_body( $request ) )
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 {
491 update_option( 'propertyhive_license_key_details', $body, 'no' );
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 }
497 }
498
499 public function get_current_license()
500 {
501 $license = get_option( 'propertyhive_license_key_details', array() );
502
503 if ( !is_array( $license ) ) { $license = array(); }
504
505 return $license;
506 }
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 }
1067