PluginProbe
Property Hive / 2.2.4
Property Hive v2.2.4
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-query.php

class-ph-query.php in Property Hive 2.2.4, at includes/class-ph-query.php

2,523 lines 80.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Contains the query functions for PropertyHive which alter the front-end post queries and loops.
4 *
5 * @class PH_Query
6 * @version 1.0.0
7 * @package PropertyHive/Classes
8 * @category Class
9 * @author PropertyHive
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
14 if ( ! class_exists( 'PH_Query' ) ) :
15
16 /**
17 * PH_Query Class
18 */
19 class PH_Query {
20
21 /** @public array Query vars to add to wp */
22 public $query_vars = array();
23
24 /** @public array Unfiltered property ids (before layered nav etc) */
25 public $unfiltered_property_ids = array();
26
27 /** @public array Filtered property ids (after layered nav) */
28 public $filtered_property_ids = array();
29
30 /** @public array Filtered property ids (after layered nav, per taxonomy) */
31 public $filtered_property_ids_for_taxonomy = array();
32
33 /** @public array property IDs that match the layered nav + price filter */
34 public $post__in = array();
35
36 /** @public array The meta query for the page */
37 public $meta_query = '';
38
39 /** @public array The tax query for the page */
40 public $tax_query = '';
41
42 /** @public array Post IDs matching layered nav only */
43 public $layered_nav_post__in = array();
44
45 /** @public array Stores post IDs matching layered nav, so price filter can find max price in view */
46 public $layered_nav_property_ids = array();
47
48 /** @public array Stores post IDs matching layered nav, so price filter can find max price in view */
49 public $address_keyword_polygon_points = array();
50
51 /**
52 * Constructor for the query class. Hooks in methods.
53 *
54 * @access public
55 */
56 public function __construct() {
57
58 //add_action( 'init', array( $this, 'add_endpoints' ) );
59 add_action( 'init', array( $this, 'layered_nav_init' ) );
60 add_action( 'init', array( $this, 'price_filter_init' ) );
61
62 if ( ! is_admin() ) {
63 add_action( 'init', array( $this, 'get_errors' ) );
64 add_filter( 'query_vars', array( $this, 'add_query_vars'), 0 );
65 add_action( 'parse_request', array( $this, 'parse_request'), 0 );
66 add_filter( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
67 add_filter( 'the_posts', array( $this, 'the_posts' ), 11, 2 );
68 add_action( 'wp', array( $this, 'remove_property_query' ) );
69 add_action( 'wp', array( $this, 'remove_ordering_args' ) );
70 add_filter( 'posts_where', array( $this, 'commercial_display_where' ), 10, 2 );
71 add_filter( 'posts_where', array( $this, 'keyword_excerpt_where' ), 10, 2 );
72 add_action( 'pre_get_posts', array( $this, 'custom_order_properties_by_availability' ), 10, 2 );
73 }
74
75 $this->init_query_vars();
76 }
77
78 public function custom_order_properties_by_availability($query)
79 {
80 if ( is_admin() )
81 {
82 return;
83 }
84
85 if ( !$query->is_main_query() )
86 {
87 return;
88 }
89
90 if ( !is_post_type_archive('property') )
91 {
92 return;
93 }
94
95 if ( apply_filters( 'propertyhive_order_by_availability', false ) === false )
96 {
97 return;
98 }
99
100 $availability_order = get_option('propertyhive_taxonomy_terms_order_availability', array());
101
102 if ( empty($availability_order) )
103 {
104 return;
105 }
106
107 // Sanitize and prepare the order
108 $availability_order = explode("|", $availability_order);
109 $availability_order = array_map('intval', $availability_order);
110
111 // Modify the main query to join with term relationships and term taxonomy tables using custom aliases
112 add_filter('posts_join', function ($join, $query)
113 {
114 global $wpdb;
115
116 if ($query->is_main_query() && is_post_type_archive('property'))
117 {
118 $join .= " LEFT JOIN {$wpdb->term_relationships} AS avstr ON ({$wpdb->posts}.ID = avstr.object_id) ";
119 $join .= " LEFT JOIN {$wpdb->term_taxonomy} AS avstt ON (avstr.term_taxonomy_id = avstt.term_taxonomy_id) ";
120 }
121
122 return $join;
123 }, 10, 2);
124
125 // Add a custom ordering clause
126 add_filter('posts_orderby', function ($orderby, $query) use ($availability_order)
127 {
128 global $wpdb;
129
130 if ($query->is_main_query() && is_post_type_archive('property')) {
131 // Retrieve the original orderby clause
132 $original_orderby = $orderby ? $orderby : "{$wpdb->posts}.post_date DESC";
133
134 // Construct the custom order by clause
135 $order_by_custom = "FIELD(avstt.term_id, " . implode(',', $availability_order) . ")";
136
137 // Combine the custom order by with the original order by
138 $orderby_combined = "$order_by_custom, $original_orderby";
139
140 return $orderby_combined;
141 }
142
143 return $orderby;
144 }, 10, 2);
145 }
146
147 public function keyword_excerpt_where( $where, $query )
148 {
149 if ( ( is_array($query->get('post_type')) && in_array('property', $query->get('post_type')) ) || ( !is_array($query->get('post_type')) && $query->get('post_type') == 'property' ) )
150 {
151 global $wpdb;
152
153 if ( isset($_REQUEST['keyword']) && ph_clean($_REQUEST['keyword']) != '' )
154 {
155 $ref_pos = strpos($where, '_features_concatenated');
156 if ( $ref_pos !== FALSE )
157 {
158 $str_to_insert = " $wpdb->posts.post_excerpt LIKE '%" . esc_sql(ph_clean($_REQUEST['keyword'])) . "%' OR ";
159 $where = substr_replace($where, $str_to_insert, $ref_pos - 18, 0);
160 }
161 }
162 }
163
164 return $where;
165 }
166
167 public function commercial_display_where( $where, $query )
168 {
169 if ( $query->get('post_type') == 'property' )
170 {
171 global $wpdb;
172
173 $commercial_display = get_option( 'propertyhive_commercial_display', '' );
174
175 switch ( $commercial_display )
176 {
177 case "top_level_only":
178 {
179 $where .= " AND $wpdb->posts.post_parent=0 ";
180 break;
181 }
182 case "top_level_only_but_units_when_filtered":
183 {
184 $unit_filter_parameters = apply_filters( 'propertyhive_unit_filter_parameters', array( 'minimum_floor_area', 'maximum_floor_area' ) );
185 $unit_filter_parameter_found = false;
186 foreach ( $unit_filter_parameters as $parameter )
187 {
188 if ( isset($_REQUEST[$parameter]) && ph_clean($_REQUEST[$parameter]) != '' )
189 {
190 $unit_filter_parameter_found = true;
191 }
192 }
193 if ( !$unit_filter_parameter_found )
194 {
195 $where .= " AND $wpdb->posts.post_parent=0 ";
196 }
197 break;
198 }
199 default:
200 {
201 // do nothing
202 }
203 }
204 }
205
206 return $where;
207 }
208
209 /**
210 * Init query vars by loading options.
211 */
212 public function init_query_vars() {
213 // Query vars to add to WP
214 $this->query_vars = array(
215
216 );
217 }
218
219 /**
220 * Get any errors from querystring
221 */
222 public function get_errors() {
223 if ( ! empty( $_GET['ph_error'] ) && ( $error = sanitize_text_field( $_GET['ph_error'] ) ) && ! ph_has_notice( $error, 'error' ) )
224 ph_add_notice( $error, 'error' );
225 }
226
227 /**
228 * Add endpoints for query vars
229 */
230 public function add_endpoints() {
231 foreach ( $this->query_vars as $key => $var )
232 add_rewrite_endpoint( $var, EP_PAGES );
233 }
234
235 /**
236 * add_query_vars function.
237 *
238 * @access public
239 * @param array $vars
240 * @return array
241 */
242 public function add_query_vars( $vars ) {
243 foreach ( $this->query_vars as $key => $var )
244 $vars[] = $key;
245
246 return $vars;
247 }
248
249 /**
250 * Get query vars
251 * @return array()
252 */
253 public function get_query_vars() {
254 return $this->query_vars;
255 }
256
257 /**
258 * Parse the request and look for query vars - endpoints may not be supported
259 */
260 public function parse_request() {
261 global $wp;
262
263 // Map query vars to their keys, or get them if endpoints are not supported
264 foreach ( $this->query_vars as $key => $var ) {
265 if ( isset( $_GET[ $var ] ) ) {
266 $wp->query_vars[ $key ] = sanitize_text_field( wp_unslash( $_GET[ $var ] ) );
267 }
268
269 elseif ( isset( $wp->query_vars[ $var ] ) ) {
270 $wp->query_vars[ $key ] = $wp->query_vars[ $var ];
271 }
272 }
273 }
274
275 /**
276 * Hook into pre_get_posts to do the main property query
277 *
278 * @access public
279 * @param mixed $q query object
280 * @return void
281 */
282 public function pre_get_posts( $q ) {
283 // We only want to affect the main query
284 if ( ! $q->is_main_query() )
285 return;
286
287 // Fix for verbose page rules
288 if ( $GLOBALS['wp_rewrite']->use_verbose_page_rules && isset( $q->queried_object->ID ) && $q->queried_object->ID == ph_get_page_id( 'search_results' ) ) {
289 $q->set( 'post_type', 'property' );
290 $q->set( 'page', '' );
291 $q->set( 'pagename', '' );
292
293 // Fix conditional Functions
294 $q->is_archive = true;
295 $q->is_post_type_archive = true;
296 $q->is_singular = false;
297 $q->is_page = false;
298 }
299
300 // When orderby is set, WordPress shows posts. Get around that here.
301 if ( ($q->is_home() || $q->get( 'page_id' ) == get_option('page_on_front')) && 'page' == get_option('show_on_front') && get_option('page_on_front') == ph_get_page_id('search_results') )
302 {
303 $_query = wp_parse_args( $q->query );
304 if ( empty( $_query ) || ! array_diff( array_keys( $_query ), array( 'preview', 'page', 'paged', 'cpage', 'orderby' ) ) )
305 {
306
307 $q->is_page = true;
308 $q->is_home = false;
309 $q->set( 'page_id', (int) get_option('page_on_front') );
310 $q->set( 'post_type', 'property' );
311 }
312 }
313
314 // Special check for sites with the property search results on front page
315 if ( $q->is_page() && 'page' == get_option( 'show_on_front' ) && $q->get('page_id') == ph_get_page_id('search_results') ) {
316
317 // This is a front-page property listings
318 $q->set( 'post_type', 'property' );
319 $q->set( 'page_id', '' );
320 if ( isset( $q->query['paged'] ) )
321 $q->set( 'paged', $q->query['paged'] );
322
323 // Define a variable so we know this is the front page search results later on
324 define( 'SEARCH_RESULTS_IS_ON_FRONT', true );
325
326 // Get the actual WP page to avoid errors and let us use is_front_page()
327 // This is hacky but works. Awaiting http://core.trac.wordpress.org/ticket/21096
328 global $wp_post_types;
329
330 $search_results_page = get_post( ph_get_page_id('search_results') );
331 $q->is_page = true;
332
333 $wp_post_types['property']->ID = $search_results_page->ID;
334 $wp_post_types['property']->post_title = $search_results_page->post_title;
335 $wp_post_types['property']->post_name = $search_results_page->post_name;
336 $wp_post_types['property']->post_type = $search_results_page->post_type;
337 $wp_post_types['property']->ancestors = get_ancestors( $search_results_page->ID, $search_results_page->post_type );
338
339 // Fix conditional Functions like is_front_page
340 $q->is_singular = false;
341 $q->is_post_type_archive = true;
342 $q->is_archive = true;
343
344 // Fix WP SEO
345 if ( class_exists( 'WPSEO_Meta' ) ) {
346 add_filter( 'wpseo_metadesc', array( $this, 'wpseo_metadesc' ) );
347 add_filter( 'wpseo_metakey', array( $this, 'wpseo_metakey' ) );
348 }
349
350 } else {
351
352 // Only apply to property categories, the property post archive, the search results page, and property attribute taxonomies
353 if ( ! $q->is_post_type_archive( 'property' ) && ! $q->is_tax( get_object_taxonomies( 'property' ) ) )
354 return;
355
356 }
357
358 $this->property_query( $q );
359
360 if ( is_search() )
361 {
362 add_filter( 'posts_where', array( $this, 'search_post_excerpt' ) );
363 add_filter( 'wp', array( $this, 'remove_posts_where' ) );
364 }
365
366 add_filter( 'posts_where', array( $this, 'exclude_protected_properties' ) );
367
368 // We're on a property search page so queue the propertyhive_get_properties_in_view function
369 //add_action( 'wp', array( $this, 'get_properties_in_view' ), 2);
370
371 // And remove the pre_get_posts hook
372 $this->remove_property_query();
373 }
374
375 /**
376 * search_post_excerpt function.
377 *
378 * @access public
379 * @param string $where (default: '')
380 * @return string (modified where clause)
381 */
382 public function search_post_excerpt( $where = '' ) {
383 /*global $wp_the_query;
384
385 // If this is not a PH Query, do not modify the query
386 if ( empty( $wp_the_query->query_vars['ph_query'] ) || empty( $wp_the_query->query_vars['s'] ) )
387 return $where;
388
389 $where = preg_replace(
390 "/post_title\s+LIKE\s*(\'\%[^\%]+\%\')/",
391 "post_title LIKE $1) OR (post_excerpt LIKE $1", $where );*/
392
393 return $where;
394 }
395
396 /**
397 * Prevent password protected properties appearing in the loops
398 *
399 * @param string $where
400 * @return string
401 */
402 public function exclude_protected_properties( $where ) {
403 global $wpdb;
404 $where .= " AND {$wpdb->posts}.post_password = ''";
405 return $where;
406 }
407
408 /**
409 * wpseo_metadesc function.
410 * Hooked into wpseo_ hook already, so no need for function_exist
411 *
412 * @access public
413 * @return string
414 */
415 public function wpseo_metadesc() {
416 return WPSEO_Meta::get_value( 'metadesc', ph_get_page_id('search_results') );
417 }
418
419
420 /**
421 * wpseo_metakey function.
422 * Hooked into wpseo_ hook already, so no need for function_exist
423 *
424 * @access public
425 * @return string
426 */
427 public function wpseo_metakey() {
428 return WPSEO_Meta::get_value( 'metakey', ph_get_page_id('search_results') );
429 }
430
431
432 /**
433 * Hook into the_posts to do the main property query if needed - relevanssi compatibility
434 *
435 * @access public
436 * @param array $posts
437 * @param WP_Query|bool $query (default: false)
438 * @return array
439 */
440 public function the_posts( $posts, $query = false ) {
441
442 // Abort if there's no query
443 if ( ! $query )
444 return $posts;
445
446 // Abort if we're not filtering posts
447 if ( empty( $this->post__in ) )
448 return $posts;
449
450 // Abort if this query has already been done
451 if ( ! empty( $query->ph_query ) )
452 return $posts;
453
454 // Abort if this isn't a search query
455 if ( empty( $query->query_vars["s"] ) )
456 return $posts;
457
458 // Abort if we're not on a post type archive/property taxonomy
459 if ( ! $query->is_post_type_archive( 'property' ) && ! $query->is_tax( get_object_taxonomies( 'property' ) ) )
460 return $posts;
461
462 $filtered_posts = array();
463 $queried_post_ids = array();
464
465 foreach ( $posts as $post ) {
466 if ( in_array( $post->ID, $this->post__in ) ) {
467 $filtered_posts[] = $post;
468 $queried_post_ids[] = $post->ID;
469 }
470 }
471
472 $query->posts = $filtered_posts;
473 $query->post_count = count( $filtered_posts );
474
475 // Ensure filters are set
476 $this->unfiltered_property_ids = $queried_post_ids;
477 $this->filtered_property_ids = $queried_post_ids;
478
479 if ( sizeof( $this->layered_nav_post__in ) > 0 ) {
480 $this->layered_nav_property_ids = array_intersect( $this->unfiltered_property_ids, $this->layered_nav_post__in );
481 } else {
482 $this->layered_nav_property_ids = $this->unfiltered_property_ids;
483 }
484
485 return $filtered_posts;
486 }
487
488
489 /**
490 * Query the properties, applying sorting/ordering etc. This applies to the main wordpress loop
491 *
492 * @access public
493 * @param mixed $q
494 * @return void
495 */
496 public function property_query( $q ) {
497
498 // Meta query
499 $meta_query = $this->get_meta_query( $q );
500
501 // Tax query
502 $tax_query = $this->get_tax_query( $q->get( 'tax_query' ) );
503
504 // Date query
505 $date_query = $this->get_date_query();
506
507 // Ordering
508 $ordering = $this->get_search_results_ordering_args();
509
510 // Get a list of post id's which match the current filters set (in the layered nav and price filter)
511 $post__in = array();
512 //$post__in = array_unique( apply_filters( 'loop_shop_post_in', array() ) );
513
514 // Ordering query vars
515 $q->set( 'orderby', $ordering['orderby'] . ' post_title' );
516 $q->set( 'order', $ordering['order'] );
517 if ( isset( $ordering['meta_key'] ) )
518 $q->set( 'meta_key', $ordering['meta_key'] );
519
520 // Query vars that affect posts shown
521 $q->set( 'meta_query', $meta_query );
522 $q->set( 'tax_query', $tax_query );
523 $q->set( 'date_query', $date_query );
524 $q->set( 'post__in', $post__in );
525 $q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_search_results_per_page', get_option( 'posts_per_page' ) ) );
526
527 // Set a special variable
528 $q->set( 'ph_query', true );
529
530 // Store variables
531 $this->post__in = $post__in;
532 $this->meta_query = $meta_query;
533 $this->tax_query = $tax_query;
534
535 do_action( 'propertyhive_property_query', $q, $this );
536 }
537
538
539 /**
540 * Remove the query
541 *
542 * @access public
543 * @return void
544 */
545 public function remove_property_query() {
546 remove_filter( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
547 }
548
549 /**
550 * Remove ordering queries
551 */
552 public function remove_ordering_args() {
553
554 }
555
556 /**
557 * Remove the posts_where filter
558 *
559 * @access public
560 * @return void
561 */
562 public function remove_posts_where() {
563 remove_filter( 'posts_where', array( $this, 'search_post_excerpt' ) );
564 }
565
566
567 /**
568 * Get an unpaginated list all property ID's (both filtered and unfiltered). Makes use of transients.
569 *
570 * @access public
571 * @return void
572 */
573 public function get_properties_in_view() {
574 global $wp_the_query;
575
576 $unfiltered_property_ids = array();
577
578 // Get main query
579 $current_wp_query = $wp_the_query->query;
580
581 // Get WP Query for current page (without 'paged')
582 unset( $current_wp_query['paged'] );
583
584 // Generate a transient name based on current query
585 $transient_name = 'ph_uf_pid_' . md5( http_build_query( $current_wp_query ) );
586 $transient_name = ( is_search() ) ? $transient_name . '_s' : $transient_name;
587
588 if ( false === ( $unfiltered_property_ids = get_transient( $transient_name ) ) ) {
589
590 // Get all visible posts, regardless of filters
591 $unfiltered_property_ids = get_posts(
592 array_merge(
593 $current_wp_query,
594 array(
595 'post_type' => 'property',
596 'numberposts' => -1,
597 'post_status' => 'publish',
598 'meta_query' => $this->meta_query,
599 'fields' => 'ids',
600 'no_found_rows' => true,
601 'update_post_meta_cache' => false,
602 'update_post_term_cache' => false
603 )
604 )
605 );
606
607 set_transient( $transient_name, $unfiltered_property_ids, YEAR_IN_SECONDS );
608 }
609
610 // Store the variable
611 $this->unfiltered_property_ids = $unfiltered_property_ids;
612
613 // Also store filtered posts ids...
614 if ( sizeof( $this->post__in ) > 0 )
615 $this->filtered_property_ids = array_intersect( $this->unfiltered_property_ids, $this->post__in );
616 else
617 $this->filtered_property_ids = $this->unfiltered_property_ids;
618
619 // And filtered post ids which just take layered nav into consideration (to find max price in the price widget)
620 if ( sizeof( $this->layered_nav_post__in ) > 0 )
621 $this->layered_nav_property_ids = array_intersect( $this->unfiltered_property_ids, $this->layered_nav_post__in );
622 else
623 $this->layered_nav_property_ids = $this->unfiltered_property_ids;
624 }
625
626
627 /**
628 * Returns an array of arguments for ordering properties based on the selected values
629 *
630 * @access public
631 * @return array
632 */
633 public function get_search_results_ordering_args( $orderby = '', $order = '' ) {
634 // Get ordering from query string unless defined
635 if ( ! $orderby ) {
636 $orderby_value = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : apply_filters( 'propertyhive_default_search_results_orderby', get_option( 'propertyhive_default_search_results_orderby' ) );
637
638 // Get order + orderby args from string
639 $orderby_value = explode( '-', $orderby_value );
640 $orderby = esc_attr( $orderby_value[0] );
641 $order = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order;
642 }
643
644 $orderby = strtolower( $orderby );
645 $order = strtoupper( $order );
646
647 $args = array();
648
649 // default - menu_order
650 if (
651 ( isset($_REQUEST['department']) && $_REQUEST['department'] != 'commercial' && ph_get_custom_department_based_on($_REQUEST['department']) != 'commercial' ) ||
652 ( !isset($_REQUEST['department']) && get_option( 'propertyhive_primary_department' ) != 'commercial' && ph_get_custom_department_based_on(get_option( 'propertyhive_primary_department' )) != 'commercial' )
653 )
654 {
655 $args['orderby'] = 'meta_value_num';
656 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
657 $args['meta_key'] = '_price_actual';
658 }
659 elseif (
660 ( isset($_REQUEST['department']) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) ) ||
661 ( !isset($_REQUEST['department']) && ( get_option( 'propertyhive_primary_department' ) == 'commercial' || ph_get_custom_department_based_on(get_option( 'propertyhive_primary_department' )) == 'commercial' ) )
662 )
663 {
664 $args['orderby'] = 'meta_value_num';
665 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
666 $args['meta_key'] = '_floor_area_from_sqft';
667 }
668
669 switch ( $orderby ) {
670 case 'price' :
671 $args['orderby'] = 'meta_value_num';
672 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
673 if (
674 ( isset($_REQUEST['department']) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) ) ||
675 ( !isset($_REQUEST['department']) && ( get_option( 'propertyhive_primary_department' ) == 'commercial' || ph_get_custom_department_based_on(get_option( 'propertyhive_primary_department' )) == 'commercial' ) )
676 )
677 {
678 $args['meta_key'] = '_price_from_actual';
679 }
680 else
681 {
682 $args['meta_key'] = '_price_actual';
683 }
684 break;
685 case 'floor_area' :
686 $args['orderby'] = 'meta_value_num';
687 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
688 $args['meta_key'] = '_floor_area_from_sqft';
689 break;
690 case 'date' :
691 $args['orderby'] = 'meta_value';
692 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
693 $args['meta_key'] = '_on_market_change_date';
694 break;
695 default :
696 {
697 if ( $orderby != '' )
698 {
699 $args['orderby'] = $orderby;
700 $args['order'] = $order == 'ASC' ? 'ASC' : 'DESC';
701 }
702 }
703 }
704
705 return apply_filters( 'propertyhive_get_search_results_ordering_args', $args );
706 }
707
708 /**
709 * Appends date queries to an array.
710 * @access public
711 * @param array $meta_query
712 * @return array
713 */
714 public function get_date_query() {
715
716 $date_query = array();
717
718 if ( isset( $_REQUEST['added_from'] ) && $_REQUEST['added_from'] != '' )
719 {
720 $date_query = array(
721 'column' => 'post_date_gmt',
722 'after' => sanitize_text_field( $_REQUEST['added_from'] )
723 );
724 }
725
726 if ( isset( $_REQUEST['added_from_hours'] ) && $_REQUEST['added_from_hours'] != '' )
727 {
728 $date_query = array(
729 'column' => 'post_date_gmt',
730 'after' => sanitize_text_field( $_REQUEST['added_from_hours'] ) . ' hours ago'
731 );
732 }
733
734 return array_filter( $date_query );
735 }
736
737 /**
738 * Appends meta queries to an array.
739 * @access public
740 * @param array $meta_query
741 * @return array
742 */
743 public function get_meta_query( $q = array() ) {
744
745 $meta_query = array();
746 if ( !empty($q) )
747 {
748 $meta_query = $q->get( 'meta_query' );
749 }
750
751 if ( ! is_array( $meta_query ) )
752 $meta_query = array();
753
754 $meta_query[] = $this->on_market_meta_query();
755 $meta_query[] = $this->department_meta_query($q);
756 $meta_query[] = $this->featured_meta_query();
757 $meta_query[] = $this->date_added_meta_query();
758 $meta_query[] = $this->address_keyword_meta_query();
759 $meta_query[] = $this->country_meta_query();
760 $meta_query[] = $this->minimum_price_meta_query();
761 $meta_query[] = $this->maximum_price_meta_query();
762 $meta_query[] = $this->price_range_meta_query();
763 $meta_query[] = $this->minimum_rent_meta_query();
764 $meta_query[] = $this->maximum_rent_meta_query();
765 $meta_query[] = $this->rent_range_meta_query();
766 $meta_query[] = $this->bedrooms_meta_query();
767 $meta_query[] = $this->minimum_bedrooms_meta_query();
768 $meta_query[] = $this->maximum_bedrooms_meta_query();
769 $meta_query[] = $this->minimum_bathrooms_meta_query();
770 $meta_query[] = $this->maximum_bathrooms_meta_query();
771 $meta_query[] = $this->minimum_reception_rooms_meta_query();
772 $meta_query[] = $this->maximum_reception_rooms_meta_query();
773 $meta_query[] = $this->available_date_from_meta_query();
774 $meta_query[] = $this->minimum_floor_area_meta_query();
775 $meta_query[] = $this->maximum_floor_area_meta_query();
776 $meta_query[] = $this->minimum_maximum_floor_area_meta_query();
777 $meta_query[] = $this->floor_area_range_meta_query();
778 $meta_query[] = $this->commercial_for_sale_to_rent_meta_query();
779 $meta_query[] = $this->commercial_for_sale_meta_query();
780 $meta_query[] = $this->commercial_to_rent_meta_query();
781 $meta_query[] = $this->commercial_minimum_price_meta_query();
782 $meta_query[] = $this->commercial_maximum_price_meta_query();
783 $meta_query[] = $this->commercial_minimum_rent_meta_query();
784 $meta_query[] = $this->commercial_maximum_rent_meta_query();
785 $meta_query[] = $this->negotiator_meta_query();
786 $meta_query[] = $this->office_meta_query();
787 $meta_query[] = $this->keyword_meta_query();
788
789 return array_filter( apply_filters( 'propertyhive_property_query_meta_query', $meta_query, $this ) );
790 }
791
792 /**
793 * Returns a meta query to handle property on market status
794 *
795 * @access public
796 * @param string $compare (default: 'IN')
797 * @return array
798 */
799 public function on_market_meta_query( ) {
800
801 $meta_query = array();
802
803 if ( !is_admin() )
804 {
805 $meta_query = array(
806 'key' => '_on_market',
807 'value' => 'yes',
808 'compare' => '='
809 );
810 }
811
812 return $meta_query;
813 }
814
815 /**
816 * Returns a meta query to handle property department
817 *
818 * @access public
819 * @return array
820 */
821 public function department_meta_query( $q ) {
822
823 $meta_query = array();
824
825 if ( isset( $_REQUEST['department'] ) && $_REQUEST['department'] != '' )
826 {
827 $meta_query = array(
828 'key' => '_department',
829 'value' => sanitize_text_field( $_REQUEST['department'] ),
830 'compare' => '='
831 );
832 }
833 else
834 {
835 // Need a department set if on search results page
836 if (!empty($q) && $q->is_post_type_archive( 'property' ))
837 {
838 if (get_option( 'propertyhive_primary_department' ) != '')
839 {
840 $department = get_option( 'propertyhive_primary_department' );
841 }
842 else
843 {
844 // No primary department set. Use first active one. Should never get to this scenario
845 $department = '';
846
847 $departments = ph_get_departments();
848
849 foreach ( $departments as $key => $value )
850 {
851 if ( get_option( 'propertyhive_active_departments_' . str_replace("residential-", "", $key) ) == 'yes' )
852 {
853 if ( $department == '' )
854 {
855 $department = $key;
856 }
857 }
858 }
859 }
860 $meta_query = array(
861 'key' => '_department',
862 'value' => $department,
863 'compare' => '='
864 );
865 }
866 }
867
868 return $meta_query;
869 }
870
871 /**
872 * Returns a meta query to handle featured
873 *
874 * @access public
875 * @return array
876 */
877 public function featured_meta_query( ) {
878
879 $meta_query = array();
880
881 if ( isset( $_REQUEST['featured'] ) && $_REQUEST['featured'] != '' )
882 {
883 $meta_query = array(
884 'key' => '_featured',
885 'value' => 'yes',
886 'compare' => '='
887 );
888 }
889
890 return $meta_query;
891 }
892
893 /**
894 * Returns a meta query to handle date added
895 *
896 * @access public
897 * @return array
898 */
899 public function date_added_meta_query( ) {
900
901 $meta_query = array();
902
903 if ( isset( $_REQUEST['date_added'] ) && $_REQUEST['date_added'] != '' && is_numeric($_REQUEST['date_added']) )
904 {
905 $meta_query = array(
906 'key' => '_on_market_change_date',
907 'value' => date('Y-m-d H:i:s', strtotime('-' . $_REQUEST['date_added'] . ' days')),
908 'compare' => '>=',
909 'type' => 'DATETIME',
910 );
911 }
912
913 return $meta_query;
914 }
915
916 /**
917 * Returns a meta query to handle searching for a keyword in the address
918 *
919 * @access public
920 * @return array
921 */
922 public function address_keyword_meta_query( ) {
923
924 $meta_query = array();
925
926 if ( isset( $_REQUEST['address_keyword'] ) && !empty($_REQUEST['address_keyword']) )
927 {
928 $_REQUEST['address_keyword'] = ph_clean( wp_unslash( $_REQUEST['address_keyword'] ) );
929
930 $do_address_search = true;
931 if ( get_option( 'propertyhive_address_keyword_compare', '=' ) == 'polygon' )
932 {
933 $address_keyword_polygon = new PH_Address_Keyword_Polygon();
934 $polygon_coordinates = $address_keyword_polygon->get_address_keyword_polygon_coordinates( $_REQUEST['address_keyword'] . ', UK' );
935
936 if ( $polygon_coordinates !== FALSE )
937 {
938 $this->address_keyword_polygon_points = $polygon_coordinates;
939 add_filter( 'posts_where' , array( $this, 'where_properties_in_polygon' ), 1, 2 );
940 $do_address_search = false;
941 }
942 }
943
944 if ( $do_address_search )
945 {
946 $address_keywords_to_query = is_array($_REQUEST['address_keyword']) ? $_REQUEST['address_keyword'] : array( $_REQUEST['address_keyword'] );
947
948 $address_fields_to_query = array(
949 '_reference_number',
950 '_address_street',
951 '_address_two',
952 '_address_three',
953 '_address_four',
954 '_address_postcode',
955 '_address_concatenated',
956 );
957
958 $address_keywords = array();
959
960 if ( !empty($address_keywords_to_query) )
961 {
962 foreach ( $address_keywords_to_query as $address_keyword )
963 {
964 // Remove country code from end (i.e. ', UK')
965 $address_keyword = preg_replace('/\,\s?[A-Z][A-Z]$/', '', $address_keyword);
966
967 // Extract postcode and use that if exists
968 $postcode_pattern = '/\b([A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9]?[A-Z]{0,2})\b/i';
969 if ( preg_match($postcode_pattern, $address_keyword, $matches) )
970 {
971 $address_keyword = $matches[1];
972 }
973
974 $address_keyword = trim($address_keyword);
975
976 $address_keywords[] = ph_clean($address_keyword);
977
978 if ( strpos( $address_keyword, ' ' ) !== FALSE )
979 {
980 $address_keywords[] = str_replace(" ", "-", ph_clean($address_keyword));
981 }
982 if ( strpos( $address_keyword, '-' ) !== FALSE )
983 {
984 $address_keywords[] = str_replace("-", " ", ph_clean($address_keyword));
985 }
986 if ( strpos( $address_keyword, '.' ) !== FALSE )
987 {
988 $address_keywords[] = str_replace(".", "", ph_clean($address_keyword));
989 }
990 if ( stripos( $address_keyword, 'st ' ) !== FALSE )
991 {
992 $address_keywords[] = str_ireplace("st ", "st. ", ph_clean($address_keyword));
993 }
994 if ( strpos( $address_keyword, '\'' ) !== FALSE )
995 {
996 $address_keywords[] = str_replace("'", "", ph_clean($address_keyword));
997 }
998 }
999 }
1000
1001 $address_keywords = apply_filters( 'propertyhive_address_keywords_to_query', $address_keywords );
1002
1003 $meta_query = array('relation' => 'OR');
1004
1005 // add country to list of fields to query if it looks like we're working with an overseas site
1006 $countries = get_option( 'propertyhive_countries', array() );
1007 if ( !is_array($countries) ) { $countries = array(); }
1008 if ( count($countries) > 1 )
1009 {
1010 $address_fields_to_query[] = '_address_country';
1011 }
1012
1013 $address_fields_to_query = array_unique($address_fields_to_query);
1014 $address_fields_to_query = apply_filters( 'propertyhive_address_fields_to_query', $address_fields_to_query );
1015
1016 foreach ( $address_keywords as $address_keyword )
1017 {
1018 foreach ( $address_fields_to_query as $address_field )
1019 {
1020 if ( in_array( $address_field, array('_address_postcode', '_address_country', '_address_concatenated') ) ) { continue; } // ignore postcode and country as they're handled differently afterwards
1021
1022 $meta_query[] = array(
1023 'key' => $address_field,
1024 'value' => $address_keyword,
1025 'compare' => get_option( 'propertyhive_address_keyword_compare', '=' )
1026 );
1027 }
1028
1029 if ( in_array('_address_postcode', $address_fields_to_query) )
1030 {
1031 if ( strlen($address_keyword) <= 4 )
1032 {
1033 $meta_query[] = array(
1034 'key' => '_address_postcode',
1035 'value' => ph_clean($address_keyword),
1036 'compare' => '='
1037 );
1038 // Run regex match where given keyword is at the start of the postcode ^
1039 // followed by one or zero letters (for WC2E-style postcodes) [a-zA-Z]?
1040 // then a single space [ ]
1041 $meta_query[] = array(
1042 'key' => '_address_postcode',
1043 'value' => '^' . ph_clean($address_keyword) . '[a-zA-Z]?[ ]',
1044 'compare' => 'RLIKE'
1045 );
1046 }
1047 else
1048 {
1049 $postcode = ph_clean($address_keyword);
1050
1051 if ( preg_match('#^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW])[0-9][ABD-HJLNP-UW-Z]{2})$#i', $postcode) )
1052 {
1053 // UK postcode found with no space
1054
1055 if ( strlen($postcode) == 5 )
1056 {
1057 $first_part = substr($postcode, 0, 2);
1058 $last_part = substr($postcode, 2, 3);
1059
1060 $postcode = $first_part . ' ' . $last_part;
1061 }
1062 elseif ( strlen($postcode) == 6 )
1063 {
1064 $first_part = substr($postcode, 0, 3);
1065 $last_part = substr($postcode, 3, 3);
1066
1067 $postcode = $first_part . ' ' . $last_part;
1068 }
1069 elseif ( strlen($postcode) == 7 )
1070 {
1071 $first_part = substr($postcode, 0, 4);
1072 $last_part = substr($postcode, 4, 3);
1073
1074 $postcode = $first_part . ' ' . $last_part;
1075 }
1076 }
1077
1078 $meta_query[] = array(
1079 'key' => '_address_postcode',
1080 'value' => ph_clean( $postcode ),
1081 'compare' => 'LIKE'
1082 );
1083 }
1084 }
1085
1086 if ( in_array('_address_country', $address_fields_to_query) )
1087 {
1088 $meta_query[] = array(
1089 'key' => '_address_country',
1090 'value' => $address_keyword,
1091 'compare' => '='
1092 );
1093
1094 // get country code for country entered
1095 $PH_Countries = new PH_Countries();
1096 $countries = $PH_Countries->countries;
1097 if ( is_array($countries) && !empty($countries) )
1098 {
1099 foreach ( $countries as $country_code => $country )
1100 {
1101 if ( strtolower($address_keyword) == strtolower($country['name']) )
1102 {
1103 $meta_query[] = array(
1104 'key' => '_address_country',
1105 'value' => $country_code,
1106 'compare' => '='
1107 );
1108 break;
1109 }
1110 }
1111 }
1112 }
1113
1114 if (
1115 !preg_match('/^(?:[A-Z]{2}\d|[A-Z]\d)/i', $address_keyword) &&
1116 in_array('_address_concatenated', $address_fields_to_query)
1117 )
1118 {
1119 $meta_query[] = array(
1120 'key' => '_address_concatenated',
1121 'value' => $address_keyword,
1122 'compare' => 'LIKE'
1123 );
1124 }
1125 }
1126
1127 }
1128 }
1129
1130 return $meta_query;
1131 }
1132
1133 public function where_properties_in_polygon( $where, $query )
1134 {
1135 global $wpdb;
1136
1137 if ( !empty($this->address_keyword_polygon_points) )
1138 {
1139 $where .= " AND
1140 ST_CONTAINS(
1141 ST_GEOMFROMTEXT('POLYGON((" . implode(", ", $this->address_keyword_polygon_points) . "))'),
1142 ST_GEOMFROMTEXT(
1143 CONCAT(
1144 'POINT(',
1145 COALESCE((SELECT meta_value FROM $wpdb->postmeta WHERE $wpdb->postmeta.meta_key='_latitude' AND $wpdb->postmeta.meta_value != '' AND $wpdb->postmeta.meta_value != 0 AND $wpdb->postmeta.post_id = $wpdb->posts.ID LIMIT 1), '0'),
1146 ' ',
1147 COALESCE((SELECT meta_value FROM $wpdb->postmeta WHERE $wpdb->postmeta.meta_key='_longitude' AND $wpdb->postmeta.meta_value != '' AND $wpdb->postmeta.meta_value != 0 AND $wpdb->postmeta.post_id = $wpdb->posts.ID LIMIT 1), '0'),
1148 ')'
1149 )
1150 )
1151 )";
1152 }
1153
1154 remove_filter( 'posts_where' , array( $this, 'where_properties_in_polygon' ), 1, 2 );
1155
1156 return $where;
1157 }
1158
1159 /**
1160 * Returns a meta query to handle country
1161 *
1162 * @access public
1163 * @return array
1164 */
1165 public function country_meta_query( ) {
1166
1167 $meta_query = array();
1168
1169 if ( isset( $_REQUEST['country'] ) && $_REQUEST['country'] != '' )
1170 {
1171 $meta_query = array(
1172 'key' => '_address_country',
1173 'value' => ph_clean( $_REQUEST['country'] )
1174 );
1175 }
1176
1177 if ( isset( $_REQUEST['country_not'] ) && $_REQUEST['country_not'] != '' )
1178 {
1179 $meta_query = array(
1180 'key' => '_address_country',
1181 'value' => ph_clean( $_REQUEST['country_not'] ),
1182 'compare' => '!='
1183 );
1184 }
1185
1186 return $meta_query;
1187 }
1188
1189 /**
1190 * Returns a meta query to handle minimum price
1191 *
1192 * @access public
1193 * @return array
1194 */
1195 public function minimum_price_meta_query( ) {
1196
1197 $meta_query = array();
1198
1199 if (
1200 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' ) &&
1201 isset( $_REQUEST['minimum_price'] ) && $_REQUEST['minimum_price'] != ''
1202 )
1203 {
1204 $minimum_price = $_REQUEST['minimum_price'];
1205
1206 if ( !is_numeric($minimum_price) )
1207 {
1208 return $meta_query;
1209 }
1210
1211 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1212 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1213
1214 if ( $search_form_currency != 'GBP' )
1215 {
1216 // Convert $_REQUEST['minimum_price'] to GBP
1217 $ph_countries = new PH_Countries();
1218
1219 $minimum_price = $ph_countries->convert_price_to_gbp( $minimum_price, $search_form_currency );
1220 }
1221
1222 $meta_query = array(
1223 'key' => '_price_actual',
1224 'value' => ph_clean( floor( $minimum_price ) ),
1225 'compare' => '>=',
1226 'type' => 'NUMERIC'
1227 );
1228 }
1229
1230 return $meta_query;
1231 }
1232
1233 /**
1234 * Returns a meta query to handle maximum price
1235 *
1236 * @access public
1237 * @return array
1238 */
1239 public function maximum_price_meta_query( ) {
1240
1241 $meta_query = array();
1242
1243 if (
1244 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' ) &&
1245 isset( $_REQUEST['maximum_price'] ) && $_REQUEST['maximum_price'] != ''
1246 )
1247 {
1248 $maximum_price = $_REQUEST['maximum_price'];
1249
1250 if ( !is_numeric($maximum_price) )
1251 {
1252 return $meta_query;
1253 }
1254
1255 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1256 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1257
1258 if ( $search_form_currency != 'GBP' )
1259 {
1260 // Convert $_REQUEST['maximum_price'] to GBP
1261 $ph_countries = new PH_Countries();
1262
1263 $maximum_price = $ph_countries->convert_price_to_gbp( $maximum_price, $search_form_currency );
1264 }
1265
1266 $meta_query = array(
1267 'key' => '_price_actual',
1268 'value' => ph_clean( ceil( $maximum_price ) ),
1269 'compare' => '<=',
1270 'type' => 'NUMERIC'
1271 );
1272 }
1273
1274 return $meta_query;
1275 }
1276
1277 /**
1278 * Returns a meta query to handle price range
1279 *
1280 * @access public
1281 * @return array
1282 */
1283 public function price_range_meta_query( ) {
1284
1285 $meta_query = array();
1286
1287 if (
1288 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' ) &&
1289 isset( $_REQUEST['price_range'] ) && $_REQUEST['price_range'] != ''
1290 )
1291 {
1292 $explode_price_range = explode("-", ph_clean($_REQUEST['price_range']));
1293
1294 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1295 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1296
1297 if ( isset($explode_price_range[0]) && $explode_price_range[0] != '' )
1298 {
1299 $minimum_price = $explode_price_range[0];
1300
1301 if ( !is_numeric($minimum_price) )
1302 {
1303 return $meta_query;
1304 }
1305
1306 if ( $search_form_currency != 'GBP' )
1307 {
1308 // Convert $explode_price_range[0] to GBP
1309 $ph_countries = new PH_Countries();
1310
1311 $minimum_price = $ph_countries->convert_price_to_gbp( $minimum_price, $search_form_currency );
1312 }
1313
1314 $meta_query[] = array(
1315 'key' => '_price_actual',
1316 'value' => sanitize_text_field( floor( $minimum_price ) ),
1317 'compare' => '>=',
1318 'type' => 'NUMERIC'
1319 );
1320 }
1321 if ( isset($explode_price_range[1]) && $explode_price_range[1] != '' )
1322 {
1323 $maximum_price = $explode_price_range[1];
1324
1325 if ( !is_numeric($maximum_price) )
1326 {
1327 return $meta_query;
1328 }
1329
1330 if ( $search_form_currency != 'GBP' )
1331 {
1332 // Convert $explode_price_range[1] to GBP
1333 $ph_countries = new PH_Countries();
1334
1335 $maximum_price = $ph_countries->convert_price_to_gbp( $maximum_price, $search_form_currency );
1336 }
1337
1338 $meta_query[] = array(
1339 'key' => '_price_actual',
1340 'value' => sanitize_text_field( ceil( $maximum_price ) ),
1341 'compare' => '<=',
1342 'type' => 'NUMERIC'
1343 );
1344 }
1345 }
1346
1347 return $meta_query;
1348 }
1349
1350 /**
1351 * Returns a meta query to handle minimum rent
1352 *
1353 * @access public
1354 * @return array
1355 */
1356 public function minimum_rent_meta_query( ) {
1357
1358 $meta_query = array();
1359
1360 if (
1361 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ) &&
1362 isset( $_REQUEST['minimum_rent'] ) && $_REQUEST['minimum_rent'] != ''
1363 )
1364 {
1365 $minimum_rent = $_REQUEST['minimum_rent'];
1366
1367 if ( !is_numeric($minimum_rent) )
1368 {
1369 return $meta_query;
1370 }
1371
1372 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1373 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1374
1375 if ( $search_form_currency != 'GBP' )
1376 {
1377 // Convert $_REQUEST['minimum_rent'] to GBP
1378 $ph_countries = new PH_Countries();
1379
1380 $minimum_rent = $ph_countries->convert_price_to_gbp( $minimum_rent, $search_form_currency );
1381 }
1382
1383 $rent_frequency = apply_filters( 'propertyhive_search_form_rent_frequency', 'pcm' );
1384 switch ($rent_frequency)
1385 {
1386 case "pd": { $minimum_rent = ($minimum_rent * 365) / 12; break; }
1387 case "pw": { $minimum_rent = ($minimum_rent * 52) / 12; break; }
1388 case "pq": { $minimum_rent = ($minimum_rent * 4) / 12; break; }
1389 case "pa": { $minimum_rent = $minimum_rent / 12; break; }
1390 }
1391
1392 $meta_query = array(
1393 'key' => '_price_actual',
1394 'value' => ph_clean( floor( $minimum_rent ) ),
1395 'compare' => '>=',
1396 'type' => 'NUMERIC'
1397 );
1398 }
1399
1400 return $meta_query;
1401 }
1402
1403 /**
1404 * Returns a meta query to handle maximum rent
1405 *
1406 * @access public
1407 * @return array
1408 */
1409 public function maximum_rent_meta_query( ) {
1410
1411 $meta_query = array();
1412
1413 if (
1414 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ) &&
1415 isset( $_REQUEST['maximum_rent'] ) && $_REQUEST['maximum_rent'] != ''
1416 )
1417 {
1418 $maximum_rent = $_REQUEST['maximum_rent'];
1419
1420 if ( !is_numeric($maximum_rent) )
1421 {
1422 return $meta_query;
1423 }
1424
1425 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1426 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1427
1428 if ( $search_form_currency != 'GBP' )
1429 {
1430 // Convert $_REQUEST['maximum_rent'] to GBP
1431 $ph_countries = new PH_Countries();
1432
1433 $maximum_rent = $ph_countries->convert_price_to_gbp( $maximum_rent, $search_form_currency );
1434 }
1435
1436 $rent_frequency = apply_filters( 'propertyhive_search_form_rent_frequency', 'pcm' );
1437 switch ($rent_frequency)
1438 {
1439 case "pd": { $maximum_rent = ($maximum_rent * 365) / 12; break; }
1440 case "pw": { $maximum_rent = ($maximum_rent * 52) / 12; break; }
1441 case "pq": { $maximum_rent = ($maximum_rent * 4) / 12; break; }
1442 case "pa": { $maximum_rent = $maximum_rent / 12; break; }
1443 }
1444
1445 $meta_query = array(
1446 'key' => '_price_actual',
1447 'value' => ph_clean( ceil( $maximum_rent ) ),
1448 'compare' => '<=',
1449 'type' => 'NUMERIC'
1450 );
1451 }
1452
1453 return $meta_query;
1454 }
1455
1456 /**
1457 * Returns a meta query to handle rent range
1458 *
1459 * @access public
1460 * @return array
1461 */
1462 public function rent_range_meta_query( ) {
1463
1464 $meta_query = array();
1465
1466 if (
1467 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ) &&
1468 isset( $_REQUEST['rent_range'] ) && $_REQUEST['rent_range'] != ''
1469 )
1470 {
1471 $explode_rent_range = explode("-", ph_clean($_REQUEST['rent_range']));
1472
1473 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
1474 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
1475
1476 $rent_frequency = apply_filters( 'propertyhive_search_form_rent_frequency', 'pcm' );
1477
1478 if ( isset($explode_rent_range[0]) && $explode_rent_range[0] != '' )
1479 {
1480 $minimum_rent = $explode_rent_range[0];
1481
1482 if ( !is_numeric($minimum_rent) )
1483 {
1484 return $meta_query;
1485 }
1486
1487 if ( $search_form_currency != 'GBP' )
1488 {
1489 // Convert $explode_rent_range[0] to GBP
1490 $ph_countries = new PH_Countries();
1491
1492 $minimum_rent = $ph_countries->convert_price_to_gbp( $minimum_rent, $search_form_currency );
1493 }
1494
1495 switch ($rent_frequency)
1496 {
1497 case "pd": { $minimum_rent = ($minimum_rent * 365) / 12; break; }
1498 case "pw": { $minimum_rent = ($minimum_rent * 52) / 12; break; }
1499 case "pq": { $minimum_rent = ($minimum_rent * 4) / 12; break; }
1500 case "pa": { $minimum_rent = $minimum_rent / 12; break; }
1501 }
1502
1503 $meta_query[] = array(
1504 'key' => '_price_actual',
1505 'value' => sanitize_text_field( floor( $minimum_rent ) ),
1506 'compare' => '>=',
1507 'type' => 'NUMERIC'
1508 );
1509 }
1510 if ( isset($explode_rent_range[1]) && $explode_rent_range[1] != '' )
1511 {
1512 $maximum_rent = $explode_rent_range[1];
1513
1514 if ( !is_numeric($maximum_rent) )
1515 {
1516 return $meta_query;
1517 }
1518
1519 if ( $search_form_currency != 'GBP' )
1520 {
1521 // Convert $explode_rent_range[1] to GBP
1522 $ph_countries = new PH_Countries();
1523
1524 $maximum_rent = $ph_countries->convert_price_to_gbp( $maximum_rent, $search_form_currency );
1525 }
1526
1527 switch ($rent_frequency)
1528 {
1529 case "pd": { $maximum_rent = ($maximum_rent * 365) / 12; break; }
1530 case "pw": { $maximum_rent = ($maximum_rent * 52) / 12; break; }
1531 case "pq": { $maximum_rent = ($maximum_rent * 4) / 12; break; }
1532 case "pa": { $maximum_rent = $maximum_rent / 12; break; }
1533 }
1534
1535 $meta_query[] = array(
1536 'key' => '_price_actual',
1537 'value' => sanitize_text_field( ceil( $maximum_rent ) ),
1538 'compare' => '<=',
1539 'type' => 'NUMERIC'
1540 );
1541 }
1542 }
1543
1544 return $meta_query;
1545 }
1546
1547 /**
1548 * Returns a meta query to handle exact bedrooms
1549 *
1550 * @access public
1551 * @return array
1552 */
1553 public function bedrooms_meta_query( ) {
1554
1555 $meta_query = array();
1556
1557 if (
1558 (
1559 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1560 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1561 ) &&
1562 isset( $_REQUEST['bedrooms'] ) && $_REQUEST['bedrooms'] != ''
1563 )
1564 {
1565 $meta_query = array(
1566 'key' => '_bedrooms',
1567 'value' => ph_clean( $_REQUEST['bedrooms'] ),
1568 'compare' => '=',
1569 'type' => 'NUMERIC'
1570 );
1571 }
1572
1573 return $meta_query;
1574 }
1575
1576 /**
1577 * Returns a meta query to handle minimum bedrooms
1578 *
1579 * @access public
1580 * @return array
1581 */
1582 public function minimum_bedrooms_meta_query( ) {
1583
1584 $meta_query = array();
1585
1586 if (
1587 (
1588 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1589 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1590 ) &&
1591 isset( $_REQUEST['minimum_bedrooms'] ) && $_REQUEST['minimum_bedrooms'] != ''
1592 )
1593 {
1594 $meta_query = array(
1595 'key' => '_bedrooms',
1596 'value' => ph_clean( $_REQUEST['minimum_bedrooms'] ),
1597 'compare' => '>=',
1598 'type' => 'NUMERIC'
1599 );
1600 }
1601
1602 return $meta_query;
1603 }
1604
1605 /**
1606 * Returns a meta query to handle maximum bedrooms
1607 *
1608 * @access public
1609 * @return array
1610 */
1611 public function maximum_bedrooms_meta_query( ) {
1612
1613 $meta_query = array();
1614
1615 if (
1616 (
1617 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1618 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1619 ) &&
1620 isset( $_REQUEST['maximum_bedrooms'] ) && $_REQUEST['maximum_bedrooms'] != ''
1621 )
1622 {
1623 $meta_query = array(
1624 'key' => '_bedrooms',
1625 'value' => ph_clean( $_REQUEST['maximum_bedrooms'] ),
1626 'compare' => '<=',
1627 'type' => 'NUMERIC'
1628 );
1629 }
1630
1631 return $meta_query;
1632 }
1633
1634 /**
1635 * Returns a meta query to handle minimum bathrooms
1636 *
1637 * @access public
1638 * @return array
1639 */
1640 public function minimum_bathrooms_meta_query( ) {
1641
1642 $meta_query = array();
1643
1644 if (
1645 (
1646 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1647 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1648 ) &&
1649 isset( $_REQUEST['minimum_bathrooms'] ) && $_REQUEST['minimum_bathrooms'] != ''
1650 )
1651 {
1652 $meta_query = array(
1653 'key' => '_bathrooms',
1654 'value' => ph_clean( $_REQUEST['minimum_bathrooms'] ),
1655 'compare' => '>=',
1656 'type' => 'NUMERIC'
1657 );
1658 }
1659
1660 return $meta_query;
1661 }
1662
1663 /**
1664 * Returns a meta query to handle maximum bathrooms
1665 *
1666 * @access public
1667 * @return array
1668 */
1669 public function maximum_bathrooms_meta_query( ) {
1670
1671 $meta_query = array();
1672
1673 if (
1674 (
1675 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1676 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1677 ) &&
1678 isset( $_REQUEST['maximum_bathrooms'] ) && $_REQUEST['maximum_bathrooms'] != ''
1679 )
1680 {
1681 $meta_query = array(
1682 'key' => '_bathrooms',
1683 'value' => ph_clean( $_REQUEST['maximum_bathrooms'] ),
1684 'compare' => '<=',
1685 'type' => 'NUMERIC'
1686 );
1687 }
1688
1689 return $meta_query;
1690 }
1691
1692 /**
1693 * Returns a meta query to handle minimum reception rooms
1694 *
1695 * @access public
1696 * @return array
1697 */
1698 public function minimum_reception_rooms_meta_query( ) {
1699
1700 $meta_query = array();
1701
1702 if (
1703 (
1704 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1705 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1706 ) &&
1707 isset( $_REQUEST['minimum_reception_rooms'] ) && $_REQUEST['minimum_reception_rooms'] != ''
1708 )
1709 {
1710 $meta_query = array(
1711 'key' => '_reception_rooms',
1712 'value' => ph_clean( $_REQUEST['minimum_reception_rooms'] ),
1713 'compare' => '>=',
1714 'type' => 'NUMERIC'
1715 );
1716 }
1717
1718 return $meta_query;
1719 }
1720
1721 /**
1722 * Returns a meta query to handle maximum reception rooms
1723 *
1724 * @access public
1725 * @return array
1726 */
1727 public function maximum_reception_rooms_meta_query( ) {
1728
1729 $meta_query = array();
1730
1731 if (
1732 (
1733 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-sales' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-sales' )) ||
1734 (isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ))
1735 ) &&
1736 isset( $_REQUEST['maximum_reception_rooms'] ) && $_REQUEST['maximum_reception_rooms'] != ''
1737 )
1738 {
1739 $meta_query = array(
1740 'key' => '_reception_rooms',
1741 'value' => ph_clean( $_REQUEST['maximum_reception_rooms'] ),
1742 'compare' => '<=',
1743 'type' => 'NUMERIC'
1744 );
1745 }
1746
1747 return $meta_query;
1748 }
1749
1750 /**
1751 * Returns a meta query to handle available date from
1752 *
1753 * @access public
1754 * @return array
1755 */
1756 public function available_date_from_meta_query( ) {
1757
1758 $meta_query = array();
1759
1760 if (
1761 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'residential-lettings' || ph_get_custom_department_based_on($_REQUEST['department']) == 'residential-lettings' ) &&
1762 isset( $_REQUEST['available_date_from'] ) && $_REQUEST['available_date_from'] != ''
1763 )
1764 {
1765 $available_date = ph_clean($_REQUEST['available_date_from']);
1766 if ( strpos($available_date, '/') !== FALSE )
1767 {
1768 // it's been provided in the format dd/mm/yyyy
1769 $explode_available_date = explode("/", $available_date);
1770 if ( count($explode_available_date) == 3 )
1771 {
1772 $available_date = $explode_available_date[0] . '-' . $explode_available_date[1] . '-' . $explode_available_date[2];
1773 }
1774 }
1775 $meta_query = array(
1776 'key' => '_available_date',
1777 'value' => ph_clean( $available_date ),
1778 'compare' => '<=',
1779 );
1780 }
1781
1782 return $meta_query;
1783 }
1784
1785 /**
1786 * Returns a meta query to handle minimum floor area
1787 *
1788 * @access public
1789 * @return array
1790 */
1791 public function minimum_floor_area_meta_query( ) {
1792
1793 $meta_query = array();
1794
1795 if (
1796 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1797 isset( $_REQUEST['minimum_floor_area'] ) && $_REQUEST['minimum_floor_area'] != '' &&
1798 (
1799 !isset( $_REQUEST['maximum_floor_area'] ) ||
1800 ( isset( $_REQUEST['maximum_floor_area'] ) && $_REQUEST['maximum_floor_area'] == '' )
1801 )
1802 )
1803 {
1804 $value = ph_clean( $_REQUEST['minimum_floor_area'] );
1805 if ( apply_filters('propertyhive_default_commercial_search_floor_area_unit', 'sqft') != 'sqft' )
1806 {
1807 // Convert value from square metres to square feet
1808 $value = $value * 10.76391041671;
1809 }
1810
1811 $meta_query = array(
1812 'key' => '_floor_area_to_sqft',
1813 'value' => $value,
1814 'compare' => '>=',
1815 'type' => 'NUMERIC'
1816 );
1817 }
1818
1819 return $meta_query;
1820 }
1821
1822 /**
1823 * Returns a meta query to handle maximum floor area
1824 *
1825 * @access public
1826 * @return array
1827 */
1828 public function maximum_floor_area_meta_query( ) {
1829
1830 $meta_query = array();
1831
1832 if (
1833 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1834 isset( $_REQUEST['maximum_floor_area'] ) && $_REQUEST['maximum_floor_area'] != '' &&
1835 (
1836 !isset( $_REQUEST['minimum_floor_area'] ) ||
1837 ( isset( $_REQUEST['minimum_floor_area'] ) && $_REQUEST['minimum_floor_area'] == '' )
1838 )
1839 )
1840 {
1841 $value = ph_clean( $_REQUEST['maximum_floor_area'] );
1842 if ( apply_filters('propertyhive_default_commercial_search_floor_area_unit', 'sqft') != 'sqft' )
1843 {
1844 // Convert value from square metres to square feet
1845 $value = $value * 10.76391041671;
1846 }
1847
1848 $meta_query = array(
1849 'key' => '_floor_area_from_sqft',
1850 'value' => $value,
1851 'compare' => '<=',
1852 'type' => 'NUMERIC'
1853 );
1854 }
1855
1856 return $meta_query;
1857 }
1858
1859 /**
1860 * Returns a meta query to handle minimum AND maximum floor area
1861 *
1862 * @access public
1863 * @return array
1864 */
1865 public function minimum_maximum_floor_area_meta_query( ) {
1866
1867 $meta_query = array();
1868
1869 if (
1870 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1871 isset( $_REQUEST['minimum_floor_area'] ) && $_REQUEST['minimum_floor_area'] != '' &&
1872 isset( $_REQUEST['maximum_floor_area'] ) && $_REQUEST['maximum_floor_area'] != ''
1873 )
1874 {
1875 $maximum_floor_area = ph_clean( $_REQUEST['maximum_floor_area'] );
1876 $minimum_floor_area = ph_clean( $_REQUEST['minimum_floor_area'] );
1877 if ( apply_filters('propertyhive_default_commercial_search_floor_area_unit', 'sqft') != 'sqft' )
1878 {
1879 // Convert value from square metres to square feet
1880 $maximum_floor_area = $maximum_floor_area * 10.76391041671;
1881 $minimum_floor_area = $minimum_floor_area * 10.76391041671;
1882 }
1883
1884 $meta_query[] = array(
1885 'key' => '_floor_area_from_sqft',
1886 'value' => $maximum_floor_area,
1887 'compare' => '<=',
1888 'type' => 'NUMERIC'
1889 );
1890 $meta_query[] = array(
1891 'key' => '_floor_area_to_sqft',
1892 'value' => $minimum_floor_area,
1893 'compare' => '>=',
1894 'type' => 'NUMERIC'
1895 );
1896 }
1897
1898 return $meta_query;
1899 }
1900
1901
1902 /**
1903 * Returns a meta query to handle floor area range
1904 *
1905 * @access public
1906 * @return array
1907 */
1908 public function floor_area_range_meta_query( ) {
1909
1910 $meta_query = array();
1911
1912 if (
1913 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1914 isset( $_REQUEST['floor_area_range'] ) && $_REQUEST['floor_area_range'] != ''
1915 )
1916 {
1917 $explode_floor_area_range = explode("-", ph_clean($_REQUEST['floor_area_range']));
1918
1919 if ( isset($explode_floor_area_range[0]) && $explode_floor_area_range[0] != '' )
1920 {
1921 $meta_query = array(
1922 'key' => '_floor_area_from_sqft',
1923 'value' => ph_clean( $explode_floor_area_range[0] ),
1924 'compare' => '>=',
1925 'type' => 'NUMERIC'
1926 );
1927 }
1928 if ( isset($explode_floor_area_range[1]) && $explode_floor_area_range[1] != '' )
1929 {
1930 $meta_query = array(
1931 'key' => '_floor_area_to_sqft',
1932 'value' => ph_clean( $explode_floor_area_range[1] ),
1933 'compare' => '<=',
1934 'type' => 'NUMERIC'
1935 );
1936 }
1937 }
1938
1939 return $meta_query;
1940 }
1941
1942 /**
1943 * Returns a meta query to handle commercial for sale or to rent
1944 *
1945 * @access public
1946 * @return array
1947 */
1948 public function commercial_for_sale_to_rent_meta_query( ) {
1949
1950 $meta_query = array();
1951
1952 if (
1953 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1954 isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'for_sale'
1955 )
1956 {
1957 $meta_query = array(
1958 'key' => '_for_sale',
1959 'value' => 'yes',
1960 'compare' => '=',
1961 );
1962 }
1963
1964 if (
1965 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1966 isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'to_rent'
1967 )
1968 {
1969 $meta_query = array(
1970 'key' => '_to_rent',
1971 'value' => 'yes',
1972 'compare' => '=',
1973 );
1974 }
1975
1976 return $meta_query;
1977 }
1978
1979 /**
1980 * Returns a meta query to handle commercial for sale
1981 *
1982 * @access public
1983 * @return array
1984 */
1985 public function commercial_for_sale_meta_query( ) {
1986
1987 $meta_query = array();
1988
1989 if (
1990 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
1991 isset( $_REQUEST['commercial_for_sale'] ) && $_REQUEST['commercial_for_sale'] == '1'
1992 )
1993 {
1994 $meta_query = array(
1995 'key' => '_for_sale',
1996 'value' => 'yes',
1997 'compare' => '=',
1998 );
1999 }
2000
2001 return $meta_query;
2002 }
2003
2004 /**
2005 * Returns a meta query to handle commercial to rent
2006 *
2007 * @access public
2008 * @return array
2009 */
2010 public function commercial_to_rent_meta_query( ) {
2011
2012 $meta_query = array();
2013
2014 if (
2015 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
2016 isset( $_REQUEST['commercial_to_rent'] ) && $_REQUEST['commercial_to_rent'] == '1'
2017 )
2018 {
2019 $meta_query = array(
2020 'key' => '_to_rent',
2021 'value' => 'yes',
2022 'compare' => '=',
2023 );
2024 }
2025
2026 return $meta_query;
2027 }
2028
2029 /**
2030 * Returns a meta query to handle commercial minimum price
2031 *
2032 * @access public
2033 * @return array
2034 */
2035 public function commercial_minimum_price_meta_query( ) {
2036
2037 $meta_query = array();
2038
2039 if (
2040 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
2041 (
2042 ( isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'for_sale' )
2043 ||
2044 ( isset( $_REQUEST['commercial_for_sale'] ) && $_REQUEST['commercial_for_sale'] == '1' )
2045 ) &&
2046 isset( $_REQUEST['commercial_minimum_price'] ) && $_REQUEST['commercial_minimum_price'] != ''
2047 )
2048 {
2049 $minimum_price = $_REQUEST['commercial_minimum_price'];
2050
2051 if ( !is_numeric($minimum_price) )
2052 {
2053 return $meta_query;
2054 }
2055
2056 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
2057 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
2058
2059 if ( $search_form_currency != 'GBP' )
2060 {
2061 // Convert $_REQUEST['minimum_price'] to GBP
2062 $ph_countries = new PH_Countries();
2063
2064 $minimum_price = $ph_countries->convert_price_to_gbp( $minimum_price, $search_form_currency );
2065 }
2066
2067 $meta_query = array(
2068 'key' => '_price_to_actual',
2069 'value' => ph_clean( floor( $minimum_price ) ),
2070 'compare' => '>=',
2071 'type' => 'NUMERIC'
2072 );
2073 }
2074
2075 return $meta_query;
2076 }
2077
2078 /**
2079 * Returns a meta query to handle commercial maximum price
2080 *
2081 * @access public
2082 * @return array
2083 */
2084 public function commercial_maximum_price_meta_query( ) {
2085
2086 $meta_query = array();
2087
2088 if (
2089 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
2090 (
2091 ( isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'for_sale' )
2092 ||
2093 ( isset( $_REQUEST['commercial_for_sale'] ) && $_REQUEST['commercial_for_sale'] == '1' )
2094 ) &&
2095 isset( $_REQUEST['commercial_maximum_price'] ) && $_REQUEST['commercial_maximum_price'] != ''
2096 )
2097 {
2098 $maximum_price = $_REQUEST['commercial_maximum_price'];
2099
2100 if ( !is_numeric($maximum_price) )
2101 {
2102 return $meta_query;
2103 }
2104
2105 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
2106 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
2107
2108 if ( $search_form_currency != 'GBP' )
2109 {
2110 // Convert $_REQUEST['maximum_price'] to GBP
2111 $ph_countries = new PH_Countries();
2112
2113 $maximum_price = $ph_countries->convert_price_to_gbp( $maximum_price, $search_form_currency );
2114 }
2115
2116 $meta_query = array(
2117 'key' => '_price_from_actual',
2118 'value' => ph_clean( ceil( $maximum_price ) ),
2119 'compare' => '<=',
2120 'type' => 'NUMERIC'
2121 );
2122 }
2123
2124 return $meta_query;
2125 }
2126
2127 /**
2128 * Returns a meta query to handle commercial minimum rent
2129 *
2130 * @access public
2131 * @return array
2132 */
2133 public function commercial_minimum_rent_meta_query( ) {
2134
2135 $meta_query = array();
2136
2137 if (
2138 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
2139 (
2140 ( isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'to_rent' )
2141 ||
2142 ( isset( $_REQUEST['commercial_to_rent'] ) && $_REQUEST['commercial_to_rent'] == '1' )
2143 ) &&
2144 isset( $_REQUEST['commercial_minimum_rent'] ) && $_REQUEST['commercial_minimum_rent'] != ''
2145 )
2146 {
2147 $minimum_rent = $_REQUEST['commercial_minimum_rent'];
2148
2149 if ( !is_numeric($minimum_rent) )
2150 {
2151 return $meta_query;
2152 }
2153
2154 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
2155 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
2156
2157 if ( $search_form_currency != 'GBP' )
2158 {
2159 // Convert $_REQUEST['minimum_rent'] to GBP
2160 $ph_countries = new PH_Countries();
2161
2162 $minimum_rent = $ph_countries->convert_price_to_gbp( $minimum_rent, $search_form_currency );
2163 }
2164
2165 $meta_query = array(
2166 'key' => '_rent_to_actual',
2167 'value' => ph_clean( floor( $minimum_rent ) ),
2168 'compare' => '>=',
2169 'type' => 'NUMERIC'
2170 );
2171 }
2172
2173 return $meta_query;
2174 }
2175
2176 /**
2177 * Returns a meta query to handle commercial maximum rent
2178 *
2179 * @access public
2180 * @return array
2181 */
2182 public function commercial_maximum_rent_meta_query( ) {
2183
2184 $meta_query = array();
2185
2186 if (
2187 isset( $_REQUEST['department'] ) && ( $_REQUEST['department'] == 'commercial' || ph_get_custom_department_based_on($_REQUEST['department']) == 'commercial' ) &&
2188 (
2189 ( isset( $_REQUEST['commercial_for_sale_to_rent'] ) && $_REQUEST['commercial_for_sale_to_rent'] == 'to_rent' )
2190 ||
2191 ( isset( $_REQUEST['commercial_to_rent'] ) && $_REQUEST['commercial_to_rent'] == '1' )
2192 ) &&
2193 isset( $_REQUEST['commercial_maximum_rent'] ) && $_REQUEST['commercial_maximum_rent'] != ''
2194 )
2195 {
2196 $maximum_rent = $_REQUEST['commercial_maximum_rent'];
2197
2198 if ( !is_numeric($maximum_rent) )
2199 {
2200 return $meta_query;
2201 }
2202
2203 $search_form_currency = get_option( 'propertyhive_search_form_currency', 'GBP' );
2204 $search_form_currency = apply_filters( 'propertyhive_query_search_form_currency', $search_form_currency );
2205
2206 if ( $search_form_currency != 'GBP' )
2207 {
2208 // Convert $_REQUEST['maximum_rent'] to GBP
2209 $ph_countries = new PH_Countries();
2210
2211 $maximum_rent = $ph_countries->convert_price_to_gbp( $maximum_rent, $search_form_currency );
2212 }
2213
2214 $meta_query = array(
2215 'key' => '_rent_from_actual',
2216 'value' => ph_clean( ceil( $maximum_rent ) ),
2217 'compare' => '<=',
2218 'type' => 'NUMERIC'
2219 );
2220 }
2221
2222 return $meta_query;
2223 }
2224
2225 /**
2226 * Returns a meta query to handle property negotiator
2227 *
2228 * @access public
2229 * @return array
2230 */
2231 public function negotiator_meta_query( ) {
2232
2233 $meta_query = array();
2234
2235 if ( isset( $_REQUEST['negotiator_id'] ) && $_REQUEST['negotiator_id'] != '' )
2236 {
2237 $meta_query = array(
2238 'key' => '_negotiator_id',
2239 'value' => (int)$_REQUEST['negotiator_id'],
2240 'compare' => '='
2241 );
2242 }
2243
2244 return $meta_query;
2245 }
2246
2247 /**
2248 * Returns a meta query to handle property office
2249 *
2250 * @access public
2251 * @param string $compare (default: 'IN')
2252 * @return array
2253 */
2254 public function office_meta_query( ) {
2255
2256 $meta_query = array();
2257
2258 if ( isset( $_REQUEST['officeID'] ) && $_REQUEST['officeID'] != '' )
2259 {
2260 $meta_query = array(
2261 'key' => '_office_id',
2262 'value' => ph_clean( (is_array($_REQUEST['officeID'])) ? $_REQUEST['officeID'] : array( $_REQUEST['officeID'] ) ),
2263 'compare' => 'IN'
2264 );
2265 }
2266
2267 return $meta_query;
2268 }
2269
2270 /**
2271 * Returns a meta query to handle searching for a keyword in the features and descriptions
2272 *
2273 * @access public
2274 * @return array
2275 */
2276 public function keyword_meta_query( ) {
2277
2278 $meta_query = array();
2279
2280 if ( isset( $_REQUEST['keyword'] ) && $_REQUEST['keyword'] != '' )
2281 {
2282 $_REQUEST['keyword'] = ph_clean( wp_unslash( $_REQUEST['keyword'] ) );
2283
2284 // Remove country code from end (i.e. ', UK')
2285 $_REQUEST['keyword'] = preg_replace('/\,\s?[A-Z][A-Z]$/', '', $_REQUEST['keyword']);
2286
2287 // Extract postcode and use that if exists
2288 $postcode_pattern = '/\b([A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9]?[A-Z]{0,2})\b/i';
2289 if ( preg_match($postcode_pattern, $_REQUEST['keyword'], $matches) )
2290 {
2291 $_REQUEST['keyword'] = $matches[1];
2292 }
2293
2294 $_REQUEST['keyword'] = trim($_REQUEST['keyword']);
2295
2296 $keywords = array( $_REQUEST['keyword'] );
2297
2298 if ( strpos( $_REQUEST['keyword'], ' ' ) !== FALSE )
2299 {
2300 $keywords[] = str_replace(" ", "-", ph_clean($_REQUEST['keyword']));
2301 }
2302 if ( strpos( $_REQUEST['keyword'], '-' ) !== FALSE )
2303 {
2304 $keywords[] = str_replace("-", " ", ph_clean($_REQUEST['keyword']));
2305 }
2306 if ( strpos( $_REQUEST['keyword'], '.' ) !== FALSE )
2307 {
2308 $keywords[] = str_replace(".", "", ph_clean($_REQUEST['keyword']));
2309 }
2310 if ( stripos( $_REQUEST['keyword'], 'st ' ) !== FALSE )
2311 {
2312 $keywords[] = str_ireplace("st ", "st. ", ph_clean($_REQUEST['keyword']));
2313 }
2314 if ( strpos( $_REQUEST['keyword'], '\'' ) !== FALSE )
2315 {
2316 $keywords[] = str_replace("'", "", ph_clean($_REQUEST['keyword']));
2317 }
2318
2319 $meta_query = array( 'relation' => 'OR' );
2320
2321 $fields_to_query = array(
2322 '_features_concatenated',
2323 '_descriptions_concatenated',
2324 '_reference_number',
2325 '_address_street',
2326 '_address_two',
2327 '_address_three',
2328 '_address_four',
2329 '_address_postcode',
2330 );
2331
2332 $fields_to_query = apply_filters( 'propertyhive_keyword_fields_to_query', $fields_to_query );
2333
2334 foreach ( $keywords as $keyword )
2335 {
2336 foreach ( $fields_to_query as $field )
2337 {
2338 if ( $field == '_address_postcode' ) { continue; } // ignore postcode as that is handled differently afterwards
2339
2340 $meta_query[] = array(
2341 'key' => $field,
2342 'value' => $keyword,
2343 'compare' => 'LIKE'
2344 );
2345 }
2346 }
2347 if ( in_array('_address_postcode', $fields_to_query) )
2348 {
2349 if ( strlen($_REQUEST['keyword']) <= 4 )
2350 {
2351 $meta_query[] = array(
2352 'key' => '_address_postcode',
2353 'value' => ph_clean( $_REQUEST['keyword'] ),
2354 'compare' => '='
2355 );
2356 // Run regex match where given keyword is at the start of the postcode ^
2357 // followed by one or zero letters (for WC2E-style postcodes) [a-zA-Z]?
2358 // then a single space [ ]
2359 $meta_query[] = array(
2360 'key' => '_address_postcode',
2361 'value' => '^' . ph_clean( $_REQUEST['keyword'] ) . '[a-zA-Z]?[ ]',
2362 'compare' => 'RLIKE'
2363 );
2364 }
2365 else
2366 {
2367 $postcode = ph_clean( $_REQUEST['keyword'] );
2368
2369 if ( preg_match('#^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW])[0-9][ABD-HJLNP-UW-Z]{2})$#i', $postcode) )
2370 {
2371 // UK postcode found with no space
2372
2373 if ( strlen($postcode) == 5 )
2374 {
2375 $first_part = substr($postcode, 0, 2);
2376 $last_part = substr($postcode, 2, 3);
2377
2378 $postcode = $first_part . ' ' . $last_part;
2379 }
2380 elseif ( strlen($postcode) == 6 )
2381 {
2382 $first_part = substr($postcode, 0, 3);
2383 $last_part = substr($postcode, 3, 3);
2384
2385 $postcode = $first_part . ' ' . $last_part;
2386 }
2387 elseif ( strlen($postcode) == 7 )
2388 {
2389 $first_part = substr($postcode, 0, 4);
2390 $last_part = substr($postcode, 4, 3);
2391
2392 $postcode = $first_part . ' ' . $last_part;
2393 }
2394 }
2395
2396 $meta_query[] = array(
2397 'key' => '_address_postcode',
2398 'value' => ph_clean( $postcode ),
2399 'compare' => 'LIKE'
2400 );
2401 }
2402 }
2403 }
2404
2405 return $meta_query;
2406 }
2407
2408 /**
2409 * Appends taxonomy queries to an array.
2410 * @access public
2411 * @param array $tax_query
2412 * @return array
2413 */
2414 public function get_tax_query( $tax_query = array() ) {
2415 if ( ! is_array( $tax_query ) )
2416 $tax_query = array();
2417
2418 if ( isset($_REQUEST) && !empty($_REQUEST) )
2419 {
2420 foreach ( $_REQUEST as $key => $value )
2421 {
2422 if ( taxonomy_exists($key) && isset( $_REQUEST[$key] ) && !empty($_REQUEST[$key]) && $this->taxonomy_allowed_for_department( $key ) )
2423 {
2424 $operator = $key == 'property_feature' ? 'AND' : 'IN';
2425
2426 $tax_query[] = array(
2427 'taxonomy' => $key,
2428 'terms' => ph_clean( (is_array($value)) ? $value : array( $value ) ),
2429 'operator' => $operator,
2430 );
2431 }
2432 }
2433 }
2434
2435 return array_filter( apply_filters( 'propertyhive_property_query_tax_query', $tax_query, $this ) );
2436 }
2437
2438 private function taxonomy_allowed_for_department( $taxonomy )
2439 {
2440 if ( isset( $_REQUEST['department'] ) && $_REQUEST['department'] != '' )
2441 {
2442 $department = ph_clean($_REQUEST['department']);
2443 }
2444 else
2445 {
2446 $department = get_option( 'propertyhive_primary_department', 'residential-sales' );
2447 }
2448
2449 if ( ph_get_custom_department_based_on( $department ) !== false )
2450 {
2451 $department = ph_get_custom_department_based_on( $department );
2452 }
2453
2454 switch ( $department )
2455 {
2456 case 'residential-sales':
2457 {
2458 if ( in_array( $taxonomy, array('commercial_property_type', 'commercial_tenure', 'furnished') ) )
2459 {
2460 return false;
2461 }
2462 break;
2463 }
2464 case 'residential-lettings':
2465 {
2466 if ( in_array( $taxonomy, array('commercial_property_type', 'commercial_tenure', 'tenure', 'sale_by', 'price_qualifier') ) )
2467 {
2468 return false;
2469 }
2470 break;
2471 }
2472 case 'commercial':
2473 {
2474 if ( in_array( $taxonomy, array('property_type', 'tenure', 'parking', 'outside_space', 'furnished') ) )
2475 {
2476 return false;
2477 }
2478 break;
2479 }
2480 }
2481
2482
2483 return true;
2484 }
2485
2486 /**
2487 * Layered Nav Init
2488 */
2489 public function layered_nav_init( ) {
2490
2491 }
2492
2493 /**
2494 * Layered Nav post filter
2495 *
2496 * @param array $filtered_posts
2497 * @return array
2498 */
2499 public function layered_nav_query( $filtered_posts ) {
2500
2501 }
2502
2503 /**
2504 * Price filter Init
2505 */
2506 public function price_filter_init() {
2507
2508 }
2509
2510 /**
2511 * Price Filter post filter
2512 *
2513 * @param array $filtered_posts
2514 * @return array
2515 */
2516 public function price_filter( $filtered_posts ) {
2517
2518 }
2519
2520 }
2521
2522 endif;
2523