/** * Performs front-end pre-header functionality * * - This function is not called on admin side. * - Loads conditional CSS styles. * - Determines if page is single property or property overview. * * @since 1.11 */ public function template_redirect() { global $post, $property, $wp_query, $wp_properties, $wp_styles, $wpp_query; /** * HACK. * @see self::parse_request(); * @author peshkov@UD */ if (get_query_var('_fix_to_page_template')) { $wp_query->is_single = false; $wp_query->is_page = true; } wp_localize_script('wpp-localization', 'wpp', array('instance' => $this->get_instance())); //** Load global wp-property script on all frontend pages */ wp_enqueue_script('wp-property-global'); if (apply_filters('wpp::custom_styles', false) === false) { //** Possibly load essential styles that are used in widgets */ wp_enqueue_style('wp-property-frontend'); //** Possibly load theme specific styles */ wp_enqueue_style('wp-property-theme-specific'); } if (!isset($wp_properties['configuration']['do_not_enable_text_widget_shortcodes']) || $wp_properties['configuration']['do_not_enable_text_widget_shortcodes'] != 'true') { add_filter('widget_text', 'do_shortcode'); } do_action('wpp_template_redirect'); //** Handle single property page previews */ if (!empty($wp_query->query_vars['preview']) && $post->post_type == "property" && $post->post_status == "publish") { wp_redirect(get_permalink($post->ID)); die; } /* (count($wp_query->posts) < 2) added post 1.31.1 release */ /* to avoid taxonomy archives from being broken by single property pages */ if (isset($post) && count($wp_query->posts) < 2 && ($post->post_type == "property" || isset($wp_query->is_child_property))) { $wp_query->single_property_page = true; //** This is a hack and should be done better */ if (!$post) { $post = get_post($wp_query->queried_object_id); $wp_query->posts[0] = $post; $wp_query->post = $post; } } //** If viewing root property page that is the default dynamic page. */ if (isset($wp_query->wpp_default_property_page)) { $wp_query->is_property_overview = true; } //** If this is the root page with a manually inserted shortcode, or any page with a PO shortcode */ if (isset($post) && strpos($post->post_content, "property_overview")) { $wp_query->is_property_overview = true; } //** If this is the root page and the shortcode is automatically inserted */ if (isset($wp_query->wpp_root_property_page) && $wp_properties['configuration']['automatically_insert_overview'] == 'true') { $wp_query->is_property_overview = true; } //** If search result page, and system not explicitly configured to not include PO on search result page automatically */ if (isset($wp_query->wpp_search_page) && (!isset($wp_properties['configuration']['do_not_override_search_result_page']) || $wp_properties['configuration']['do_not_override_search_result_page'] != 'true')) { $wp_query->is_property_overview = true; } //** Scripts and styles to load on all overview and single listing pages */ if (isset($wp_query->single_property_page) || isset($wp_query->is_property_overview)) { // Check for and load conditional browser styles $conditional_styles = apply_filters('wpp_conditional_style_slugs', array('IE', 'IE 7', 'msie')); foreach ($conditional_styles as $type) { // Fix slug for URL $url_slug = strtolower(str_replace(" ", "_", $type)); if (file_exists(STYLESHEETPATH . "/wp_properties-{$url_slug}.css")) { wp_register_style('wp-property-frontend-' . $url_slug, get_bloginfo('stylesheet_directory') . "/wp_properties-{$url_slug}.css", array('wp-property-frontend'), '1.13'); } elseif (file_exists(TEMPLATEPATH . "/wp_properties-{$url_slug}.css")) { wp_register_style('wp-property-frontend-' . $url_slug, get_bloginfo('template_url') . "/wp_properties-{$url_slug}.css", array('wp-property-frontend'), '1.13'); } elseif (file_exists(WPP_URL . "styles/wp_properties-{$url_slug}.css") && $wp_properties['configuration']['autoload_css'] == 'true') { wp_register_style('wp-property-frontend-' . $url_slug, WPP_URL . "styles/wp_properties-{$url_slug}.css", array('wp-property-frontend'), WPP_Version); } // Mark every style as conditional $wp_styles->add_data('wp-property-frontend-' . $url_slug, 'conditional', $type); wp_enqueue_style('wp-property-frontend-' . $url_slug); } } //** Scripts loaded only on single property pages */ if (isset($wp_query->single_property_page)) { WPP_F::console_log('Including scripts for all single property pages.'); WPP_F::load_assets(array('single')); do_action('template_redirect_single_property'); add_action('wp_head', create_function('', "do_action('wp_head_single_property'); ")); $property = (array) WPP_F::get_property($post->ID, "load_gallery=true"); $property_type = !empty($property['property_type']) ? $property['property_type'] : false; // Redirect to parent if property type is non-public. if (isset($wp_properties['redirect_to_parent']) && is_array($wp_properties['redirect_to_parent']) && in_array($property_type, $wp_properties['redirect_to_parent']) && $property['post_parent']) { die(wp_redirect(get_permalink($property['post_parent']))); } $property = prepare_property_for_display($property); //** Make certain variables available to be used within the single listing page */ $single_page_vars = apply_filters('wpp_property_page_vars', array('property' => $property, 'wp_properties' => $wp_properties)); //** By merging our extra variables into $wp_query->query_vars they will be extracted in load_template() */ if (is_array($single_page_vars)) { $wp_query->query_vars = array_merge($wp_query->query_vars, $single_page_vars); } } //** Current requests includes a property overview. PO may be via shortcode, search result, or due to this being the Default Dynamic Property page */ if (isset($wp_query->is_property_overview)) { WPP_F::console_log('Including scripts for all property overview pages.'); WPP_F::load_assets(array('overview')); if (isset($wp_query->wpp_default_property_page)) { WPP_F::console_log('Dynamic Default Property page detected, will load custom template.'); } else { WPP_F::console_log('Custom Default Property page detected, property overview content may be rendered via shortcode.'); } //** Make certain variables available to be used within the single listing page */ $overview_page_vars = apply_filters('wpp_overview_page_vars', array('wp_properties' => $wp_properties, 'wpp_query' => $wpp_query)); //** By merging our extra variables into $wp_query->query_vars they will be extracted in load_template() */ if (is_array($overview_page_vars)) { $wp_query->query_vars = array_merge($wp_query->query_vars, $overview_page_vars); } do_action('template_redirect_property_overview'); add_action('wp_head', create_function('', "do_action('wp_head_property_overview'); ")); } do_action('wpp_template_redirect_post_scripts'); }
/** * Primary static function for queries properties based on type and attributes * * @todo There is a limitation when doing a search such as 4,5+ then mixture of specific and open ended search is not supported. * @since 1.08 * * @param string $args / $args * * @param bool $total * * @return bool|mixed|void */ public static function get_properties($args = "", $total = false) { global $wpdb, $wp_properties, $wpp_query; //** Cleanup (fix) ID argument if it's passed */ $args = wp_parse_args($args); if (isset($args['id'])) { $args['ID'] = $args['id']; unset($args['id']); } //** property_id is replaced with ID only if Property Attribute with slug 'property_id' does not exist */ if (isset($args['property_id']) && !key_exists('property_id', $wp_properties['property_stats'])) { $args['ID'] = $args['property_id']; unset($args['property_id']); } //** Prints args to firebug if debug mode is enabled */ $log = is_array($args) ? urldecode(http_build_query($args)) : $args; WPP_F::console_log("get_properties() args: {$log}"); //** The function can be overwritten using the filter below. */ $response = apply_filters('wpp::get_properties::custom', null, $args, $total); if ($response !== null) { return $response; } $_query_keys = array(); /* Define keys that should not be used to query data */ $_system_keys = array('pagi', 'pagination', 'limit_query', 'starting_row', 'sort_by', 'sort_order'); // Non post_meta fields $non_post_meta = array('post_title' => 'like', 'post_status' => 'equal', 'post_author' => 'equal', 'ID' => 'or', 'post_parent' => 'equal', 'post_date' => 'date'); /** * Specific meta data can contain value with commas. E.g. location field ( address_attribute ) * The current list contains meta slugs which will be ignored for comma parsing. peshkov@UD */ $commas_ignore = apply_filters('wpp::get_properties::commas_ignore', array_filter(array($wp_properties['configuration']['address_attribute']))); $capture_sql_args = array('limit_query'); //** added to avoid range and "LIKE" searches on single numeric values * if (is_array($args)) { foreach ((array) $args as $thing => $value) { if (in_array($thing, (array) $capture_sql_args)) { $sql_args[$thing] = $value; unset($args[$thing]); continue; } // unset empty filter options if (empty($value)) { unset($args[$thing]); continue; } if (is_array($value)) { $value = implode(',', $value); } $value = trim($value); $original_value = $value; $numeric = !empty($wp_properties['numeric_attributes']) && in_array($thing, (array) $wp_properties['numeric_attributes']) ? true : false; //** If not CSV and last character is a +, we look for open-ended ranges, i.e. bedrooms: 5+ if (substr($original_value, -1, 1) == '+' && !strpos($original_value, ',') && $numeric) { //** User requesting an open ended range, we leave it off with a dash, i.e. 500- */ $args[$thing] = str_replace('+', '', $value) . '-'; } elseif (is_numeric($value) && $numeric) { //** If number is numeric, we do a specific search, i.e. 500-500 */ if (!array_key_exists($thing, $non_post_meta)) { $args[$thing] = $value . '-' . $value; } } elseif (is_string($value)) { $args[$thing] = $value; } } } $defaults = array('property_type' => 'all', 'pagi' => false, 'sort_by' => false); $query = wp_parse_args($args, $defaults); $query = apply_filters('wpp_get_properties_query', $query); $query_keys = array_keys((array) $query); //** Search by non meta values */ $additional_sql = ''; //** Show 'publish' posts if status is not specified */ if (!array_key_exists('post_status', $query)) { $additional_sql .= " AND p.post_status = 'publish' "; } else { if ($query['post_status'] != 'all') { if (strpos($query['post_status'], ',') === false) { $additional_sql .= " AND p.post_status = '{$query['post_status']}' "; } else { $post_status = explode(',', $query['post_status']); foreach ($post_status as &$ps) { $ps = trim($ps); } $additional_sql .= " AND p.post_status IN ( '" . implode("','", $post_status) . "') "; } } else { $additional_sql .= " AND p.post_status <> 'auto-draft' "; } unset($query['post_status']); } foreach ((array) $non_post_meta as $field => $condition) { if (array_key_exists($field, $query)) { if ($condition == 'like') { $additional_sql .= " AND p.{$field} LIKE '%{$query[$field]}%' "; } else { if ($condition == 'equal') { $additional_sql .= " AND p.{$field} = '{$query[$field]}' "; } else { if ($condition == 'or') { $f = ''; $d = !is_array($query[$field]) ? explode(',', $query[$field]) : $query[$field]; foreach ($d as $k => $v) { $f .= !empty($f) ? ",'" . trim($v) . "'" : "'" . trim($v) . "'"; } $additional_sql .= " AND p.{$field} IN ({$f}) "; } else { if ($condition == 'date') { $additional_sql .= " AND YEAR( p.{$field} ) = " . substr($query[$field], 0, 4) . " AND MONTH( p.{$field} ) = " . substr($query[$field], 4, 2) . " "; } } } } unset($query[$field]); } } if (!empty($sql_args['limit_query'])) { $sql_args['starting_row'] = $sql_args['starting_row'] ? $sql_args['starting_row'] : 0; $limit_query = "LIMIT {$sql_args['starting_row']}, {$sql_args['limit_query']};"; } elseif (substr_count($query['pagi'], '--')) { $pagi = explode('--', $query['pagi']); if (count($pagi) == 2 && is_numeric($pagi[0]) && is_numeric($pagi[1])) { $limit_query = "LIMIT {$pagi['0']}, {$pagi['1']};"; } } /** Handles the sort_by parameter in the Short Code */ if ($query['sort_by']) { $sql_sort_by = $query['sort_by']; $sql_sort_order = isset($query['sort_order']) ? strtoupper($query['sort_order']) : 'ASC'; } else { $sql_sort_by = 'post_date'; $sql_sort_order = 'ASC'; } //** Unsert arguments that will conflict with attribute query */ foreach ((array) $_system_keys as $system_key) { unset($query[$system_key]); } // Go down the array list narrowing down matching properties foreach ((array) $query as $meta_key => $criteria) { $specific = ''; // Stop filtering ( loop ) because no IDs left if (isset($matching_ids) && empty($matching_ids)) { break; } $numeric = isset($wp_properties['numeric_attributes']) && in_array($meta_key, (array) $wp_properties['numeric_attributes']) ? true : false; if (!in_array($meta_key, (array) $commas_ignore) && substr_count($criteria, ',') || substr_count($criteria, '-') && $numeric || substr_count($criteria, '--')) { if (substr_count($criteria, '-') && !substr_count($criteria, ',')) { $cr = explode('-', $criteria); // Check pieces of criteria. Array should contains 2 int's elements // In other way, it's just value of meta_key if (count($cr) > 2 || (double) $cr[0] == 0 && (double) $cr[1] == 0) { $specific = $criteria; } else { $hyphen_between = $cr; // If min value doesn't exist, set 1 if (empty($hyphen_between[0]) && $hyphen_between[0] != "0") { $hyphen_between[0] = 1; } } } if (substr_count($criteria, ',')) { $comma_and = explode(',', $criteria); } } else { $specific = $criteria; } if (!isset($limit_query)) { $limit_query = ''; } switch ($meta_key) { case 'property_type': // Get all property types if ($specific == 'all') { if (isset($matching_ids)) { $matching_id_filter = implode("' OR ID ='", $matching_ids); $matching_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE (ID ='{$matching_id_filter}' ) AND post_type = 'property'"); } else { $matching_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'property'"); } break; } //** If comma_and is set, $criteria is ignored, otherwise $criteria is used */ $property_type_array = isset($comma_and) && is_array($comma_and) ? $comma_and : array($specific); //** Make sure property type is in slug format */ foreach ($property_type_array as $key => $this_property_type) { foreach ((array) $wp_properties['property_types'] as $pt_key => $pt_value) { if (strtolower($pt_value) == strtolower($this_property_type)) { $property_type_array[$key] = $pt_key; } } } if (!empty($property_type_array)) { //** Multiple types passed */ $where_string = implode("' OR meta_value ='", $property_type_array); } else { //** Only on type passed */ $where_string = $property_type_array[0]; } // See if mathinc_ids have already been filtered down if (isset($matching_ids)) { $matching_id_filter = implode("' OR post_id ='", $matching_ids); $matching_ids = $wpdb->get_col("SELECT post_id FROM {$wpdb->postmeta} WHERE (post_id ='{$matching_id_filter}' ) AND ( meta_key = 'property_type' AND (meta_value ='{$where_string}' ))"); } else { $matching_ids = $wpdb->get_col("SELECT post_id FROM {$wpdb->postmeta} WHERE (meta_key = 'property_type' AND (meta_value ='{$where_string}' ))"); } break; case apply_filters('wpp::get_properties::custom_case', false, $meta_key): $matching_ids = apply_filters('wpp::get_properties::custom_key', $matching_ids, $meta_key, $criteria); break; default: // Get all properties for that meta_key if ($specific == 'all' && empty($comma_and) && empty($hyphen_between)) { if (isset($matching_ids)) { $matching_id_filter = implode("' OR post_id ='", $matching_ids); $matching_ids = $wpdb->get_col("SELECT post_id FROM {$wpdb->postmeta} WHERE (post_id ='{$matching_id_filter}' ) AND ( meta_key = '{$meta_key}' )"); } else { $matching_ids = $wpdb->get_col("SELECT post_id FROM {$wpdb->postmeta} WHERE (meta_key = '{$meta_key}' )"); } break; } else { if (!empty($comma_and)) { $where_and = "( meta_value ='" . implode("' OR meta_value ='", $comma_and) . "')"; $specific = $where_and; } if (!empty($hyphen_between)) { // We are going to see if we are looking at some sort of date, in which case we have a special MySQL modifier $adate = false; if (preg_match('%\\d{1,2}/\\d{1,2}/\\d{4}%i', $hyphen_between[0])) { $adate = true; } if (!empty($hyphen_between[1])) { if (preg_match('%\\d{1,2}/\\d{1,2}/\\d{4}%i', $hyphen_between[1])) { foreach ($hyphen_between as $key => $value) { $hyphen_between[$key] = "STR_TO_DATE( '{$value}', '%c/%e/%Y' )"; } $where_between = "STR_TO_DATE( `meta_value`, '%c/%e/%Y' ) BETWEEN " . implode(" AND ", $hyphen_between) . ""; } else { $where_between = "`meta_value` BETWEEN " . implode(" AND ", $hyphen_between) . ""; } } else { if ($adate) { $where_between = "STR_TO_DATE( `meta_value`, '%c/%e/%Y' ) >= STR_TO_DATE( '{$hyphen_between[0]}', '%c/%e/%Y' )"; } else { $where_between = "`meta_value` >= {$hyphen_between['0']}"; } } $specific = $where_between; } if ($specific == 'true') { // If properties data were imported, meta value can be '1' instead of 'true' // So we're trying to find also '1' $specific = "meta_value IN ( 'true', '1' )"; } elseif (!substr_count($specific, 'meta_value')) { //** Determine if we don't need to use LIKE in SQL query */ preg_match("/^#(.+)#\$/", $specific, $matches); if ($matches) { $specific = " meta_value = '{$matches[1]}'"; } else { //** Adds conditions for Searching by partial value */ $s = explode(' ', trim($specific)); $specific = ''; $count = 0; foreach ($s as $p) { if ($count > 0) { $specific .= " AND "; } $specific .= "meta_value LIKE '%{$p}%'"; $count++; } } } if (isset($matching_ids)) { $matching_id_filter = implode(",", $matching_ids); $sql_query = "SELECT post_id FROM {$wpdb->postmeta} WHERE post_id IN ( {$matching_id_filter} ) AND meta_key = '{$meta_key}' AND {$specific}"; } else { $sql_query = "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND {$specific}"; } //** Some specific additional conditions can be set in filters */ $sql_query = apply_filters('wpp::get_properties::meta_key::sql_query', $sql_query, array('meta_key' => $meta_key, 'specific' => $specific, 'matching_id_filter' => isset($matching_id_filter) ? $matching_id_filter : false, 'criteria' => $criteria)); $matching_ids = $wpdb->get_col($sql_query); } break; } // END switch unset($comma_and); unset($hyphen_between); } // END foreach // Return false, if there are any result using filter conditions if (empty($matching_ids)) { return false; } // Remove duplicates $matching_ids = array_unique($matching_ids); $matching_ids = apply_filters('wpp::get_properties::matching_ids', $matching_ids, array_merge((array) $query, array('additional_sql' => $additional_sql, 'total' => $total))); $result = apply_filters('wpp::get_properties::custom_sort', false, array('matching_ids' => $matching_ids, 'additional_sql' => $additional_sql, 'sort_by' => $sql_sort_by, 'sort_order' => $sql_sort_order, 'limit_query' => $limit_query)); if (!$result) { // Sorts the returned Properties by the selected sort order if ($sql_sort_by && $sql_sort_by != 'menu_order' && $sql_sort_by != 'post_date' && $sql_sort_by != 'post_modified' && $sql_sort_by != 'post_title') { //** Sorts properties in random order. */ if ($sql_sort_by === 'random') { $result = $wpdb->get_col("\n SELECT ID FROM {$wpdb->posts} AS p\n WHERE ID IN (" . implode(",", $matching_ids) . ")\n {$additional_sql}\n ORDER BY RAND() {$sql_sort_order}\n {$limit_query}"); } else { //** Determine if attribute has numeric format or all values of meta_key are numbers we use CAST in SQL query to avoid sort issues */ if (isset($wp_properties['numeric_attributes']) && in_array($sql_sort_by, $wp_properties['numeric_attributes']) || self::meta_has_number_data_type($matching_ids, $sql_sort_by)) { $meta_value = "CAST( meta_value AS DECIMAL(20,3 ))"; } else { $meta_value = "meta_value"; } $result = $wpdb->get_col("\n SELECT p.ID , (SELECT pm.meta_value FROM {$wpdb->postmeta} AS pm WHERE pm.post_id = p.ID AND pm.meta_key = '{$sql_sort_by}' LIMIT 1 ) as meta_value\n FROM {$wpdb->posts} AS p\n WHERE p.ID IN ( " . implode(",", $matching_ids) . ")\n {$additional_sql}\n ORDER BY {$meta_value} {$sql_sort_order}\n {$limit_query}"); } } else { $result = $wpdb->get_col("\n SELECT ID FROM {$wpdb->posts} AS p\n WHERE ID IN (" . implode(",", $matching_ids) . ")\n {$additional_sql}\n ORDER BY {$sql_sort_by} {$sql_sort_order}\n {$limit_query}"); } } // Stores the total Properties returned if ($total) { $total = count($wpdb->get_col("\n SELECT p.ID\n FROM {$wpdb->posts} AS p\n WHERE p.ID IN (" . implode(",", $matching_ids) . ")\n {$additional_sql}")); } WPP_F::console_log("get_properties() total: {$total}"); if (!empty($result)) { $return = array(); if (!empty($total)) { $return['total'] = $total; $return['results'] = $result; } else { $return = $result; } return apply_filters('wpp::get_properties::result', $return, $args); } return false; }