PluginProbe
Property Hive / trunk
Property Hive vtrunk
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 1.4.63 All 259 releases
propertyhive / includes / class-ph-query.php

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

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