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 / ph-core-functions.php

ph-core-functions.php in Property Hive 2.3.0, at includes/ph-core-functions.php

533 lines 19.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PropertyHive Core Functions
4 *
5 * General core functions available on both the front-end and admin.
6 *
7 * @author PropertyHive
8 * @category Core
9 * @package PropertyHive/Functions
10 * @version 1.0.0
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
15 // Include core functions
16 include( 'ph-formatting-functions.php' );
17 include( 'ph-conditional-functions.php' );
18 include( 'ph-term-functions.php' );
19 include( 'ph-page-functions.php' );
20 include( 'ph-property-functions.php' );
21
22 /**
23 * Get template part (for templates like the single-property).
24 *
25 * @access public
26 * @param mixed $slug
27 * @param string $name (default: '')
28 * @return void
29 */
30 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_template_part; the established callable name is part of the plugin/extension API and must remain stable.
31 function ph_get_template_part( $slug, $name = '' ) {
32 $template = '';
33
34 // Look in yourtheme/slug-name.php and yourtheme/propertyhive/slug-name.php
35 if ( $name ) {
36 $template = locate_template( array( "{$slug}-{$name}.php", PH()->template_path() . "{$slug}-{$name}.php" ) );
37 }
38
39 // Get default slug-name.php
40 if ( ! $template && $name && file_exists( PH()->plugin_path() . "/templates/{$slug}-{$name}.php" ) ) {
41 $template = PH()->plugin_path() . "/templates/{$slug}-{$name}.php";
42 }
43
44 // If template file doesn't exist, look in yourtheme/slug.php and yourtheme/propertyhive/slug.php
45 if ( ! $template ) {
46 $template = locate_template( array( "{$slug}.php", PH()->template_path() . "{$slug}.php" ) );
47 }
48
49 // Allow 3rd party plugin filter template file from their plugin
50 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Existing public Property Hive extension hook ph_get_template_part; changing the established name would detach installed callbacks.
51 $template = apply_filters( 'ph_get_template_part', $template, $slug, $name );
52
53 if ( $template ) {
54 load_template( $template, false );
55 }
56 }
57
58 /**
59 * Get other templates (e.g. property images) passing attributes and including the file.
60 *
61 * @access public
62 * @param string $template_name
63 * @param array $args (default: array())
64 * @param string $template_path (default: '')
65 * @param string $default_path (default: '')
66 * @return void
67 */
68 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_template; the established callable name is part of the plugin/extension API and must remain stable.
69 function ph_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
70 if ( $args && is_array( $args ) ) {
71 extract( $args );
72 }
73
74 $located = ph_locate_template( $template_name, $template_path, $default_path );
75
76 if ( ! file_exists( $located ) ) {
77 _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', esc_html( $located ) ), '2.1' );
78 return;
79 }
80
81 do_action( 'propertyhive_before_template_part', $template_name, $template_path, $located, $args );
82
83 include( $located );
84
85 do_action( 'propertyhive_after_template_part', $template_name, $template_path, $located, $args );
86 }
87
88 /**
89 * Locate a template and return the path for inclusion.
90 *
91 * This is the load order:
92 *
93 * yourtheme / $template_path / $template_name
94 * yourtheme / $template_name
95 * $default_path / $template_name
96 *
97 * @access public
98 * @param string $template_name
99 * @param string $template_path (default: '')
100 * @param string $default_path (default: '')
101 * @return string
102 */
103 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_locate_template; the established callable name is part of the plugin/extension API and must remain stable.
104 function ph_locate_template( $template_name, $template_path = '', $default_path = '' ) {
105 if ( ! $template_path ) {
106 $template_path = PH()->template_path();
107 }
108
109 if ( ! $default_path ) {
110 $default_path = PH()->plugin_path() . '/templates/';
111 }
112
113 // Look within passed path within the theme - this is priority
114 $template = locate_template(
115 array(
116 trailingslashit( $template_path ) . $template_name,
117 $template_name
118 )
119 );
120
121 // Get default template
122 if ( ! $template ) {
123 $template = $default_path . $template_name;
124 }
125
126 // Return what we found
127 return apply_filters('propertyhive_locate_template', $template, $template_name, $template_path);
128 }
129
130 /**
131 * Set a cookie - wrapper for setcookie using WP constants
132 *
133 * @param string $name Name of the cookie being set
134 * @param string $value Value of the cookie
135 * @param integer $expire Expiry of the cookie
136 * @param string $secure Whether the cookie should be served only over https
137 */
138 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_setcookie; the established callable name is part of the plugin/extension API and must remain stable.
139 function ph_setcookie( $name, $value, $expire = 0, $secure = false ) {
140 if ( ! headers_sent() ) {
141 return setcookie( $name, $value, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
142 } elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
143 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Intentional developer notice, enabled only by WP_DEBUG, for a failed cookie API call; no request or private data is included.
144 trigger_error( "Cookie cannot be set - headers already sent", E_USER_NOTICE );
145 }
146 return false;
147 }
148
149 /**
150 * Get an image size.
151 *
152 * @param mixed $image_size
153 * @return array
154 */
155 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_image_size; the established callable name is part of the plugin/extension API and must remain stable.
156 function ph_get_image_size( $image_size ) {
157 if ( is_array( $image_size ) ) {
158 $width = isset( $image_size[0] ) ? $image_size[0] : '300';
159 $height = isset( $image_size[1] ) ? $image_size[1] : '300';
160 $crop = isset( $image_size[2] ) ? $image_size[2] : 1;
161
162 $size = array(
163 'width' => $width,
164 'height' => $height,
165 'crop' => $crop
166 );
167
168 $image_size = $width . '_' . $height;
169 } else {
170 $size = array(
171 'width' => '300',
172 'height' => '300',
173 'crop' => 1
174 );
175 }
176
177 return $size;
178 }
179
180 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_custom_departments; the established callable name is part of the plugin/extension API and must remain stable.
181 function ph_get_custom_departments( $active_only = true )
182 {
183 $return = array();
184
185 $custom_departments = get_option( 'propertyhive_custom_departments', array() );
186
187 if ( is_array($custom_departments) && !empty($custom_departments) )
188 {
189 foreach ( $custom_departments as $key => $custom_department )
190 {
191 if ( !$active_only || ( $active_only && get_option('propertyhive_active_departments_' . $key) == 'yes' ) )
192 {
193 $return[$key] = $custom_department;
194 }
195 }
196 }
197
198 return $return;
199 }
200
201 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_custom_department_based_on; the established callable name is part of the plugin/extension API and must remain stable.
202 function ph_get_custom_department_based_on( $department )
203 {
204 $custom_departments = get_option( 'propertyhive_custom_departments', array() );
205
206 if ( isset($custom_departments[$department]['based_on']) )
207 {
208 return $custom_departments[$department]['based_on'];
209 }
210
211 return false;
212 }
213
214 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_departments; the established callable name is part of the plugin/extension API and must remain stable.
215 function ph_get_departments( $raw = false )
216 {
217 $departments = array(
218 'residential-sales' => __( 'Residential Sales', 'propertyhive' ),
219 'residential-lettings' => __( 'Residential Lettings', 'propertyhive' ),
220 'commercial' => __( 'Commercial', 'propertyhive' ),
221 );
222
223 return $raw ? $departments : apply_filters( 'propertyhive_departments', $departments );
224 }
225
226 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_viewing_statuses; the established callable name is part of the plugin/extension API and must remain stable.
227 function ph_get_viewing_statuses()
228 {
229 $viewing_statuses = array(
230 'pending' => __( 'Pending', 'propertyhive' ),
231 'confirmed' => '- ' . __( 'Confirmed', 'propertyhive' ),
232 'unconfirmed' => '- ' . __( 'Awaiting Confirmation', 'propertyhive' ),
233 'carried_out' => __( 'Carried Out', 'propertyhive' ),
234 'awaiting_feedback' => '- ' . __( 'Awaiting Feedback', 'propertyhive' ),
235 'feedback_passed_on' => '- ' . __( 'Feedback Passed On', 'propertyhive' ),
236 'feedback_not_passed_on' => '- ' . __( 'Feedback Not Passed On', 'propertyhive' ),
237 'cancelled' => __( 'Cancelled', 'propertyhive' ),
238 'no_show' => __( 'No Show', 'propertyhive' ),
239 );
240
241 return $viewing_statuses;
242 }
243
244 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper add_viewing_status_meta_query; the established callable name is part of the plugin/extension API and must remain stable.
245 function add_viewing_status_meta_query( $meta_query, $selected_status )
246 {
247 switch ( $selected_status )
248 {
249 case "confirmed":
250 {
251 $meta_query[] = array(
252 'key' => '_status',
253 'value' => 'pending',
254 );
255 $meta_query[] = array(
256 'key' => '_all_confirmed',
257 'value' => 'yes',
258 );
259 break;
260 }
261 case "unconfirmed":
262 {
263 $meta_query[] = array(
264 'key' => '_status',
265 'value' => 'pending',
266 );
267 $meta_query[] = array(
268 'relation' => 'OR',
269 array(
270 'key' => '_all_confirmed',
271 'value' => '',
272 ),
273 array(
274 'key' => '_all_confirmed',
275 'compare' => 'NOT EXISTS',
276 )
277 );
278 break;
279 }
280 case "awaiting_feedback":
281 {
282 $meta_query[] = array(
283 'key' => '_status',
284 'value' => 'carried_out',
285 );
286 $meta_query[] = array(
287 'key' => '_feedback_status',
288 'value' => '',
289 );
290 break;
291 }
292 case "feedback_passed_on":
293 {
294 $meta_query[] = array(
295 'key' => '_status',
296 'value' => 'carried_out',
297 );
298 $meta_query[] = array(
299 'key' => '_feedback_status',
300 'value' => array('interested', 'not_interested'),
301 'compare' => 'IN'
302 );
303 $meta_query[] = array(
304 'key' => '_feedback_passed_on',
305 'value' => 'yes',
306 );
307 break;
308 }
309 case "feedback_not_passed_on":
310 {
311 $meta_query[] = array(
312 'key' => '_status',
313 'value' => 'carried_out',
314 );
315 $meta_query[] = array(
316 'key' => '_feedback_status',
317 'value' => array('interested', 'not_interested'),
318 'compare' => 'IN'
319 );
320 $meta_query[] = array(
321 'key' => '_feedback_passed_on',
322 'value' => '',
323 );
324 break;
325 }
326 default:
327 {
328 $meta_query[] = array(
329 'key' => '_status',
330 'value' => sanitize_text_field( $selected_status ),
331 );
332 }
333 }
334 return $meta_query;
335 }
336
337 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_offer_statuses; the established callable name is part of the plugin/extension API and must remain stable.
338 function ph_get_offer_statuses()
339 {
340 $offer_statuses = array(
341 'pending' => __( 'Pending', 'propertyhive' ),
342 'accepted' => __( 'Accepted', 'propertyhive' ),
343 'declined' => __( 'Declined', 'propertyhive' ),
344 );
345
346 return $offer_statuses;
347 }
348
349 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_sale_statuses; the established callable name is part of the plugin/extension API and must remain stable.
350 function ph_get_sale_statuses()
351 {
352 $sale_statuses = array(
353 'current' => __( 'Current', 'propertyhive' ),
354 'exchanged' => __( 'Exchanged', 'propertyhive' ),
355 'completed' => __( 'Completed', 'propertyhive' ),
356 'fallen_through' => __( 'Fallen Through', 'propertyhive' ),
357 );
358
359 return $sale_statuses;
360 }
361
362 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_get_enquiry_statuses; the established callable name is part of the plugin/extension API and must remain stable.
363 function ph_get_enquiry_statuses()
364 {
365 $enquiry_statuses = array(
366 'open' => __( 'Open', 'propertyhive' ),
367 'closed' => __( 'Closed', 'propertyhive' ),
368 );
369
370 return $enquiry_statuses;
371 }
372
373 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper get_area_units; the established callable name is part of the plugin/extension API and must remain stable.
374 function get_area_units()
375 {
376 $size_options = array(
377 'sqft' => __( 'Sq Ft', 'propertyhive' ),
378 'sqm' => __( 'Sq M', 'propertyhive' ),
379 'acre' => __( 'Acres', 'propertyhive' ),
380 'hectare' => __( 'Hectares', 'propertyhive' ),
381 );
382
383 // $size_options = apply_filters( 'propertyhive_commercial_size_units', $size_options ).
384 // Above filter not in use as we need a way to add the conversion rate to sqft also
385 // If it's a commonly used unit we could just add it for everyones benefit
386
387 return $size_options;
388 }
389
390 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper convert_size_to_sqft; the established callable name is part of the plugin/extension API and must remain stable.
391 function convert_size_to_sqft( $size, $unit = 'sqft' )
392 {
393 $size_sqft = $size;
394
395 if ( $size_sqft != '' )
396 {
397 switch ( $unit )
398 {
399 case "sqm": { $size_sqft = $size * 10.7639; break; }
400 case "acre": { $size_sqft = $size * 43560; break; }
401 case "hectare": { $size_sqft = $size * 107639; break; }
402 }
403 }
404 return $size_sqft;
405 }
406
407 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper get_commercial_price_units; the established callable name is part of the plugin/extension API and must remain stable.
408 function get_commercial_price_units( )
409 {
410 $price_options = array(
411 'psqft' => __( 'Per Sq Ft', 'propertyhive' ),
412 'psqm' => __( 'Per Sq M', 'propertyhive' ),
413 'pacre' => __( 'Per Acre', 'propertyhive' ),
414 'phectare' => __( 'Per Hectare', 'propertyhive' ),
415 );
416
417 return $price_options;
418 }
419
420 /**
421 * Get ordinal suffix (st, nd, rd etc) for any number
422 *
423 * @param int $number
424 * @param bool $return_number Include $n in the string returned
425 * @return string $number including its ordinal suffix
426 */
427 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Legacy public global helper ph_ordinal_suffix; the established callable name is part of the plugin/extension API and must remain stable.
428 function ph_ordinal_suffix( $number, $return_words = true, $return_number = true )
429 {
430 $n_last = $number % 100;
431 if ( ($n_last > 10 && $n_last << 14) || $number == 0 )
432 {
433 $suffix = 'th';
434 $number_in_words = substr($number, -1) . 'th';
435 }
436 else
437 {
438 switch( substr($number, -1) )
439 {
440 case '1':
441 $suffix = 'st';
442 $number_in_words = 'First';
443 break;
444 case '2':
445 $suffix = 'nd';
446 $number_in_words = 'Second';
447 break;
448 case '3':
449 $suffix = 'rd';
450 $number_in_words = 'Third';
451 break;
452 case '4':
453 $suffix = 'th';
454 $number_in_words = 'Fourth';
455 break;
456 case '5':
457 $suffix = 'th';
458 $number_in_words = 'Fifth';
459 break;
460 default:
461 $suffix = 'th';
462 $number_in_words = substr($number, -1) . 'th';
463 break;
464 }
465 }
466 return $return_words ? $number_in_words : ( $return_number ? $number . $suffix : $suffix );
467 }
468
469 /**
470 * Save an ordered property media list without modifying unauthorized attachments.
471 * The caller verifies the property form nonce before invoking this helper.
472 *
473 * @param int $post_id Property ID.
474 * @param string $meta_key Media list key.
475 * @param string $submitted_ids Comma-separated attachment IDs.
476 * @return bool Whether the list was saved.
477 */
478 function propertyhive_save_media_attachment_list( $post_id, $meta_key, $submitted_ids ) {
479 if ( ! current_user_can( 'manage_propertyhive' ) || ! current_user_can( 'edit_post', $post_id ) || 'property' !== get_post_type( $post_id ) ) {
480 return false;
481 }
482 if ( ! in_array( $meta_key, array( '_photos', '_floorplans', '_brochures', '_epcs' ), true ) || ! is_string( $submitted_ids ) || ! preg_match( '/^[0-9,\s]*$/D', $submitted_ids ) ) {
483 return false;
484 }
485 $ids = array_values( array_unique( array_filter( array_map( 'absint', explode( ',', $submitted_ids ) ) ) ) );
486 $previous_ids = get_post_meta( $post_id, $meta_key, true );
487 $previous_ids = is_array( $previous_ids ) ? array_map( 'absint', $previous_ids ) : array();
488
489 foreach ( $ids as $index => $attachment_id ) {
490 if ( 'attachment' !== get_post_type( $attachment_id ) ) {
491 unset( $ids[$index] );
492 continue;
493 }
494
495 if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
496 return false;
497 }
498 }
499
500 $ids = array_values( $ids );
501
502 foreach ( $ids as $attachment_id ) {
503 wp_update_post( array( 'ID' => $attachment_id, 'post_parent' => $post_id ) );
504 clean_attachment_cache( $attachment_id );
505 }
506 update_post_meta( $post_id, $meta_key, $ids );
507 foreach ( array_diff( $previous_ids, $ids ) as $attachment_id ) {
508 if ( 'attachment' === get_post_type( $attachment_id ) && (int) get_post_field( 'post_parent', $attachment_id ) === (int) $post_id && current_user_can( 'edit_post', $attachment_id ) ) {
509 wp_update_post( array( 'ID' => $attachment_id, 'post_parent' => 0 ) );
510 clean_attachment_cache( $attachment_id );
511 }
512 }
513 return true;
514 }
515
516 /**
517 * Determine public visibility on all supported WordPress versions.
518 *
519 * @param int|WP_Post $post Post to inspect.
520 * @return bool Whether anonymous visitors may view it.
521 */
522 function propertyhive_is_post_publicly_viewable( $post ) {
523 if ( function_exists( 'is_post_publicly_viewable' ) ) {
524 return is_post_publicly_viewable( $post );
525 }
526 $post = get_post( $post );
527 if ( ! $post || ! is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) {
528 return false;
529 }
530 $status = get_post_status_object( $post->post_status );
531 return $status && ! empty( $status->public );
532 }
533