PluginProbe
Property Hive / 2.4.0
Property Hive v2.4.0
2.4.0 2.3.1 2.3.0 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 All 262 releases
← All changes | includes/class-ph-licenses.php +110 -30 2.2.6 → 2.4.0 View file →
@@ -43,9 +43,9 @@
43 43 *
44 44 * @since 1.0.0
45 45 */
46 46 public function __clone() {
47 - _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
47 + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
48 48 }
49 49
50 50 /**
51 51 * Unserializing instances of this class is forbidden.
@@ -52,9 +52,9 @@
52 52 *
53 53 * @since 1.0.0
54 54 */
55 55 public function __wakeup() {
56 - _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
56 + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'propertyhive' ), '1.0.0' );
57 57 }
58 58
59 59 /**
60 60 * Constructor for the licenses class
@@ -150,8 +150,13 @@
150 150 $product_id_and_package = PH()->license->get_pro_license_product_id_and_package();
151 151
152 152 if ( isset($product_id_and_package['success']) && $product_id_and_package['success'] === true )
153 153 {
154 + if ( ( $product_id_and_package['is_trial'] ?? null ) !== false )
155 + {
156 + return false;
157 + }
158 +
154 159 if (
155 160 isset($feature['plans']) &&
156 161 isset($product_id_and_package['package']) &&
157 162 in_array($product_id_and_package['package'], $feature['plans'])
@@ -211,14 +216,14 @@
211 216
212 217 $data['php_version'] = phpversion();
213 218 $data['ph_version'] = PH_VERSION;
214 219 $data['wp_version'] = get_bloginfo( 'version' );
215 - $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
220 + $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) && is_string( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
216 221
217 222 $data['install_date'] = get_option('propertyhive_install_timestamp', '');
218 223 if ( $data['install_date'] != '' && $data['install_date'] != 0 )
219 224 {
220 - $data['install_date'] = date("jS F Y", $data['install_date']);
225 + $data['install_date'] = gmdate("jS F Y", $data['install_date']);
221 226 }
222 227
223 228 $data['multisite'] = is_multisite();
224 229 $data['theme'] = $theme;
@@ -350,10 +355,10 @@
350 355 $data['locrating_enabled'] = ( $locrating_settings['enabled'] == 1 ? $locrating_settings['enabled'] : 0 );
351 356 }
352 357
353 358 // Search analytics
354 - $table_name = $wpdb->prefix . 'ph_search_log';
355 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.
356 361 $counts = $wpdb->get_row(
357 362 "SELECT
358 363 COALESCE(
359 364 SUM(searched_at >= UTC_TIMESTAMP() - INTERVAL 7 DAY),
@@ -363,9 +368,9 @@
363 368 SUM(searched_at >= UTC_TIMESTAMP() - INTERVAL 30 DAY),
364 369 0
365 370 ) AS last_30_days,
366 371 COUNT(*) AS last_90_days
367 - FROM {$table_name}
372 + FROM {$wpdb->prefix}ph_search_log
368 373 WHERE searched_at >= UTC_TIMESTAMP() - INTERVAL 90 DAY",
369 374 ARRAY_A
370 375 );
371 376
@@ -382,13 +387,14 @@
382 387 {
383 388 $args = array(
384 389 'post_type' => $post_type,
385 390 'fields' => 'ids',
386 - 'nopaging' => TRUE,
391 + 'posts_per_page' => 1,
387 392 'post_status' => 'publish'
388 393 );
389 394 if ( $post_type == 'property' )
390 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.
391 397 $args['meta_query'] = array(
392 398 array(
393 399 'key' => '_on_market',
394 400 'value' => 'yes'
@@ -402,8 +408,80 @@
402 408
403 409 wp_reset_postdata();
404 410 }
405 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 + // Onboarding wizard step
447 + $onboarding_state = get_option( 'propertyhive_onboarding', false );
448 +
449 + if ( is_array( $onboarding_state ) && ! empty( $onboarding_state ) )
450 + {
451 + $onboarding_status = isset( $onboarding_state['status'] )
452 + ? sanitize_key( $onboarding_state['status'] )
453 + : 'not_started';
454 +
455 + $onboarding_step = isset( $onboarding_state['last_step'] )
456 + ? sanitize_key( $onboarding_state['last_step'] )
457 + : '';
458 +
459 + // When skipped, last_step is the exact step on which Skip was clicked.
460 + // Otherwise, use the most recently viewed step so abandonment is captured.
461 + if (
462 + $onboarding_status !== 'skipped' &&
463 + ! empty( $onboarding_state['events'] ) &&
464 + is_array( $onboarding_state['events'] )
465 + )
466 + {
467 + foreach ( array_reverse( $onboarding_state['events'] ) as $event )
468 + {
469 + if (
470 + isset( $event['event'], $event['data']['step'] ) &&
471 + $event['event'] === 'step_viewed'
472 + )
473 + {
474 + $onboarding_step = sanitize_key( $event['data']['step'] );
475 + break;
476 + }
477 + }
478 + }
479 +
480 + $data['onboarding_status'] = $onboarding_status;
481 + $data['onboarding_step'] = $onboarding_step;
482 + }
483 +
406 484 $data = apply_filters( 'propertyhive_license_check_data', $data );
407 485 }
408 486
409 487 return $data;
@@ -422,10 +500,9 @@
422 500 }
423 501
424 502 update_option( 'propertyhive_last_license_check', time() );
425 503
426 - // Start by removing what we already know about the license
427 - update_option( 'propertyhive_license_key_details', '', 'no' );
504 + // Retain last-known license details during outages; replace them only with a valid HTTPS response.
428 505 update_option( 'propertyhive_license_key_error', '', 'no' );
429 506
430 507 $data = $this->get_data_for_license_check();
431 508
@@ -431,9 +508,9 @@
431 508
432 509 $request = wp_remote_post( 'http://license.wp-property-hive.com/check-license.php', array(
433 510 'method' => 'POST',
434 511 'timeout' => 20,
435 - 'redirection' => 5,
512 + 'redirection' => 1,
436 513 'httpversion' => '1.1',
437 514 'blocking' => true,
438 515 'body' => $data,
439 516 'user-agent' => 'PH/' . PH_VERSION . '; ' . get_bloginfo( 'url' )
@@ -440,29 +517,26 @@
440 517 ) );
441 518
442 519 if ( is_wp_error( $request ) )
443 520 {
444 - update_option( 'propertyhive_license_key_details', array(), 'no' );
445 - update_option( 'propertyhive_license_key_error', $request->get_error_message(), 'no' );
521 + 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' );
446 522 return false;
447 523 }
448 524
449 - if ( isset($request['body']) && $request['body'] == '' )
525 + if ( 200 !== wp_remote_retrieve_response_code( $request ) || '' === wp_remote_retrieve_body( $request ) )
450 526 {
451 - update_option( 'propertyhive_license_key_details', array(), 'no' );
452 - update_option( 'propertyhive_license_key_error', 'No response received when checking license', 'no' );
527 + update_option( 'propertyhive_license_key_error', __( 'The license service returned an invalid response.', 'propertyhive' ) . ' ' . wp_remote_retrieve_response_code( $request ), 'no' );
453 528 return false;
454 529 }
455 530
456 531 $body = @unserialize($request['body'], ['allowed_classes' => false]);
457 - if ( $body !== FALSE && is_array($body) && !empty($body) )
532 + if ( $body !== FALSE && is_array($body) )
458 533 {
459 534 update_option( 'propertyhive_license_key_details', $body, 'no' );
460 535 }
461 536 else
462 537 {
463 - update_option( 'propertyhive_license_key_details', array(), 'no' );
464 - update_option( 'propertyhive_license_key_error', 'Failed to process response data: ' . print_r($request['body'], true), 'no' );
538 + update_option( 'propertyhive_license_key_error', __( 'The license service returned invalid license data.', 'propertyhive' ) . ' ' . print_r($body, true), 'no' );
465 539 }
466 540 }
467 541
468 542 public function get_current_license()
@@ -507,9 +581,9 @@
507 581 $url = 'https://wp-property-hive.com/?';
508 582 $url .= 'wc-api=wc-am-api&';
509 583 $url .= 'wc_am_action=activate&';
510 584 $url .= 'instance=' . $instance_id . '&';
511 - $url .= 'object=' . parse_url( get_site_url(), PHP_URL_HOST ) . '&';
585 + $url .= 'object=' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '&';
512 586 $url .= 'product_id=' . $license['product_id'] . '&';
513 587 $url .= 'api_key=' . $license_key;
514 588
515 589 $response = wp_remote_post( $url, array(
@@ -545,9 +619,9 @@
545 619 if ( json_last_error() !== JSON_ERROR_NONE )
546 620 {
547 621 $return = array(
548 622 'success' => false,
549 - 'error' => __( 'Failed to decode response when activating license key status. Please try again', 'propertyhive' ) . ': ' . print_r( $result, true )
623 + 'error' => __( 'Failed to decode response when activating license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
550 624 );
551 625 return $return;
552 626 }
553 627
@@ -572,9 +646,9 @@
572 646 else
573 647 {
574 648 $return = array(
575 649 'success' => false,
576 - 'error' => __( 'Something went wrong when trying to activate license key', 'propertyhive' ) . ': ' . print_r($body, true)
650 + 'error' => __( 'Something went wrong when trying to activate license key', 'propertyhive' ) . ': ' . wp_json_encode( $body )
577 651 );
578 652 return $return;
579 653 }
580 654 }
@@ -606,9 +680,9 @@
606 680 $url = 'https://wp-property-hive.com/?';
607 681 $url .= 'wc-api=wc-am-api&';
608 682 $url .= 'wc_am_action=deactivate&';
609 683 $url .= 'instance=' . $instance_id . '&';
610 - $url .= 'object=' . parse_url( get_site_url(), PHP_URL_HOST ) . '&';
684 + $url .= 'object=' . wp_parse_url( get_site_url(), PHP_URL_HOST ) . '&';
611 685 $url .= 'product_id=' . $license['product_id'] . '&';
612 686 $url .= 'api_key=' . $license_key;
613 687
614 688 $response = wp_remote_post( $url, array(
@@ -644,9 +718,9 @@
644 718 if ( json_last_error() !== JSON_ERROR_NONE )
645 719 {
646 720 $return = array(
647 721 'success' => false,
648 - 'error' => __( 'Failed to decode response when deactivating license key status. Please try again', 'propertyhive' ) . ': ' . print_r( $result, true )
722 + 'error' => __( 'Failed to decode response when deactivating license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
649 723 );
650 724 return $return;
651 725 }
652 726
@@ -671,9 +745,9 @@
671 745 else
672 746 {
673 747 $return = array(
674 748 'success' => false,
675 - 'error' => __( 'Something went wrong when trying to deactivate license key', 'propertyhive' ) . ': ' . print_r($body, true)
749 + 'error' => __( 'Something went wrong when trying to deactivate license key', 'propertyhive' ) . ': ' . wp_json_encode( $body )
676 750 );
677 751 return $return;
678 752 }
679 753 }
@@ -774,9 +848,9 @@
774 848 if ( json_last_error() !== JSON_ERROR_NONE )
775 849 {
776 850 $return = array(
777 851 'success' => false,
778 - 'error' => __( 'Failed to decode response when requesting license key product list. Please try again', 'propertyhive' ) . ': ' . print_r( $result, true )
852 + 'error' => __( 'Failed to decode response when requesting license key product list. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
779 853 );
780 854
781 855 $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
782 856 if ( !empty($last_known) )
@@ -795,8 +869,9 @@
795 869 if ( isset($body['data']['product_list']['wc_subs_resources']) && !empty($body['data']['product_list']['wc_subs_resources']) )
796 870 {
797 871 $package = false;
798 872 $product_id = '';
873 + $is_trial = null;
799 874
800 875 foreach ( $body['data']['product_list']['wc_subs_resources'] as $resource )
801 876 {
802 877 if ( isset($resource['product_id']) )
@@ -809,8 +884,12 @@
809 884 {
810 885 $package = 'complete';
811 886 }
812 887 $product_id = $resource['product_id'];
888 + $is_trial = isset( $resource['is_trial'] )
889 + && is_bool( $resource['is_trial'] )
890 + ? $resource['is_trial']
891 + : null;
813 892 }
814 893 }
815 894
816 895 if ( $package !== FALSE )
@@ -817,9 +896,10 @@
817 896 {
818 897 $return = array(
819 898 'success' => true,
820 899 'package' => $package,
821 - 'product_id' => $product_id
900 + 'product_id' => $product_id,
901 + 'is_trial' => $is_trial,
822 902 );
823 903 }
824 904 else
825 905 {
@@ -832,9 +912,9 @@
832 912 else
833 913 {
834 914 $return = array(
835 915 'success' => false,
836 - 'error' => __( 'API key doesn\'t appear to belong to any orders', 'propertyhive' ) . ': ' . print_r($body, true)
916 + 'error' => __( 'API key doesn\'t appear to belong to any orders', 'propertyhive' ) . ': ' . wp_json_encode( $body )
837 917 );
838 918 }
839 919 }
840 920 else
@@ -852,9 +932,9 @@
852 932 else
853 933 {
854 934 $return = array(
855 935 'success' => false,
856 - 'error' => __( 'Something went wrong when requesting license key product list', 'propertyhive' ) . ': ' . print_r($body, true)
936 + 'error' => __( 'Something went wrong when requesting license key product list', 'propertyhive' ) . ': ' . wp_json_encode( $body )
857 937 );
858 938
859 939 $last_known = get_option('ph_pro_last_known_license_product_id_and_package', array());
860 940 if ( !empty($last_known) )
@@ -967,9 +1047,9 @@
967 1047 if ( json_last_error() !== JSON_ERROR_NONE )
968 1048 {
969 1049 $return = array(
970 1050 'success' => false,
971 - 'error' => __( 'Failed to decode response when requesting license key status. Please try again', 'propertyhive' ) . ': ' . print_r( $result, true )
1051 + 'error' => __( 'Failed to decode response when requesting license key status. Please try again', 'propertyhive' ) . ': ' . wp_json_encode( $result )
972 1052 );
973 1053
974 1054 // error for some reason. Return last known status
975 1055 $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );
@@ -1017,9 +1097,9 @@
1017 1097 else
1018 1098 {
1019 1099 $return = array(
1020 1100 'success' => false,
1021 - 'error' => __( 'Something went wrong when requesting license key status', 'propertyhive' ) . ': ' . print_r($body, true)
1101 + 'error' => __( 'Something went wrong when requesting license key status', 'propertyhive' ) . ': ' . wp_json_encode( $body )
1022 1102 );
1023 1103
1024 1104 // error for some reason. Return last known status
1025 1105 $previous_license_key_status = get_option( 'propertyhive_pro_license_key_status', '' );