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
← All changes | includes/class-ph-shortcodes.php +64 -17 2.2.62.3.0 View file →
@@ -1,6 +1,9 @@
1 1 <?php
2 +// phpcs:set WordPress.Security.ValidatedSanitizedInput customSanitizingFunctions[] ph_clean
3 +// ph_clean() recursively sanitizes text; presence, shape and unslashing checks remain separate.
2 4
5 +
3 6 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4 7
5 8 /**
6 9 * PH_Shortcodes class.
@@ -35,8 +38,9 @@
35 38 'propertyhive_reset_password_form' => __CLASS__ . '::reset_password_form',
36 39 );
37 40
38 41 foreach ( $shortcodes as $shortcode => $function ) {
42 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Public shortcode registration filter; extensions can customize each shortcode tag through this existing dynamic hook contract.
39 43 add_shortcode( apply_filters( "{$shortcode}_shortcode_tag", $shortcode ), $function );
40 44 }
41 45 }
42 46
@@ -60,10 +64,12 @@
60 64
61 65 $before = empty( $wrapper['before'] ) ? '<div class="' . esc_attr( $wrapper['class'] ) . '">' : $wrapper['before'];
62 66 $after = empty( $wrapper['after'] ) ? '</div>' : $wrapper['after'];
63 67
68 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Wrapper HTML is supplied by PHP callers; the default class is escaped when assembled.
64 69 echo $before;
65 70 call_user_func( $function, $atts );
71 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Closing wrapper HTML is supplied by PHP callers.
66 72 echo $after;
67 73
68 74 return ob_get_clean();
69 75 }
@@ -99,8 +105,9 @@
99 105 $form_controls = apply_filters( 'propertyhive_search_form_fields_after', $form_controls, $atts );
100 106
101 107 if (
102 108 isset($atts['default_department']) && in_array($atts['default_department'], array_keys( ph_get_departments() )) &&
109 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public read-only search form default; no state change.
103 110 ( !isset($_REQUEST['department']) )
104 111 )
105 112 {
106 113 $form_controls['department']['value'] = $atts['default_department'];
@@ -126,10 +133,12 @@
126 133 $atts = shortcode_atts( array(
127 134 'columns' => '2',
128 135 'orderby' => 'meta_value_num',
129 136 'order' => 'desc',
137 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- These lines declare shortcode defaults; they do not pass a meta_key/exclude value to WP_Query or get_posts. 131 is the properties shortcode_atts default meta_key; 133/751/1045/1338 are exclude defaults in shortcode_atts.
130 138 'meta_key' => '_price_actual',
131 139 'ids' => '',
140 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- These lines declare shortcode defaults; they do not pass a meta_key/exclude value to WP_Query or get_posts. 131 is the properties shortcode_atts default meta_key; 133/751/1045/1338 are exclude defaults in shortcode_atts.
132 141 'exclude' => '',
133 142 'department' => '', // residential-sales / residential-lettings / commercial / any custom department
134 143 'minimum_price' => '',
135 144 'maximum_price' => '',
@@ -364,8 +373,9 @@
364 373 if ( isset($atts['keyword']) && $atts['keyword'] != '' )
365 374 {
366 375 $atts['keyword'] = sanitize_text_field( trim( $atts['keyword'] ) );
367 376
377 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Preserve the original request verbatim only to restore it after this shortcode's query; it is not output or persisted.
368 378 $original_keyword = isset($_REQUEST['keyword']) ? $_REQUEST['keyword'] : '';
369 379 $_REQUEST['keyword'] = $atts['keyword'];
370 380
371 381 add_filter( 'posts_where', array( PH()->query, 'keyword_excerpt_where' ), 10, 2 );
@@ -604,8 +614,9 @@
604 614 get_option( 'propertyhive_active_departments_commercial' ) == 'yes'
605 615 )
606 616 )
607 617 {
618 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
608 619 $atts['meta_key'] = '_floor_area_from_sqft';
609 620 }
610 621
611 622 // Get which page we're currently viewing from the URL
@@ -618,13 +629,16 @@
618 629 'orderby' => $atts['orderby'],
619 630 'order' => $atts['order'],
620 631 'posts_per_page' => $atts['posts_per_page'],
621 632 'paged' => $paged,
633 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property eligibility and matching fields live in the established metadata schema; retain these filters and the shortcode page limit.
622 634 'meta_query' => $meta_query,
635 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Property taxonomy filters are required by this shortcode; WordPress builds the query and the shortcode page limit is retained.
623 636 'tax_query' => $tax_query,
624 637 'has_password' => false,
625 638 );
626 639 if ( ! empty( $atts['meta_key'] ) ) {
640 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
627 641 $args['meta_key'] = $atts['meta_key'];
628 642 }
629 643
630 644 if ( ! empty( $atts['ids'] ) )
@@ -640,8 +654,9 @@
640 654 {
641 655 $exclude_ids = array_map( 'absint', explode( ',', $atts['exclude'] ) );
642 656 $exclude_ids = array_filter( $exclude_ids );
643 657 if ( ! empty( $exclude_ids ) ) {
658 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Explicit shortcode exclusions are validated as integer IDs above; retain this published selection feature within the shortcode page limit.
644 659 $args['post__not_in'] = $exclude_ids;
645 660 }
646 661 }
647 662 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
@@ -646,8 +661,9 @@
646 661 }
647 662 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
648 663 {
649 664 $args['orderby'] = 'meta_value';
665 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
650 666 $args['meta_key'] = '_on_market_change_date';
651 667 }
652 668
653 669 $args['orderby'] .= ' post_title';
@@ -693,9 +709,10 @@
693 709 if ( isset($atts['carousel']) && !empty($atts['carousel']) )
694 710 {
695 711 $loop_start = str_replace("class=\"properties", "class=\"properties propertyhive-shortcode-carousel", $loop_start);
696 712 }
697 - echo $loop_start;
713 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Buffered loop template HTML; preserve theme overrides and the static carousel class insertion.
714 + echo $loop_start;
698 715 ?>
699 716
700 717 <?php while ( $properties->have_posts() ) : $properties->the_post(); ?>
701 718
@@ -746,8 +763,9 @@
746 763 'sale_by_id' => '',
747 764 'location_id' => '',
748 765 'commercial_for_sale' => '',
749 766 'commercial_to_rent' => '',
767 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- These lines declare shortcode defaults; they do not pass a meta_key/exclude value to WP_Query or get_posts. 131 is the properties shortcode_atts default meta_key; 133/751/1045/1338 are exclude defaults in shortcode_atts.
750 768 'exclude' => '',
751 769 'orderby' => 'date',
752 770 'order' => 'desc',
753 771 'no_results_output' => '',
@@ -937,9 +955,11 @@
937 955 'posts_per_page' => $atts['per_page'],
938 956 'paged' => $paged,
939 957 'orderby' => $atts['orderby'],
940 958 'order' => $atts['order'],
959 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property eligibility and matching fields live in the established metadata schema; retain these filters and the shortcode page limit.
941 960 'meta_query' => $meta_query,
961 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Property taxonomy filters are required by this shortcode; WordPress builds the query and the shortcode page limit is retained.
942 962 'tax_query' => $tax_query,
943 963 'has_password' => false,
944 964 );
945 965
@@ -947,8 +967,9 @@
947 967 {
948 968 $exclude_ids = array_map( 'absint', explode( ',', $atts['exclude'] ) );
949 969 $exclude_ids = array_filter( $exclude_ids );
950 970 if ( ! empty( $exclude_ids ) ) {
971 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Explicit shortcode exclusions are validated as integer IDs above; retain this published selection feature within the shortcode page limit.
951 972 $args['post__not_in'] = $exclude_ids;
952 973 }
953 974 }
954 975
@@ -954,8 +975,9 @@
954 975
955 976 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
956 977 {
957 978 $args['orderby'] = 'meta_value';
979 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
958 980 $args['meta_key'] = '_on_market_change_date';
959 981 }
960 982
961 983 $args['orderby'] .= ' post_title';
@@ -992,9 +1014,10 @@
992 1014 if ( isset($atts['carousel']) && !empty($atts['carousel']) )
993 1015 {
994 1016 $loop_start = str_replace("class=\"properties", "class=\"properties propertyhive-shortcode-carousel", $loop_start);
995 1017 }
996 - echo $loop_start;
1018 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Buffered loop template HTML; preserve theme overrides and the static carousel class insertion.
1019 + echo $loop_start;
997 1020 ?>
998 1021
999 1022 <?php while ( $properties->have_posts() ) : $properties->the_post(); ?>
1000 1023
@@ -1040,11 +1063,13 @@
1040 1063 'address_keyword' => '',
1041 1064 'office_id' => '',
1042 1065 'negotiator_id' => '',
1043 1066 'availability_id' => '',
1067 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- These lines declare shortcode defaults; they do not pass a meta_key/exclude value to WP_Query or get_posts. 131 is the properties shortcode_atts default meta_key; 133/751/1045/1338 are exclude defaults in shortcode_atts.
1044 1068 'exclude' => '',
1045 1069 'orderby' => 'rand',
1046 1070 'order' => 'desc',
1071 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Shortcode default declaration only; no query executes here.
1047 1072 'meta_key' => '',
1048 1073 'no_results_output' => '',
1049 1074 'pagination' => '',
1050 1075 'show_order' => '',
@@ -1211,11 +1236,13 @@
1211 1236 'compare' => 'IN',
1212 1237 );
1213 1238 }
1214 1239
1240 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property eligibility and matching fields live in the established metadata schema; retain these filters and the shortcode page limit.
1215 1241 $args['meta_query'] = $meta_query;
1216 1242
1217 1243 if ( ! empty( $atts['meta_key'] ) ) {
1244 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
1218 1245 $args['meta_key'] = $atts['meta_key'];
1219 1246 }
1220 1247
1221 1248 $tax_query = array();
@@ -1229,8 +1256,9 @@
1229 1256 );
1230 1257 }
1231 1258
1232 1259 if ( ! empty( $tax_query ) ) {
1260 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Property taxonomy filters are required by this shortcode; WordPress builds the query and the shortcode page limit is retained.
1233 1261 $args['tax_query'] = $tax_query;
1234 1262 }
1235 1263
1236 1264 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
@@ -1235,8 +1263,9 @@
1235 1263
1236 1264 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
1237 1265 {
1238 1266 $args['orderby'] = 'meta_value';
1267 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
1239 1268 $args['meta_key'] = '_on_market_change_date';
1240 1269 }
1241 1270
1242 1271 $args['orderby'] .= ' post_title';
@@ -1245,8 +1274,9 @@
1245 1274 {
1246 1275 $exclude_ids = array_map( 'absint', explode( ',', $atts['exclude'] ) );
1247 1276 $exclude_ids = array_filter( $exclude_ids );
1248 1277 if ( ! empty( $exclude_ids ) ) {
1278 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Explicit shortcode exclusions are validated as integer IDs above; retain this published selection feature within the shortcode page limit.
1249 1279 $args['post__not_in'] = $exclude_ids;
1250 1280 }
1251 1281 }
1252 1282
@@ -1282,9 +1312,10 @@
1282 1312 if ( isset($atts['carousel']) && !empty($atts['carousel']) )
1283 1313 {
1284 1314 $loop_start = str_replace("class=\"properties", "class=\"properties propertyhive-shortcode-carousel", $loop_start);
1285 1315 }
1286 - echo $loop_start;
1316 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Buffered loop template HTML; preserve theme overrides and the static carousel class insertion.
1317 + echo $loop_start;
1287 1318 ?>
1288 1319
1289 1320 <?php while ( $properties->have_posts() ) : $properties->the_post(); ?>
1290 1321
@@ -1333,8 +1364,9 @@
1333 1364 'property_id' => '',
1334 1365 'availability_id' => '',
1335 1366 'property_type_id' => '',
1336 1367 'match_property_type' => '',
1368 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- These lines declare shortcode defaults; they do not pass a meta_key/exclude value to WP_Query or get_posts. 131 is the properties shortcode_atts default meta_key; 133/751/1045/1338 are exclude defaults in shortcode_atts.
1337 1369 'exclude' => '',
1338 1370 'no_results_output' => '',
1339 1371 'carousel' => '',
1340 1372 ), $atts, 'similar_properties' );
@@ -1374,8 +1406,9 @@
1374 1406 $department = get_post_meta( $atts['property_id'], '_department', true );
1375 1407
1376 1408 $args = array(
1377 1409 'post_type' => 'property',
1410 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Similar-property results must exclude the one current property; the result count is limited by per_page.
1378 1411 'post__not_in' => array($atts['property_id']),
1379 1412 'post_status' => ( ( is_user_logged_in() && current_user_can( 'manage_propertyhive' ) ) ? array('publish', 'private') : 'publish' ),
1380 1413 'ignore_sticky_posts' => 1,
1381 1414 'posts_per_page' => $atts['per_page'],
@@ -1604,8 +1637,9 @@
1604 1637 'value' => $address_field,
1605 1638 );
1606 1639 }
1607 1640
1641 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Property eligibility and matching fields live in the established metadata schema; retain these filters and the shortcode page limit.
1608 1642 $args['meta_query'] = $meta_query;
1609 1643
1610 1644 $tax_query = array();
1611 1645
@@ -1671,8 +1705,9 @@
1671 1705 }
1672 1706 }
1673 1707
1674 1708 if ( ! empty( $tax_query ) ) {
1709 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Property taxonomy filters are required by this shortcode; WordPress builds the query and the shortcode page limit is retained.
1675 1710 $args['tax_query'] = $tax_query;
1676 1711 }
1677 1712
1678 1713 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
@@ -1677,8 +1712,9 @@
1677 1712
1678 1713 if ( isset($atts['orderby']) && $atts['orderby'] == 'date' )
1679 1714 {
1680 1715 $args['orderby'] = 'meta_value';
1716 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
1681 1717 $args['meta_key'] = '_on_market_change_date';
1682 1718 }
1683 1719
1684 1720 $args['orderby'] .= ' post_title';
@@ -1687,8 +1723,9 @@
1687 1723 {
1688 1724 $exclude_ids = array_map( 'absint', explode( ',', $atts['exclude'] ) );
1689 1725 $exclude_ids = array_filter( $exclude_ids );
1690 1726 if ( ! empty( $exclude_ids ) ) {
1727 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Explicit shortcode exclusions are validated as integer IDs above; retain this published selection feature within the shortcode page limit.
1691 1728 $args['post__not_in'] = $exclude_ids;
1692 1729 }
1693 1730 }
1694 1731
@@ -1707,9 +1744,10 @@
1707 1744 if ( isset($atts['carousel']) && !empty($atts['carousel']) )
1708 1745 {
1709 1746 $loop_start = str_replace("class=\"properties", "class=\"properties propertyhive-shortcode-carousel", $loop_start);
1710 1747 }
1711 - echo $loop_start;
1748 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Buffered loop template HTML; preserve theme overrides and the static carousel class insertion.
1749 + echo $loop_start;
1712 1750 ?>
1713 1751
1714 1752 <?php while ( $properties->have_posts() ) : $properties->the_post(); ?>
1715 1753
@@ -1758,9 +1796,9 @@
1758 1796 ), $atts, 'property_map' );
1759 1797
1760 1798 ob_start();
1761 1799
1762 - echo get_property_map( $atts );
1800 + get_property_map( $atts );
1763 1801
1764 1802 return ob_get_clean();
1765 1803 }
1766 1804
@@ -1783,9 +1821,9 @@
1783 1821 ), $atts, 'property_static_map' );
1784 1822
1785 1823 ob_start();
1786 1824
1787 - echo get_property_static_map( $atts );
1825 + get_property_static_map( $atts );
1788 1826
1789 1827 return ob_get_clean();
1790 1828 }
1791 1829
@@ -1807,9 +1845,9 @@
1807 1845 ), $atts, 'property_street_view' );
1808 1846
1809 1847 ob_start();
1810 1848
1811 - echo get_property_street_view( $atts );
1849 + get_property_street_view( $atts );
1812 1850
1813 1851 return ob_get_clean();
1814 1852 }
1815 1853
@@ -1845,9 +1883,9 @@
1845 1883 }
1846 1884
1847 1885 if ( $property->get_office_address( $atts['address_separator'] ) != '' )
1848 1886 {
1849 - echo '<div class="office-address">' . $property->get_office_address( $atts['address_separator'] ) . '</div>';
1887 + echo '<div class="office-address">' . wp_kses_post( $property->get_office_address( $atts['address_separator'] ) ) . '</div>';
1850 1888 }
1851 1889
1852 1890 if ( $property->office_telephone_number != '' )
1853 1891 {
@@ -1910,12 +1948,12 @@
1910 1948
1911 1949 ob_start();
1912 1950
1913 1951 $api_key = get_option('propertyhive_google_maps_api_key', '');
1914 - wp_register_script('googlemaps', '//maps.googleapis.com/maps/api/js?' . ( ( $api_key != '' && $api_key !== FALSE ) ? 'key=' . $api_key : '' ), false, '3');
1952 + wp_register_script('googlemaps', '//maps.googleapis.com/maps/api/js?' . ( ( $api_key != '' && $api_key !== FALSE ) ? 'key=' . $api_key : '' ), false, '3', true );
1915 1953 wp_enqueue_script('googlemaps');
1916 1954
1917 - echo '<div id="office_map_canvas" style="height:' . str_replace( "px", "", ( ( isset($atts['height']) && !empty($atts['height']) && is_numeric($atts['height']) ) ? (int)$atts['height'] : '400' ) ) . 'px"></div>';
1955 + echo '<div id="office_map_canvas" style="height:' . (int) ( ( isset($atts['height']) && !empty($atts['height']) && is_numeric($atts['height']) ) ? $atts['height'] : 400 ) . 'px"></div>';
1918 1956 ?>
1919 1957 <script>
1920 1958
1921 1959 // We declare vars globally so developers can access them
@@ -1936,8 +1974,9 @@
1936 1974 $args['p'] = (int)$atts['office_id'];
1937 1975 }
1938 1976 else
1939 1977 {
1978 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Selects the primary office from the established metadata schema and returns at most one office.
1940 1979 $args['meta_query'] = array(
1941 1980 array(
1942 1981 'key' => 'primary',
1943 1982 'value' => '1'
@@ -1977,11 +2016,15 @@
1977 2016 if ( class_exists( 'PH_Map_Search' ) )
1978 2017 {
1979 2018 $map_add_on_settings = get_option( 'propertyhive_map_search', array() );
1980 2019
1981 - if ( isset($map_add_on_settings['style_js']) && trim($map_add_on_settings['style_js']) != '' )
2020 + if ( isset($map_add_on_settings['style_js']) && is_string($map_add_on_settings['style_js']) && trim($map_add_on_settings['style_js']) != '' )
1982 2021 {
1983 - echo 'map_options.styles = ' . trim($map_add_on_settings['style_js']) . ';';
2022 + // Google Maps styles are JSON arrays, including legacy Snazzy Maps style properties.
2023 + $map_styles = json_decode( $map_add_on_settings['style_js'] );
2024 + if ( is_array( $map_styles ) ) {
2025 + echo 'map_options.styles = ' . wp_json_encode( $map_styles, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ) . ';';
2026 + }
1984 2027 }
1985 2028 }
1986 2029
1987 2030 do_action( 'propertyhive_office_map_options' );
@@ -2192,17 +2235,19 @@
2192 2235 ph_get_template( 'account/invalid-access.php' );
2193 2236 return ob_get_clean();
2194 2237 }
2195 2238
2196 - // check key provided is valid
2197 - if ( !isset($_GET['key']) || empty(ph_clean($_GET['key'])) || !isset($_GET['id']) || empty(absint($_GET['id'])) )
2239 + // Display only: WordPress validates the opaque reset key; the reset action has its own nonce.
2240 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- An opaque key must remain intact for check_password_reset_key().
2241 + $key = isset( $_GET['key'] ) && is_string( $_GET['key'] ) ? wp_unslash( $_GET['key'] ) : '';
2242 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only selects the user whose reset key WordPress verifies below.
2243 + $user_id = isset( $_GET['id'] ) && is_string( $_GET['id'] ) ? absint( $_GET['id'] ) : 0;
2244 + if ( $key === '' || $user_id === 0 )
2198 2245 {
2199 2246 echo esc_html(__( 'Invalid key or id provided. Please try again', 'propertyhive' ));
2200 2247 return ob_get_clean();
2201 2248 }
2202 2249
2203 - $key = ph_clean($_GET['key']);
2204 - $user_id = absint($_GET['id']);
2205 2250
2206 2251 $userdata = get_userdata( $user_id );
2207 2252 $user_login = $userdata ? $userdata->user_login : '';
2208 2253
@@ -2260,9 +2305,10 @@
2260 2305 private static function get_show_order_args( $atts, $args )
2261 2306 {
2262 2307 $orderby = '';
2263 2308
2264 - if ( isset( $_GET['orderby'] ) && $_GET['orderby'] != '' )
2309 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public read-only sort selection; the query helper validates the ordering value.
2310 + if ( isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) && $_GET['orderby'] != '' )
2265 2311 {
2266 2312 $PH_Query = new PH_Query();
2267 2313 $ordering_args = $PH_Query->get_search_results_ordering_args();
2268 2314
@@ -2270,8 +2316,9 @@
2270 2316 $args['order'] = $ordering_args['order'];
2271 2317
2272 2318 if ( isset( $ordering_args['meta_key'] ) )
2273 2319 {
2320 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Property sorting uses the established price, floor-area or market-date metadata; retain the selected ordering and existing query limits.
2274 2321 $args['meta_key'] = $ordering_args['meta_key'];
2275 2322 }
2276 2323 else
2277 2324 {