PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.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 1.4.61 All 261 releases
← All changes | includes/ph-formatting-functions.php +108 -1 2.2.62.3.0 View file →
@@ -1,5 +1,8 @@
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.
4 +
2 5 /**
3 6 * PropertyHive Formatting
4 7 *
5 8 * Functions for formatting data.
@@ -14,12 +17,97 @@
14 17 exit; // Exit if accessed directly
15 18 }
16 19
17 20 /**
21 + * Clean stored description HTML while retaining ordinary links and tour frames.
22 + */
23 +function propertyhive_sanitize_description( $html ) {
24 + $allowed = wp_kses_allowed_html( 'post' );
25 + $allowed['iframe'] = array_fill_keys( array( 'src', 'title', 'width', 'height', 'allow', 'allowfullscreen', 'frameborder', 'loading', 'referrerpolicy' ), true );
26 + $clean = wp_kses( $html, $allowed, wp_allowed_protocols() );
27 +
28 + // KSES attribute callbacks are unavailable on WordPress 5.6. Check only the
29 + // normalized iframe tags here, including quoted attributes containing >.
30 + return preg_replace_callback( '~<iframe\b(?:[^>"\']++|"[^"]*+"|\'[^\']*+\')*>~i', static function( $match ) {
31 + $attributes = wp_kses_hair( substr( $match[0], 7, -1 ), wp_allowed_protocols() );
32 + $sources = array();
33 + foreach ( $attributes as $name => $attribute ) {
34 + if ( strtolower( $name ) === 'src' ) {
35 + $sources[] = $attribute['value'];
36 + }
37 + }
38 + if ( empty( $sources ) ) {
39 + return $match[0];
40 + }
41 + if ( count( $sources ) !== 1 ) {
42 + return '<iframe>';
43 + }
44 + $url = html_entity_decode( $sources[0], ENT_QUOTES, 'UTF-8' );
45 + $parts = wp_parse_url( $url );
46 + if ( ! is_array( $parts ) || empty( $parts['host'] ) || ! preg_match( '~^(?:https?:)?//~i', $url ) || ( isset( $parts['scheme'] ) && ! in_array( strtolower( $parts['scheme'] ), array( 'http', 'https' ), true ) ) ) {
47 + return '<iframe>';
48 + }
49 + if ( ! apply_filters( 'propertyhive_description_iframe_url_allowed', true, $url ) ) {
50 + return '<iframe>';
51 + }
52 + return $match[0];
53 + }, $clean );
54 +}
55 +
56 +/**
57 + * Translate built-in rent frequency labels, preserving custom labels.
58 + *
59 + * @param string $frequency Stored frequency.
60 + * @return string Display label.
61 + */
62 +function propertyhive_get_rent_frequency_label( $frequency ) {
63 + $labels = array(
64 + 'pd' => __( 'pd', 'propertyhive' ),
65 + 'pppw' => __( 'pppw', 'propertyhive' ),
66 + 'pw' => __( 'pw', 'propertyhive' ),
67 + 'pcm' => __( 'pcm', 'propertyhive' ),
68 + 'pq' => __( 'pq', 'propertyhive' ),
69 + 'pa' => __( 'pa', 'propertyhive' ),
70 + );
71 + return isset( $labels[$frequency] ) ? $labels[$frequency] : $frequency;
72 +}
73 +
74 +/**
75 + * Translate built-in CRM statuses without passing dynamic text to gettext.
76 + *
77 + * @param string $status Stored status.
78 + * @return string Display label.
79 + */
80 +function propertyhive_get_status_label( $status ) {
81 + $labels = array(
82 + 'pending' => __( 'Pending', 'propertyhive' ),
83 + 'confirmed' => __( 'Confirmed', 'propertyhive' ),
84 + 'unconfirmed' => __( 'Unconfirmed', 'propertyhive' ),
85 + 'carried_out' => __( 'Carried Out', 'propertyhive' ),
86 + 'awaiting_feedback' => __( 'Awaiting Feedback', 'propertyhive' ),
87 + 'feedback_passed_on' => __( 'Feedback Passed On', 'propertyhive' ),
88 + 'feedback_not_passed_on' => __( 'Feedback Not Passed On', 'propertyhive' ),
89 + 'cancelled' => __( 'Cancelled', 'propertyhive' ),
90 + 'no_show' => __( 'No Show', 'propertyhive' ),
91 + 'offer_made' => __( 'Offer Made', 'propertyhive' ),
92 + 'accepted' => __( 'Accepted', 'propertyhive' ),
93 + 'declined' => __( 'Declined', 'propertyhive' ),
94 + 'current' => __( 'Current', 'propertyhive' ),
95 + 'exchanged' => __( 'Exchanged', 'propertyhive' ),
96 + 'completed' => __( 'Completed', 'propertyhive' ),
97 + 'fallen_through' => __( 'Fallen Through', 'propertyhive' ),
98 + 'interested' => __( 'Interested', 'propertyhive' ),
99 + 'not_interested' => __( 'Not Interested', 'propertyhive' ),
100 + );
101 + return isset( $labels[$status] ) ? $labels[$status] : ucwords( str_replace( '_', ' ', $status ) );
102 +}
103 +
104 +/**
18 105 * Clean variables using sanitize_text_field.
19 106 * @param string|array $var
20 107 * @return string|array
21 108 */
109 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_clean; the established callable name is part of the plugin/extension API and must remain stable.
22 110 function ph_clean( $var ) {
23 111
24 112 if ( is_array( $var ) ) {
25 113 return array_map( 'ph_clean', $var );
@@ -33,8 +121,9 @@
33 121 * @param string
34 122 * @return string
35 123 */
36 124
125 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_clean_telephone_number; the established callable name is part of the plugin/extension API and must remain stable.
37 126 function ph_clean_telephone_number( $var ) {
38 127
39 128 return preg_replace( "/[^0-9,]/", "", $var );
40 129 }
@@ -43,8 +132,9 @@
43 132 * Format monetary number value with decimal and thousands separators for display in a form field
44 133 * @param string
45 134 * @return string
46 135 */
136 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_display_price_field; the established callable name is part of the plugin/extension API and must remain stable.
47 137 function ph_display_price_field( $var, $use_separator_setting = false )
48 138 {
49 139 $float_var = (float)$var;
50 140
@@ -79,8 +169,9 @@
79 169 *
80 170 * @param mixed $color
81 171 * @return string
82 172 */
173 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_rgb_from_hex; the established callable name is part of the plugin/extension API and must remain stable.
83 174 function ph_rgb_from_hex( $color ) {
84 175 $color = str_replace( '#', '', $color );
85 176 // Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF"
86 177 $color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color );
@@ -102,8 +193,9 @@
102 193 * @param mixed $color
103 194 * @param int $factor (default: 30)
104 195 * @return string
105 196 */
197 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_hex_darker; the established callable name is part of the plugin/extension API and must remain stable.
106 198 function ph_hex_darker( $color, $factor = 30 ) {
107 199 $base = ph_rgb_from_hex( $color );
108 200 $color = '#';
109 201
@@ -131,8 +223,9 @@
131 223 * @param mixed $color
132 224 * @param int $factor (default: 30)
133 225 * @return string
134 226 */
227 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_hex_lighter; the established callable name is part of the plugin/extension API and must remain stable.
135 228 function ph_hex_lighter( $color, $factor = 30 ) {
136 229 $base = ph_rgb_from_hex( $color );
137 230 $color = '#';
138 231
@@ -162,8 +255,9 @@
162 255 * @param string $dark (default: '#000000')
163 256 * @param string $light (default: '#FFFFFF')
164 257 * @return string
165 258 */
259 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_light_or_dark; the established callable name is part of the plugin/extension API and must remain stable.
166 260 function ph_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
167 261
168 262 $hex = str_replace( '#', '', $color );
169 263
@@ -184,8 +278,9 @@
184 278 *
185 279 * @param string $hex
186 280 * @return string
187 281 */
282 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_format_hex; the established callable name is part of the plugin/extension API and must remain stable.
188 283 function ph_format_hex( $hex ) {
189 284
190 285 $hex = trim( str_replace( '#', '', $hex ) );
191 286
@@ -196,8 +291,9 @@
196 291 return $hex ? '#' . $hex : null;
197 292 }
198 293 }
199 294
295 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_nl2br; the established callable name is part of the plugin/extension API and must remain stable.
200 296 function ph_nl2br($str)
201 297 {
202 298 // Match any <ul> or <ol> with their content
203 299 $pattern = '/(<ul[^>]*>.*?<\/ul>|<ol[^>]*>.*?<\/ol>)/is';
@@ -213,8 +309,9 @@
213 309 // Reassemble the string
214 310 return implode('', $parts);
215 311 }
216 312
313 +// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_split_address_into_fields; the established callable name is part of the plugin/extension API and must remain stable.
217 314 function ph_split_address_into_fields( $address )
218 315 {
219 316 $fields = [
220 317 'address_name_number' => '',
@@ -277,5 +374,15 @@
277 374 if (isset($remainingParts[1])) $fields['address_three'] = $remainingParts[1];
278 375 if (isset($remainingParts[2])) $fields['address_four'] = $remainingParts[2];
279 376
280 377 return $fields;
281 -}
378 +}
379 +/**
380 + * Resolve translated built-in or extension-provided department labels.
381 + *
382 + * @param string $department Department key.
383 + * @return string Department label.
384 + */
385 +function propertyhive_get_department_label( $department ) {
386 + $labels = ph_get_departments();
387 + return isset( $labels[$department] ) ? $labels[$department] : ucwords( str_replace( '-', ' ', $department ) );
388 +}