/class-asp-search-cpt.php Secret
Last active
May 13, 2020 08:52
Star
You must be signed in to star a gist
class-asp-search-cpt.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* Prevent direct access */ | |
defined( 'ABSPATH' ) or die( "You can't access this file directly." ); | |
if ( ! class_exists( 'ASP_Search_CPT' ) ) { | |
/** | |
* Content (post,page,CPT) search class | |
* | |
* @class ASP_Search_CPT | |
* @version 2.0 | |
* @package AjaxSearchPro/Classes/Search | |
* @category Class | |
* @author Ernest Marcinko | |
*/ | |
class ASP_Search_CPT extends ASP_Search { | |
/** | |
* @var array of query parts | |
*/ | |
protected $parts = array(); | |
/** | |
* @var array of custom field query parts | |
*/ | |
protected $cf_parts = array(); | |
protected $ordering = array( | |
"primary" => "relevance DESC", | |
"secondary" => "post_date DESC", | |
"primary_field" => "relevance" | |
); | |
/** | |
* Gets the related taxonomy term count based on input post IDs and taxonomies and terms | |
* | |
* @param (int|object)[] $ids Array of post IDs or Array of Objects with post IDs | |
* @param ['taxonomy' => int[] terms] $taxonomies | |
* @param int $max_packet_size Maximum number of IDs per query | |
* @param int $max_call_count Maximum number of queries overall | |
* @return int[] associative array of term_id => object_count | |
*/ | |
public function get_relevant_tax_terms($post_ids, $taxonomy_terms, $max_packet_size = 1000, $max_call_count = 2 ) { | |
$_ids = array(); | |
$results = array(); | |
if ( count($post_ids) <= 0 ) return $results; | |
// Is this an object array? | |
if ( isset($post_ids[0]->id) ) { | |
foreach ($post_ids as $o) | |
$_ids[] = $o->id; | |
} else { | |
$_ids = $post_ids; | |
} | |
for ($i=0;$i<$max_call_count;$i++) { | |
$pack = array_splice($_ids, $max_packet_size); | |
// SELECT id FROM xxx WHERE post in $pack AND tax in ($taxonomies) | |
// $results = array_merge($results ...) | |
if ( count($_ids) <= 0 ) break; | |
} | |
return array_unique($results); | |
} | |
/** | |
* Content search function | |
* | |
* @return array|string | |
*/ | |
protected function do_search() { | |
global $wpdb; | |
global $q_config; | |
$args = &$this->args; | |
$aspdb = wd_asp()->tables; | |
if ( isset($args["_sd"]) ) | |
$sd = &$args["_sd"]; | |
else | |
$sd = array(); | |
// General variables | |
$postmeta_join = ""; | |
// Prefixes and suffixes | |
$pre_field = $this->pre_field; | |
$suf_field = $this->suf_field; | |
$pre_like = $this->pre_like; | |
$suf_like = $this->suf_like; | |
$wcl = '%'; // Wildcard Left | |
$wcr = '%'; // Wildcard right | |
if ( $args["_exact_matches"] == 1 ) { | |
if ( $args['_exact_match_location'] == 'start' ) | |
$wcl = ''; | |
else if ( $args['_exact_match_location'] == 'end' ) | |
$wcr = ''; | |
} | |
$kw_logic = $args['keyword_logic']; | |
$q_config['language'] = $args['_qtranslate_lang']; | |
$s = $this->s; // full keyword | |
$_s = $this->_s; // array of keywords | |
if ( $args['_limit'] > 0 ) { | |
$this->remaining_limit = $args['_limit']; | |
} else { | |
if ( $args['_ajax_search'] ) | |
$this->remaining_limit = $args['posts_limit']; | |
else | |
$this->remaining_limit = $args['posts_limit_override']; | |
} | |
$query_limit = $this->remaining_limit * $this->remaining_limit_mod; | |
if ($this->remaining_limit <= 0) | |
return array(); | |
$group_priority_select = $this->build_pgp_query( $wpdb->posts.".ID" ); | |
$group_priority_select = $group_priority_select . " AS group_priority,"; | |
$group_priority_orderby = "group_priority DESC, "; | |
/** | |
* Determine if the priorities table should be used or not. | |
*/ | |
$priority_select = WD_ASP_Priorities::count() > 0 ? " | |
IFNULL(( | |
SELECT | |
aspp.priority | |
FROM $aspdb->priorities as aspp | |
WHERE aspp.post_id = $wpdb->posts.ID AND aspp.blog_id = " . get_current_blog_id() . " | |
), 100) | |
" : 100; | |
/*------------------------- Statuses ----------------------------*/ | |
$post_statuses = ""; | |
$allowed_statuses = "'publish'"; // used later! | |
if ( count($args['post_status']) > 0) { | |
$allowed_statuses = "'".implode( "','", $args['post_status'] )."'"; | |
$post_statuses = "AND (" . $pre_field . $wpdb->posts . ".post_status" . $suf_field . " IN ($allowed_statuses) )"; | |
} | |
/*---------------------------------------------------------------*/ | |
/*----------------------- Gather Types --------------------------*/ | |
$page_q = ""; | |
if ( $args['_exclude_page_parent_child'] != '' ) | |
$page_q = " AND ( | |
$wpdb->posts.post_parent NOT IN (" . str_replace( '|', ',', $args['_exclude_page_parent_child'] ) . ") AND | |
$wpdb->posts.ID NOT IN (" . str_replace( '|', ',', $args['_exclude_page_parent_child'] ) . ") | |
)"; | |
// If no post types selected, well then return | |
if ( count( $args['post_type'] ) < 1 && $page_q == "" ) { | |
return ''; | |
} else { | |
$words = implode( "','", $args['post_type'] ); | |
if ( in_array('product_variation', $args['post_type']) ) { | |
$_post_types = $args['post_type']; | |
$_post_types = array_diff($_post_types, array('product_variation')); | |
if (count($_post_types) > 0) | |
$or_ptypes = "OR $wpdb->posts.post_type IN ('".implode("', '", $_post_types)."')"; | |
else | |
$or_ptypes = ''; | |
$post_types = " | |
(( | |
( | |
$wpdb->posts.post_type = 'product_variation' AND | |
EXISTS(SELECT 1 FROM $wpdb->posts par WHERE par.ID = $wpdb->posts.post_parent AND par.post_status IN($allowed_statuses) ) | |
) $or_ptypes | |
) $page_q)"; | |
} else { | |
$post_types = "($wpdb->posts.post_type IN ('$words') $page_q)"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
// ------------------------ Categories/tags/taxonomies ---------------------- | |
$term_query = $this->build_term_query( $wpdb->posts.".ID", $wpdb->posts.'.post_type' ); | |
// --------------------------------------------------------------------- | |
/*------------- Custom Fields with Custom selectors -------------*/ | |
$cf_select = $this->build_cff_query( $wpdb->posts.".ID" ); | |
/*---------------------------------------------------------------*/ | |
/*----------------------- Exclude USER id -----------------------*/ | |
$user_query = ""; | |
if ( isset($args['post_user_filter']['include']) ) { | |
if ( !in_array(-1, $args['post_user_filter']['include']) ) { | |
$user_query = "AND $wpdb->posts.post_author IN (" . implode(", ", $args['post_user_filter']['include']) . ") | |
"; | |
} | |
} | |
if ( isset($args['post_user_filter']['exclude']) ) { | |
if ( !in_array(-1, $args['post_user_filter']['exclude']) ) | |
$user_query = "AND $wpdb->posts.post_author NOT IN (".implode(", ", $args['post_user_filter']['exclude']).") "; | |
else | |
return array(); | |
} | |
/*---------------------------------------------------------------*/ | |
/*------------------------ Exclude ids --------------------------*/ | |
if ( !empty($args['post_not_in']) ) | |
$exclude_posts = "AND ($wpdb->posts.ID NOT IN (".(is_array($args['post_not_in']) ? implode(",", $args['post_not_in']) : $args['post_not_in'])."))"; | |
else | |
$exclude_posts = ""; | |
if ( !empty($args['post_not_in2']) ) | |
$exclude_posts .= "AND ($wpdb->posts.ID NOT IN (".implode(",", $args['post_not_in2'])."))"; | |
/*---------------------------------------------------------------*/ | |
/*------------------------ Include ids --------------------------*/ | |
if ( !empty($args['post_in']) ) | |
$include_posts = "AND ($wpdb->posts.ID IN (".(is_array($args['post_in']) ? implode(",", $args['post_in']) : $args['post_in'])."))"; | |
else | |
$include_posts = ""; | |
/*---------------------------------------------------------------*/ | |
/*------------------------ Term JOIN -------------------------*/ | |
// If the search in terms is not active, we don't need this unnecessary big join | |
$term_join = ""; | |
if ( in_array('terms', $args['post_fields']) ) { | |
$term_join = " | |
LEFT JOIN $wpdb->term_relationships ON $wpdb->posts.ID = $wpdb->term_relationships.object_id | |
LEFT JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id | |
LEFT JOIN $wpdb->terms ON $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id"; | |
} | |
/*---------------------------------------------------------------*/ | |
/*------------------------- WPML filter -------------------------*/ | |
$wpml_query = "(1)"; | |
if ( $args['_wpml_lang'] != "" ) { | |
global $sitepress; | |
$site_lang_selected = false; | |
$wpml_post_types_arr = array(); | |
foreach ($args['post_type'] as $tt) { | |
$wpml_post_types_arr[] = "post_" . $tt; | |
} | |
$wpml_post_types = implode( "','", $wpml_post_types_arr ); | |
// Let us get the default site language if possible | |
if ( is_object($sitepress) && method_exists($sitepress, 'get_default_language') ) { | |
$site_lang_selected = $sitepress->get_default_language() == $args['_wpml_lang'] ? true : false; | |
} | |
$_wpml_query_id_field = "$wpdb->posts.ID"; | |
// Product variations are not translated, so we need to use the parent ID (product) field to compare | |
if ( in_array('product_variation', $args['post_type']) ) { | |
$_wpml_query_id_field = "(IF($wpdb->posts.post_type='product_variation', $wpdb->posts.post_parent, $wpdb->posts.ID))"; | |
} | |
$wpml_query = " | |
EXISTS ( | |
SELECT DISTINCT(wpml.element_id) | |
FROM " . $wpdb->prefix . "icl_translations as wpml | |
WHERE | |
$_wpml_query_id_field = wpml.element_id AND | |
wpml.language_code = '" . ASP_Helpers::escape( $args['_wpml_lang'] ) . "' AND | |
wpml.element_type IN ('$wpml_post_types') | |
)"; | |
/** | |
* For missing translations.. | |
* If the site language is used, the translation can be non-existent | |
*/ | |
if ($site_lang_selected) { | |
$wpml_query = " | |
NOT EXISTS ( | |
SELECT DISTINCT(wpml.element_id) | |
FROM " . $wpdb->prefix . "icl_translations as wpml | |
WHERE | |
$_wpml_query_id_field = wpml.element_id AND | |
wpml.element_type IN ('$wpml_post_types') | |
) OR | |
" . $wpml_query; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*----------------------- POLYLANG filter -----------------------*/ | |
$polylang_query = ""; | |
if ( $args['_polylang_lang'] != "" ) { | |
$languages = get_terms('language', array( | |
'hide_empty' => false, | |
'fields' => 'ids', | |
'orderby' => 'term_group', | |
'slug' => $args['_polylang_lang']) | |
); | |
if ( !empty($languages) && !is_wp_error($languages) && isset($languages[0]) ) { | |
if ( in_array('product_variation', $args['post_type']) && class_exists('WooCommerce') ) { | |
$poly_field = "IF($wpdb->posts.post_type = 'product_variation', $wpdb->posts.post_parent, $wpdb->posts.ID)"; | |
} else { | |
$poly_field = "$wpdb->posts.ID"; | |
} | |
$polylang_query = " AND ( | |
$poly_field IN ( SELECT DISTINCT(tr.object_id) | |
FROM $wpdb->term_relationships AS tr | |
LEFT JOIN $wpdb->term_taxonomy as tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'language') | |
WHERE tt.term_id = $languages[0] | |
) )"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*--------------------- Post parent IDs -------------------------*/ | |
$post_parents = ''; | |
if ( count($args['post_parent']) > 0 ) { | |
$post_parents = "AND $wpdb->posts.post_parent IN (".implode(',', $args['post_parent']).") "; | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------- Post parent IDs exclude ----------------------*/ | |
$post_parents_exclude = ''; | |
if ( count($args['post_parent_exclude']) > 0 ) { | |
$post_parents_exclude = "AND $wpdb->posts.post_parent NOT IN (".implode(',', $args['post_parent_exclude']).") "; | |
} | |
/*---------------------------------------------------------------*/ | |
/*--------------------- Other Query stuff -----------------------*/ | |
// Do not select the content field, if it is not used at all | |
$select_content = $args['_post_get_content'] ? $wpdb->posts. ".post_content" : "''"; | |
// Do not select excerpt if its not used at all | |
$select_excerpt = $args['_post_get_excerpt'] ? $wpdb->posts. ".post_excerpt" : "''"; | |
/*---------------------------------------------------------------*/ | |
/*----------------------- Date filtering ------------------------*/ | |
$date_query = ""; | |
$date_query_parts = $this->get_date_query_parts(); | |
if ( count($date_query_parts) > 0 ) | |
$date_query = " AND (" . implode(" AND ", $date_query_parts) . ") "; | |
/*---------------------------------------------------------------*/ | |
/*-------------- Additional Query parts by Filters --------------*/ | |
/** | |
* Use these filters to add additional parts to the select, join or where | |
* parts of the search query. | |
* Params: | |
* array() $args - search arguments | |
* string $s - the full search keyword | |
* array() $_s - the array of unique search keywords separated | |
*/ | |
$add_select = apply_filters('asp_cpt_query_add_select', '', $args, $s, $_s); | |
$add_join = apply_filters('asp_cpt_query_add_join', '', $args, $s, $_s); | |
$add_where = apply_filters('asp_cpt_query_add_where', '', $args, $s, $_s); | |
/*---------------------------------------------------------------*/ | |
/*------------------- Post type based ordering ------------------*/ | |
$p_type_priority = ""; | |
if ( isset($sd['use_post_type_order']) && $sd['use_post_type_order'] == 1 ) { | |
foreach ( $sd['post_type_order'] as $pk => $p_order ) { | |
$p_type_priority .= " | |
WHEN '$p_order' THEN $pk "; | |
} | |
if ( $p_type_priority != "") | |
$p_type_priority = " | |
CASE $wpdb->posts.post_type | |
" . " " .$p_type_priority . " | |
ELSE 999 | |
END "; | |
else | |
$p_type_priority = "1"; | |
} else { | |
$p_type_priority = "1"; | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------- Primary custom field ordering ----------------*/ | |
$custom_field_selectp = "1 "; | |
if ( | |
strpos($args['post_primary_order'], 'customfp') !== false && | |
$args['_post_primary_order_metakey'] !== false | |
) { | |
$custom_field_selectp = "(SELECT IF(meta_value IS NULL, 0, meta_value) | |
FROM $wpdb->postmeta | |
WHERE | |
$wpdb->postmeta.meta_key='".esc_sql($args['_post_primary_order_metakey'])."' AND | |
$wpdb->postmeta.post_id=$wpdb->posts.ID | |
LIMIT 1 | |
) "; | |
} | |
/*---------------------------------------------------------------*/ | |
/*--------------- Secondary custom field ordering ---------------*/ | |
$custom_field_selects = "1 "; | |
if ( | |
strpos($args['post_secondary_order'], 'customfs') !== false && | |
$args['_post_secondary_order_metakey'] !== false | |
) { | |
$custom_field_selects = "(SELECT IF(meta_value IS NULL, 0, meta_value) | |
FROM $wpdb->postmeta | |
WHERE | |
$wpdb->postmeta.meta_key='".esc_sql($args['_post_secondary_order_metakey'])."' AND | |
$wpdb->postmeta.post_id=$wpdb->posts.ID | |
LIMIT 1 | |
) "; | |
} | |
/*---------------------------------------------------------------*/ | |
/** | |
* This is the main query. | |
* | |
* The ttid field is a bit tricky as the term_taxonomy_id doesn't always equal term_id, | |
* so we need the LEFT JOINS :( | |
*/ | |
$this->ordering['primary'] = $args['post_primary_order']; | |
$this->ordering['secondary'] = $args['post_secondary_order']; | |
$_primary_field = explode(" ", $this->ordering['primary']); | |
$this->ordering['primary_field'] = $_primary_field[0]; | |
$orderby_primary = str_replace( "post_", $wpdb->posts . ".post_", $args['post_primary_order'] ); | |
$orderby_secondary = str_replace( "post_", $wpdb->posts . ".post_", $args['post_secondary_order'] ); | |
if ( | |
$args['post_primary_order_metatype'] !== false && | |
$args['post_primary_order_metatype'] == 'numeric' | |
) | |
$orderby_primary = str_replace('customfp', 'CAST(customfp as SIGNED)', $orderby_primary); | |
if ( | |
$args['post_secondary_order_metatype'] !== false && | |
$args['post_secondary_order_metatype'] == 'numeric' | |
) | |
$orderby_secondary = str_replace('customfs', 'CAST(customfs as SIGNED)', $orderby_secondary); | |
$this->query = " | |
SELECT | |
$add_select | |
{args_fields} | |
$wpdb->posts.post_title as title, | |
$wpdb->posts.post_title as post_title, | |
$wpdb->posts.ID as id, | |
$this->c_blogid as blogid, | |
$wpdb->posts.post_date as date, | |
$wpdb->posts.post_date as post_date, | |
$select_content as content, | |
$select_excerpt as excerpt, | |
$wpdb->posts.post_type as post_type, | |
'pagepost' as content_type, | |
'post_page_cpt' as g_content_type, | |
(SELECT | |
$wpdb->users." . w_isset_def( $sd['author_field'], 'display_name' ) . " as author | |
FROM $wpdb->users | |
WHERE $wpdb->users.ID = $wpdb->posts.post_author | |
) as author, | |
$wpdb->posts.post_author as post_author, | |
$wpdb->posts.post_type as post_type, | |
$priority_select AS priority, | |
$p_type_priority AS p_type_priority, | |
$group_priority_select | |
{relevance_query} as relevance, | |
$custom_field_selectp as customfp, | |
$custom_field_selects as customfs | |
FROM $wpdb->posts | |
{postmeta_join} | |
$term_join | |
$add_join | |
{args_join} | |
WHERE | |
$post_types | |
$term_query | |
$user_query | |
AND $cf_select | |
$post_statuses | |
AND {like_query} | |
$exclude_posts | |
$include_posts | |
$post_parents | |
$post_parents_exclude | |
AND ( $wpml_query ) | |
$polylang_query | |
$date_query | |
$add_where | |
{args_where} | |
GROUP BY | |
{args_groupby} | |
ORDER BY {args_orderby} $group_priority_orderby priority DESC, p_type_priority ASC, $orderby_primary, $orderby_secondary, id DESC | |
LIMIT $query_limit"; | |
// Place the argument query fields | |
if ( isset($args['cpt_query']) && is_array($args['cpt_query']) ) { | |
$this->query = str_replace( | |
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}'), | |
array($args['cpt_query']['fields'], $args['cpt_query']['join'], $args['cpt_query']['where'], $args['cpt_query']['orderby']), | |
$this->query | |
); | |
} else { | |
$this->query = str_replace( | |
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}'), | |
'', | |
$this->query | |
); | |
} | |
if ( isset($args['cpt_query'], $args['cpt_query']['groupby']) && $args['cpt_query']['groupby'] != '' ) { | |
$this->query = str_replace('{args_groupby}', $args['cpt_query']['groupby'], $this->query); | |
} else { | |
$this->query = str_replace('{args_groupby}', "$wpdb->posts.ID", $this->query); | |
} | |
$words = $args["_exact_matches"] == 1 && $s != '' ? array($s) : $_s; | |
/** | |
* Ex.: When the minimum word count is 2, and the user enters 'a' then $_s is empty. | |
* But $s is not actually empty, thus the wrong query will be executed. | |
*/ | |
if ( count($words) == 0 && $s != '' ) { | |
$words = array($s); | |
// Allow only beginnings | |
if ( $args["_exact_matches"] == 0 ) | |
$wcl = ''; | |
} | |
if ( $s != '' ) | |
$words = !in_array($s, $words) ? array_merge(array($s), $words) : $words; | |
$relevance_added = false; | |
foreach ( $words as $k => $word ) { | |
$parts = array(); | |
$relevance_parts = array(); | |
$is_exact = $args["_exact_matches"] == 1 || ( count($words) > 1 && $k == 0 && ($kw_logic == 'or' || $kw_logic == 'and') ); | |
/*----------------------- Title query ---------------------------*/ | |
if ( in_array('title', $args['post_fields']) ) { | |
if ( $kw_logic == 'or' || $kw_logic == 'and' || $is_exact ) { | |
$parts[] = "( " . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
} else { | |
$parts[] = " | |
( " . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE $pre_like'% " . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE $pre_like'" . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE $pre_like'% " . $word . "'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " = '" . $word . "')"; | |
} | |
if ( !$relevance_added ) { | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE '$s%') | |
then " . (w_isset_def($sd['etitleweight'], 10) * 2) . " else 0 end)"; | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE '%$s%') | |
then " . w_isset_def($sd['etitleweight'], 10) . " else 0 end)"; | |
// The first word relevance is higher | |
if ( isset($_s[0]) ) { | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_title" . $suf_field . " LIKE '%" . $_s[0] . "%') | |
then " . w_isset_def($sd['etitleweight'], 10) . " else 0 end)"; | |
} | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------------- Content query --------------------------*/ | |
if ( in_array('content', $args['post_fields']) ) { | |
if ( $kw_logic == 'or' || $kw_logic == 'and' || $is_exact ) { | |
$parts[] = "( " . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
/** | |
* Exact matching multi line + word boundary with REGEXP | |
* | |
* $parts[] = "( " . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " REGEXP '([[:blank:][:punct:]]|^|\r\n)" . $word . "([[:blank:][:punct:]]|$|\r\n)' )"; | |
*/ | |
} else { | |
$parts[] = " | |
(" . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE $pre_like'% " . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE $pre_like'" . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE $pre_like'% " . $word . "'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " = '" . $word . "')"; | |
} | |
if ( !$relevance_added ) { | |
if ( isset($_s[0]) ) { | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE '%" . $_s[0] . "%') | |
then ".w_isset_def($sd['contentweight'], 10)." else 0 end)"; | |
} | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_content" . $suf_field . " LIKE '%$s%') | |
then " . w_isset_def($sd['econtentweight'], 10) . " else 0 end)"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*----------------- Permalink/Post name query -------------------*/ | |
if ( in_array('permalink', $args['post_fields']) ) { | |
$parts[] = "( " . $pre_field . $wpdb->posts . ".post_name" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------------- Excerpt query --------------------------*/ | |
if ( in_array('excerpt', $args['post_fields']) ) { | |
if ( $kw_logic == 'or' || $kw_logic == 'and' || $is_exact ) { | |
$parts[] = "( " . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
} else { | |
$parts[] = " | |
(" . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE $pre_like'% " . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE $pre_like'" . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE $pre_like'% " . $word . "'$suf_like | |
OR " . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " = '" . $word . "')"; | |
} | |
if ( !$relevance_added ) { | |
if ( isset($_s[0]) ) { | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE '%" . $_s[0] . "%') | |
then ".w_isset_def($sd['excerptweight'], 10)." else 0 end)"; | |
} | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->posts . ".post_excerpt" . $suf_field . " LIKE '%$s%') | |
then " . w_isset_def($sd['eexcerptweight'], 10) . " else 0 end)"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*------------------------ Term query ---------------------------*/ | |
if ( in_array('terms', $args['post_fields']) ) { | |
if ( $kw_logic == 'or' || $kw_logic == 'and' || $is_exact ) { | |
$parts[] = "( " . $pre_field . $wpdb->terms . ".name" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
} else { | |
$parts[] = " | |
(" . $pre_field . $wpdb->terms . ".name" . $suf_field . " LIKE $pre_like'% " . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->terms . ".name" . $suf_field . " LIKE $pre_like'" . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->terms . ".name" . $suf_field . " LIKE $pre_like'% " . $word . "'$suf_like | |
OR " . $pre_field . $wpdb->terms . ".name" . $suf_field . " = '" . $word . "')"; | |
} | |
if ( !$relevance_added ) { | |
$relevance_parts[] = "(case when | |
(" . $pre_field . $wpdb->terms . ".name" . $suf_field . " = '$s') | |
then " . w_isset_def($sd['etermsweight'], 10) . " else 0 end)"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------------- Custom Fields --------------------------*/ | |
if ( $args['post_custom_fields_all'] == 1 ) | |
$args['post_custom_fields'] = array("all"); | |
if ( count($args['post_custom_fields']) > 0 ) { | |
$postmeta_join = "LEFT JOIN $wpdb->postmeta ON $wpdb->postmeta.post_id = $wpdb->posts.ID"; | |
foreach ( $args['post_custom_fields'] as $cfield ) { | |
$key_part = $args['post_custom_fields_all'] == 1 ? "" : "$wpdb->postmeta.meta_key='$cfield' AND "; | |
if ( $kw_logic == 'or' || $kw_logic == 'and' || $is_exact ) { | |
$parts[] = "( $key_part " . $pre_field . $wpdb->postmeta . ".meta_value" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )"; | |
} else { | |
$parts[] = "( $key_part | |
(" . $pre_field . $wpdb->postmeta . ".meta_value" . $suf_field . " LIKE $pre_like'% " . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->postmeta . ".meta_value" . $suf_field . " LIKE $pre_like'" . $word . " %'$suf_like | |
OR " . $pre_field . $wpdb->postmeta . ".meta_value" . $suf_field . " LIKE $pre_like'% " . $word . "'$suf_like | |
OR " . $pre_field . $wpdb->postmeta . ".meta_value" . $suf_field . " = '" . $word . "') )"; | |
} | |
if ( !$relevance_added ) { | |
if ($cfield == 'author_field_name') | |
$relevance_parts[] = "(case when | |
(EXISTS (SELECT 1 FROM $wpdb->postmeta as cfre WHERE cfre.post_id = $wpdb->posts.ID AND cfre.meta_key = '$cfield' AND | |
(cfre.meta_value" . $suf_field . " LIKE '%" . $s . "%'))) | |
then 100 else 0 end)"; | |
if ($cfield == 'fulltext_field_name') | |
$relevance_parts[] = "(case when | |
(EXISTS (SELECT 1 FROM $wpdb->postmeta as cfre WHERE cfre.post_id = $wpdb->posts.ID AND cfre.meta_key = '$cfield' AND | |
(cfre.meta_value" . $suf_field . " LIKE '%" . $s . "%'))) | |
then 10 else 0 end)"; | |
} | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------------- Post CPT IDs ---------------------------*/ | |
if ( in_array("ids", $args['post_fields']) ) | |
$parts[] = "($wpdb->posts.ID LIKE '$word')"; | |
/*---------------------------------------------------------------*/ | |
$this->parts[] = array( $parts, $relevance_parts ); | |
$relevance_added = true; | |
} | |
// Add the meta join if needed.. | |
$this->query = str_replace( '{postmeta_join}', $postmeta_join, $this->query ); | |
$querystr = $this->build_query( $this->parts ); | |
$all_pageposts = $wpdb->get_results( $querystr, OBJECT ); | |
// Get the real count, up to 500 | |
$this->results_count = count($all_pageposts); | |
// For non-ajax search, results count needs to be limited to the maximum limit, | |
// ..as nothing is parsed beyond that | |
if ($args['_ajax_search'] == false && $this->results_count > $this->remaining_limit) { | |
$this->results_count = $this->remaining_limit; | |
} | |
/** | |
* Order them again: | |
* - The custom field ordering always uses alphanumerical comparision, which is not ok | |
*/ | |
if ( | |
count($all_pageposts) > 0 && | |
( | |
strpos($args['post_primary_order'], 'customfp') !== false || | |
strpos($args['post_secondary_order'], 'customfs') !== false | |
) | |
) { | |
usort( $all_pageposts, array( $this, 'compare_by_primary' ) ); | |
/** | |
* Let us save some time. There is going to be a user selecting the same sorting | |
* for both primary and secondary. Only do secondary if it is different from the primary. | |
*/ | |
if ( $this->ordering['primary'] != $this->ordering['secondary'] ) { | |
$i = 0; | |
foreach ($all_pageposts as $pk => $pp) { | |
$all_pageposts[$pk]->primary_order = $i; | |
$i++; | |
} | |
usort( $all_pageposts, array( $this, 'compare_by_secondary' ) ); | |
} | |
} | |
// Slice the needed ones only | |
$all_pageposts = array_slice($all_pageposts, $args['_call_num'] * $this->remaining_limit, $this->remaining_limit); | |
$this->results = $all_pageposts; | |
$this->return_count = count($this->results); | |
return $all_pageposts; | |
} | |
protected function build_pgp_query($post_id_field) { | |
global $wpdb; | |
$query = '1'; | |
$s = $this->s; | |
$args = $this->args; | |
$group_query_arr = array(); | |
foreach(wd_asp()->priority_groups->getSorted() as $group) { | |
// Rule affects this instance? | |
if ($group['instance'] != 0 && $group['instance'] != $args['_sid']) | |
continue; | |
// Rule affects this phrase? | |
if ( ASP_mb::strlen($group['phrase']) > 0 ) { | |
switch ($group['phrase_logic']) { | |
case 'any': | |
if (ASP_mb::strpos($s, $group['phrase']) === false) | |
continue 2; | |
break; | |
case 'exact': | |
if ($s !== $group['phrase']) | |
continue 2; | |
break; | |
case 'start': | |
if (ASP_mb::strpos($s, $group['phrase']) !== 0) | |
continue 2; | |
break; | |
case 'end': | |
if (!(ASP_mb::substr($s, -ASP_mb::strlen($group['phrase'])) === $group['phrase'])) | |
continue 2; | |
break; | |
} | |
} | |
$rule_query_arr = array(); | |
foreach($group['rules'] as $rule) { | |
switch($rule['field']) { | |
case 'tax': | |
$tax_term_query_arr = array(); | |
foreach ( $rule['values'] as $taxonomy => $terms ) { | |
if (count($terms) < 1) | |
continue; | |
$term_ids = implode(',', $terms); | |
if ( $rule['operator'] == 'in' ) { | |
$operator = 'EXISTS'; | |
} else { | |
$operator = 'NOT EXISTS'; | |
} | |
$tax_term_query_arr[] = "( | |
$operator ( SELECT 1 | |
FROM $wpdb->term_relationships AS gptr | |
LEFT JOIN $wpdb->term_taxonomy as gptt ON (gptr.term_taxonomy_id = gptt.term_taxonomy_id AND gptt.taxonomy = '$taxonomy') | |
WHERE gptt.term_id IN ($term_ids) AND gptr.object_id = $post_id_field | |
) )"; | |
} | |
if ( count($tax_term_query_arr) ) { | |
$tax_term_query = '( '.implode(' AND ', $tax_term_query_arr) . ' )'; | |
$rule_query_arr[] = $tax_term_query; | |
} | |
break; | |
case 'cf': | |
// Get the field and the values | |
foreach ( $rule['values'] as $field => $values ) | |
break; | |
$field = ASP_Helpers::escape($field); | |
$numeric_operators = array('=', '<>', '>', '>=', '<', '<='); | |
if ( false !== $nkey = array_search($rule['operator'], $numeric_operators) ) { | |
$operator = $numeric_operators[$nkey]; | |
$values = ASP_Helpers::force_numeric($values); | |
$qry = " gp_pm.meta_value".$operator.$values[0]; | |
} else if( | |
$rule['operator'] == 'between' && | |
isset($values[0], $values[1]) | |
) { | |
$qry = " gp_pm.meta_value BETWEEN ".$values[0]. " AND ".$values[1]; | |
} else if ( $rule['operator'] == 'like' ) { | |
$qry = " gp_pm.meta_value LIKE '%".$values[0]."%'"; | |
} else if ( $rule['operator'] == 'not like' ) { | |
$qry = " gp_pm.meta_value NOT LIKE '%".$values[0]."%'"; | |
} else if ( $rule['operator'] == 'elike' ) { | |
$qry = " gp_pm.meta_value LIKE '".$values[0]."'"; | |
} else { | |
// None of the operators above? | |
continue 2; | |
} | |
$cf_query = " | |
(EXISTS( | |
SELECT 1 | |
FROM $wpdb->postmeta as gp_pm | |
WHERE gp_pm.post_id = $post_id_field AND gp_pm.meta_key='$field' AND $qry | |
GROUP BY gp_pm.meta_id | |
ORDER BY gp_pm.meta_id | |
LIMIT 1 | |
))"; | |
$rule_query_arr[] = $cf_query; | |
break; | |
} | |
} | |
// Construct the WHEN-THEN for this case | |
if ( count($rule_query_arr) > 0 ) { | |
$priority = $group['priority'] + 0; | |
if ( $group['logic'] == 'and' ) | |
$rule_logic = ' AND '; | |
else | |
$rule_logic = ' OR '; | |
$condition = implode($rule_logic, $rule_query_arr); | |
$group_query_arr[] = "WHEN $condition THEN $priority"; | |
} | |
} | |
if ( count($group_query_arr) > 0 ) { | |
$query = implode(' ', $group_query_arr); | |
$query = "(CASE | |
$query | |
ELSE 1 | |
END)"; | |
} | |
return $query; | |
} | |
protected function build_term_query($post_id_field, $post_type_field) { | |
global $wpdb; | |
$args = $this->args; | |
if ( isset($_GET['ignore_op']) ) return ""; | |
$term_query = ""; | |
$term_query_parts = array(); | |
foreach ($args['post_tax_filter'] as $k => $item) { | |
$tax_term_query = ''; | |
$taxonomy = $item['taxonomy']; | |
// Is there an argument set to allow empty items for this taxonomy filter? | |
if ( isset($item['allow_empty']) ) { | |
$allow_empty_tax_term = $item['allow_empty']; | |
} else { | |
$allow_empty_tax_term = $taxonomy == 'post_tag' ? $args["_post_tags_empty"] : $args['_post_allow_empty_tax_term']; | |
} | |
if ( $allow_empty_tax_term == 1 ) { | |
$empty_terms_query = " | |
NOT EXISTS ( | |
SELECT * | |
FROM $wpdb->term_relationships as xt | |
INNER JOIN $wpdb->term_taxonomy as tt ON ( xt.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy') | |
WHERE | |
xt.object_id = $post_id_field | |
) OR "; | |
} else { | |
$empty_terms_query = ""; | |
} | |
// Quick explanation for the AND | |
// .. MAIN SELECT: selects all object_ids that are not in the array | |
// .. SUBSELECT: excludes all the object_ids that are part of the array | |
// This is used because of multiple object_ids (posts in more than 1 tag) | |
if ( !empty($item['exclude']) ) { | |
$words = implode( ',', $item['exclude'] ); | |
$tax_term_query = " ( | |
$empty_terms_query | |
$post_id_field IN ( | |
SELECT DISTINCT(tr.object_id) | |
FROM $wpdb->term_relationships AS tr | |
LEFT JOIN $wpdb->term_taxonomy as tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy') | |
WHERE | |
tt.term_id NOT IN ($words) | |
AND tr.object_id NOT IN ( | |
SELECT DISTINCT(trs.object_id) | |
FROM $wpdb->term_relationships AS trs | |
LEFT JOIN $wpdb->term_taxonomy as tts ON (trs.term_taxonomy_id = tts.term_taxonomy_id AND tts.taxonomy = '$taxonomy') | |
WHERE tts.term_id IN ($words) | |
) | |
) | |
)"; | |
} | |
if ( !empty($item['include']) ) { | |
$words = implode( ',', $item['include'] ); | |
if ( !empty($tax_term_query) ) | |
$tax_term_query .= " AND "; | |
if ( isset($item['logic']) && $item['logic'] == 'andex' ) { | |
$tax_term_query .= "( | |
$empty_terms_query | |
".count($item['include'])." = ( SELECT COUNT(tr.object_id) | |
FROM $wpdb->term_relationships AS tr | |
LEFT JOIN $wpdb->term_taxonomy as tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy') | |
WHERE tt.term_id IN ($words) AND tr.object_id = $post_id_field | |
) )"; | |
} else { | |
$tax_term_query .= "( | |
$empty_terms_query | |
$post_id_field IN ( SELECT DISTINCT(tr.object_id) | |
FROM $wpdb->term_relationships AS tr | |
LEFT JOIN $wpdb->term_taxonomy as tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy') | |
WHERE tt.term_id IN ($words) | |
) )"; | |
} | |
} | |
/** | |
* POST TAG SPECIFIC ONLY | |
* | |
* At this point we need to check if the user wants to hide the empty tags but the $tag_query | |
* turned out to be empty. (if not all tags are used and all of them are selected). | |
* If so, then return true on every post type other than 'post' OR check if any tags | |
* are associated with the post. | |
*/ | |
if ( | |
$taxonomy == 'post_tag' && | |
$args['_post_tags_active'] == 1 && | |
$tax_term_query == "" && | |
$args["_post_tags_empty"] == 0 | |
) { | |
$tax_term_query = " | |
( | |
($post_type_field != 'post') OR | |
EXISTS ( | |
SELECT * | |
FROM $wpdb->term_relationships as xt | |
INNER JOIN $wpdb->term_taxonomy as tt ON ( xt.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'post_tag') | |
WHERE | |
xt.object_id = $post_id_field | |
) | |
)"; | |
} | |
// ---------------------------------------------------- | |
if ( !empty($tax_term_query) ) | |
$term_query_parts[] = "(" . $tax_term_query . ")"; | |
} | |
if ( !empty($term_query_parts) ) | |
$term_query = "AND (" . implode(" ".strtoupper($args['_taxonomy_group_logic'])." ", $term_query_parts) . ") "; | |
return $term_query; | |
} | |
protected function build_cff_query( $post_id_field ) { | |
global $wpdb; | |
$args = $this->args; | |
$parts = array(); | |
aspDebug::start( '--searchContent-cf' ); | |
$allow_cf_null = $args['_post_meta_allow_null']; | |
foreach ( $args['post_meta_filter'] as $data ) { | |
$operator = $data['operator']; | |
$posted = $data['value']; | |
$field = $data['key']; | |
// Is this a special case of date operator? | |
if (strpos($operator, "datetime") === 0) { | |
$date_add = $allow_cf_null ? '' : "$wpdb->postmeta.meta_value<>'' AND "; | |
switch ($operator) { | |
case 'datetime =': | |
$current_part = "($date_add $wpdb->postmeta.meta_value BETWEEN '$posted 00:00:00' AND '$posted 23:59:59')"; | |
break; | |
case 'datetime <>': | |
$current_part = "($date_add $wpdb->postmeta.meta_value NOT BETWEEN '$posted 00:00:00' AND '$posted 23:59:59')"; | |
break; | |
case 'datetime <': | |
$current_part = "($date_add $wpdb->postmeta.meta_value < '$posted 00:00:00')"; | |
break; | |
case 'datetime <=': | |
$current_part = "($date_add $wpdb->postmeta.meta_value <= '$posted 23:59:59')"; | |
break; | |
case 'datetime >': | |
$current_part = "($date_add $wpdb->postmeta.meta_value > '$posted 23:59:59')"; | |
break; | |
case 'datetime >=': | |
$current_part = "($date_add $wpdb->postmeta.meta_value >= '$posted 00:00:00')"; | |
break; | |
default: | |
$current_part = "($date_add $wpdb->postmeta.meta_value < '$posted 00:00:00')"; | |
break; | |
} | |
// Is this a special case of timestamp? | |
} else if (strpos($operator, "timestamp") === 0) { | |
$date_add = $allow_cf_null ? '' : "$wpdb->postmeta.meta_value<>'' AND "; | |
switch ($operator) { | |
case 'timestamp =': | |
$current_part = "($date_add $wpdb->postmeta.meta_value BETWEEN $posted AND ".($posted + 86399).")"; | |
break; | |
case 'timestamp <>': | |
$current_part = "($date_add $wpdb->postmeta.meta_value NOT BETWEEN $posted AND ".($posted + 86399).")"; | |
break; | |
case 'timestamp <': | |
$current_part = "($date_add $wpdb->postmeta.meta_value < $posted)"; | |
break; | |
case 'timestamp <=': | |
$current_part = "($date_add $wpdb->postmeta.meta_value <= ".($posted + 86399).")"; | |
break; | |
case 'timestamp >': | |
$current_part = "($date_add $wpdb->postmeta.meta_value > ".($posted + 86399).")"; | |
break; | |
case 'timestamp >=': | |
$current_part = "($date_add $wpdb->postmeta.meta_value >= $posted)"; | |
break; | |
default: | |
$current_part = "($date_add $wpdb->postmeta.meta_value < $posted)"; | |
break; | |
} | |
// Check BETWEEN first -> range slider | |
} else if ( $operator === "BETWEEN" ) { | |
$current_part = "($wpdb->postmeta.meta_value BETWEEN " . $posted[0] . " AND " . $posted[1] . " )"; | |
// If not BETWEEN but value is array, then drop-down or checkboxes | |
} else if ( is_array($posted) ) { | |
// Is there a logic sent? | |
$logic = isset($data['logic']) ? $data['logic'] : "OR"; | |
$values = ''; | |
if ($operator === "IN" ) { | |
$val = implode("','", $posted); | |
if ( !empty($val) ) { | |
if ($values != '') { | |
$values .= " $logic $wpdb->postmeta.meta_value $operator ('" . $val . "')"; | |
} else { | |
$values .= "$wpdb->postmeta.meta_value $operator ('" . $val . "')"; | |
} | |
} | |
} else { | |
foreach ($posted as $v) { | |
if ($operator === "ELIKE" || $operator === "NOT ELIKE") { | |
$_op = $operator === 'ELIKE' ? 'LIKE' : 'NOT LIKE'; | |
if ($values != '') { | |
$values .= " $logic $wpdb->postmeta.meta_value $_op '" . $v . "'"; | |
} else { | |
$values .= "$wpdb->postmeta.meta_value $_op '" . $v . "'"; | |
} | |
} else if ($operator === "NOT LIKE" || $operator === "LIKE") { | |
if ($values != '') { | |
$values .= " $logic $wpdb->postmeta.meta_value $operator '%" . $v . "%'"; | |
} else { | |
$values .= "$wpdb->postmeta.meta_value $operator '%" . $v . "%'"; | |
} | |
} else { | |
if ($values != '') { | |
$values .= " $logic $wpdb->postmeta.meta_value $operator " . $v; | |
} else { | |
$values .= "$wpdb->postmeta.meta_value $operator " . $v; | |
} | |
} | |
} | |
} | |
$values = $values == '' ? '0' : $values; | |
$current_part = "($values)"; | |
// String operations | |
} else if ($operator === "NOT LIKE" || $operator === "LIKE") { | |
$current_part = "($wpdb->postmeta.meta_value $operator '%" . $posted . "%')"; | |
} else if ($operator === "ELIKE" || $operator === "NOT ELIKE") { | |
$_op = $operator === 'ELIKE' ? 'LIKE' : 'NOT LIKE'; | |
$current_part = "($wpdb->postmeta.meta_value $_op '$posted')"; | |
} else { | |
// Numeric operations or problematic stuff left | |
$current_part = "($wpdb->postmeta.meta_value $operator $posted )"; | |
} | |
// Finally add the current part to the parts array | |
if ( $current_part != "") { | |
if ( isset($data['allow_missing']) ) | |
$allowance = $data['allow_missing']; | |
else | |
$allowance = $allow_cf_null; | |
$parts[] = array($field, $current_part, $allowance); | |
} | |
} | |
// The correct count is the unique fields count | |
//$meta_count = count( $unique_fields ); | |
$cf_select = "(1)"; | |
$cf_select_arr = array(); | |
/** | |
* NOTE 1: | |
* With the previous NOT EXISTS(...) subquery solution the search would hang in some cases | |
* when checking if empty values are allowed. No idea why though... | |
* Eventually using separate sub-queries for each field is the best. | |
* | |
* NOTE 2: | |
* COUNT(post_id) is a MUST in the nested IF() statement !! Otherwise the query will return empty rows, no idea why either.. | |
*/ | |
foreach ( $parts as $k => $part ) { | |
$field = $part[0]; // Field name | |
$def = $part[2] ? "( | |
SELECT IF((meta_key IS NULL OR meta_value = ''), -1, COUNT(meta_id)) | |
FROM $wpdb->postmeta | |
WHERE $wpdb->postmeta.post_id = $post_id_field AND $wpdb->postmeta.meta_key='$field' | |
LIMIT 1 | |
) = -1 | |
OR" : ''; // Allowance | |
$qry = $part[1]; // Query condition | |
$cf_select_arr[] = " | |
( | |
$def | |
( | |
SELECT COUNT(meta_id) as mtc | |
FROM $wpdb->postmeta | |
WHERE $wpdb->postmeta.post_id = $post_id_field AND $wpdb->postmeta.meta_key='$field' AND $qry | |
GROUP BY meta_id | |
ORDER BY mtc | |
LIMIT 1 | |
) >= 1 | |
)"; | |
} | |
if ( count($cf_select_arr) ) { | |
// Connect them based on the meta logic | |
$cf_select = "( ". implode( $args['_post_meta_logic'], $cf_select_arr ) . " )"; | |
} | |
aspDebug::stop( '--searchContent-cf' ); | |
return $cf_select; | |
} | |
protected function get_date_query_parts( $table_alias = "", $date_field = "post_date" ) { | |
global $wpdb; | |
$args = $this->args; | |
if ( empty($table_alias) ) | |
$table_alias = $wpdb->posts; | |
$date_query_parts = array(); | |
foreach( $args['post_date_filter'] as $date_filter ) { | |
if (isset($date_filter['date'])) // Given by date argument | |
$date = $date_filter['date']; | |
else // Given by year, month, day arguments | |
$date = $date_filter['year'] . "-" . sprintf("%02d", $date_filter['month']) . "-" . sprintf("%02d", $date_filter['day']); | |
if ($date_filter['interval'] == "before") { | |
$op = $date_filter['operator'] == "exclude" ? ">" : "<="; | |
$date_query_parts[] = "$table_alias.$date_field $op '" . $date . " 23:59:59'"; | |
} else { | |
$op = $date_filter['operator'] == "exclude" ? "<" : ">="; | |
$date_query_parts[] = "$table_alias.$date_field $op '" . $date . " 00:00:00'"; | |
} | |
} | |
return $date_query_parts; | |
} | |
/** | |
* usort() custom function, sort by primary | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_primary( $a, $b ) { | |
// Only compare objects with the same post type priority, so the groups dont get messed up | |
if ( $a->p_type_priority === $b->p_type_priority ) { | |
if ($a->group_priority === $b->group_priority) { | |
if ($a->priority === $b->priority) { | |
switch ($this->ordering['primary']) { | |
case "average_rating DESC": | |
// ceil() is very important here!! as this expects 1, 0, -1 but no values inbetween | |
return ceil((float)$b->average_rating - (float)$a->average_rating); | |
break; | |
case "relevance DESC": | |
return $b->relevance - $a->relevance; | |
break; | |
case "post_date DESC": | |
$date_diff = strtotime($b->date) - strtotime($a->date); | |
if ($date_diff == 0) | |
return $b->id - $a->id; | |
return $date_diff; | |
break; | |
case "post_date ASC": | |
$date_diff = strtotime($a->date) - strtotime($b->date); | |
if ($date_diff == 0) | |
return $a->id - $b->id; | |
return $date_diff; | |
break; | |
case "post_title DESC": | |
return strcasecmp($b->title, $a->title); | |
break; | |
case "post_title ASC": | |
return strcasecmp($a->title, $b->title); | |
break; | |
case "customfp DESC": | |
if ($this->args['post_primary_order_metatype'] == 'numeric') | |
return floatval($b->customfp) - floatval($a->customfp); | |
else | |
return strcasecmp($b->customfp, $a->customfp); | |
break; | |
case "customfp ASC": | |
if ($this->args['post_primary_order_metatype'] == 'numeric') | |
return floatval($a->customfp) - floatval($b->customfp); | |
else | |
return strcasecmp($a->customfp, $b->customfp); | |
break; | |
default: | |
return $b->relevance - $a->relevance; | |
break; | |
} | |
} | |
return $b->priority - $a->priority; | |
} | |
return $b->group_priority - $a->group_priority; | |
} | |
// Post type priority is not equivalent, results should be treated as equals, no change | |
return $a->p_type_priority - $b->p_type_priority; | |
} | |
/** | |
* usort() custom function, sort by secondary | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_secondary( $a, $b ) { | |
if ( $a->p_type_priority === $b->p_type_priority ) { | |
if ($a->group_priority === $b->group_priority) { | |
if ($a->priority === $b->priority) { | |
$field = $this->ordering['primary_field']; | |
if ($a->$field == $b->$field) { | |
switch ($this->ordering['secondary']) { | |
case "relevance DESC": | |
return $b->relevance - $a->relevance; | |
break; | |
case "post_date DESC": | |
$date_diff = strtotime($b->date) - strtotime($a->date); | |
if ($date_diff == 0) | |
return $b->id - $a->id; | |
return $date_diff; | |
break; | |
case "post_date ASC": | |
$date_diff = strtotime($a->date) - strtotime($b->date); | |
if ($date_diff == 0) | |
return $a->id - $b->id; | |
return $date_diff; | |
break; | |
case "post_title DESC": | |
return strcasecmp($b->title, $a->title); | |
break; | |
case "post_title ASC": | |
return strcasecmp($a->title, $b->title); | |
break; | |
case "customfs DESC": | |
if ($this->args['post_secondary_order_metatype'] == 'numeric') | |
return $b->customfs - $a->customfs; | |
else | |
return strcasecmp($b->customfs, $a->customfs); | |
break; | |
case "customfs ASC": | |
if ($this->args['post_secondary_order_metatype'] == 'numeric') | |
return $a->customfs - $b->customfs; | |
else | |
return strcasecmp($a->customfs, $b->customfs); | |
break; | |
default: | |
return $b->relevance - $a->relevance; | |
break; | |
} | |
} | |
/** | |
* If the primary fields are not equal, then leave it as it is. | |
* The primary sorting already sorted the items out so return 0 - as equals | |
*/ | |
return $a->primary_order - $b->primary_order; | |
} | |
return $b->priority - $a->priority; | |
} | |
return $b->group_priority - $a->group_priority; | |
} | |
return $a->p_type_priority - $b->p_type_priority; | |
} | |
/** | |
* usort() custom function, sort by ID | |
* | |
* @param $obj_a | |
* @param $obj_b | |
* | |
* @return mixed | |
*/ | |
protected function compare_posts( $obj_a, $obj_b ) { | |
return $obj_a->id - $obj_b->id; | |
} | |
/** | |
* usort() custom function, sort by priority > relevance > date > title | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_rp( $a, $b ) { | |
if ( $a->priority === $b->priority ) { | |
if ( $a->relevance === $b->relevance ) { | |
if ( $a->date != null && $a->date != "" ) { | |
return strtotime( $b->date ) - strtotime( $a->date ); | |
} else { | |
return strcasecmp( $a->title, $b->title ); | |
} | |
} else { | |
return $b->relevance - $a->relevance; | |
} | |
} | |
return $b->priority - $a->priority; | |
} | |
/** | |
* usort() custom function, sort by priority > date ascending | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_rd_asc( $a, $b ) { | |
if ( $a->priority === $b->priority ) { | |
return strtotime( $a->date ) - strtotime( $b->date ); | |
} | |
return $b->priority - $a->priority; | |
} | |
/** | |
* usort() custom function, sort by priority > date descending | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_rd_desc( $a, $b ) { | |
if ( $a->priority === $b->priority ) { | |
return strtotime( $b->date ) - strtotime( $a->date ); | |
} | |
return $b->priority - $a->priority; | |
} | |
/** | |
* usort() custom function, sort by title descending | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_title_desc( $a, $b ) { | |
return strcasecmp( $b->title, $a->title ); | |
} | |
/** | |
* usort() custom function, sort by title ascending | |
* | |
* @param $a | |
* @param $b | |
* | |
* @return int | |
*/ | |
protected function compare_by_title_asc( $a, $b ) { | |
return strcasecmp( $a->title, $b->title ); | |
} | |
/** | |
* Builds the query from the parts | |
* | |
* @param $parts | |
* | |
* @return string query | |
*/ | |
protected function build_query( $parts ) { | |
$args = &$this->args; | |
$kw_logic = str_replace('EX', '', strtoupper( $args['keyword_logic'] ) ); | |
$kw_logic = $kw_logic != 'AND' && $kw_logic != 'OR' ? 'AND' : $kw_logic; | |
$r_parts = array(); // relevance parts | |
/*------------------------- Build like --------------------------*/ | |
$exact_query = ''; | |
$like_query_arr = array(); | |
foreach ( $parts as $k=>$part ) { | |
if ( $k == 0 ) | |
$exact_query = '(' . implode(' OR ', $part[0]) . ')'; | |
else | |
$like_query_arr[] = '(' . implode(' OR ', $part[0]) . ')'; | |
} | |
$like_query = implode(' ' . $kw_logic . ' ', $like_query_arr); | |
// When $exact query is empty, then surely $like_query must be empty too, see above | |
if ( $exact_query == '' ) { | |
$like_query = "(1)"; | |
} else { | |
// Both $like_query and $exact_query set | |
if ( $like_query != '' ) { | |
$like_query = "( $exact_query OR $like_query )"; | |
} else { | |
$like_query = "( $exact_query )"; | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
/*---------------------- Build relevance ------------------------*/ | |
foreach ( $parts as $part ) { | |
if ( isset($part[1]) && count($part[1]) > 0 ) | |
$r_parts = array_merge( $r_parts, $part[1] ); | |
} | |
$relevance = implode( ' + ', $r_parts ); | |
if ( $args['_post_use_relevance'] != 1 || $relevance == "" ) { | |
$relevance = "(1)"; | |
} else { | |
$relevance = "($relevance)"; | |
} | |
/*---------------------------------------------------------------*/ | |
if ( isset($this->remaining_limit) ) { | |
if ($this->limit_start != 0) | |
$limit = $this->limit_start . ", " . $this->remaining_limit; | |
else | |
$limit = $this->remaining_limit; | |
} else { | |
$limit = 10; | |
} | |
return str_replace( | |
array( "{relevance_query}", "{like_query}", "{remaining_limit}" ), | |
array( $relevance, $like_query, $limit ), | |
$this->query | |
); | |
} | |
/** | |
* Post-processes the results | |
* | |
* @return array of results | |
*/ | |
protected function post_process() { | |
$pageposts = is_array( $this->results ) ? $this->results : array(); | |
$s = $this->s; | |
$_s = $this->_s; | |
$args = $this->args; | |
do_action("asp_start_post_processing"); | |
// No post processing if the search data param is missing or explicitly set | |
if ( !isset($args['_sd']) || $args['_no_post_process'] ) { | |
$this->results = $pageposts; | |
return $pageposts; | |
} | |
$sd = $args['_sd']; | |
$searchId = $args['_sid']; | |
$com_options = wd_asp()->o['asp_compatibility']; | |
/*--------------------- For Image Parser -----------------------*/ | |
// Do not select the content field, if it is not used at all | |
$get_content = !( | |
( $sd['showdescription'] == 1 ) || | |
( $sd['resultstype'] == "isotopic" && $sd['i_ifnoimage'] == 'description' ) || | |
( $sd['resultstype'] == "polaroid" && ($sd['pifnoimage'] == 'descinstead' || $sd['pshowdesc'] == 1) ) | |
); | |
// Do not select excerpt if its not used at all | |
$get_excerpt = !( | |
$sd['primary_titlefield'] == 1 || | |
$sd['secondary_titlefield'] == 1 || | |
$sd['primary_descriptionfield'] == 1 || | |
$sd['secondary_descriptionfield'] == 1 | |
); | |
$image_settings = $sd['image_options']; | |
foreach ( $pageposts as $k => &$r ) { | |
// Attachment post-process uses this section, but it has a separate image parser, so skip that | |
if ( $r->post_type == 'attachment' ) | |
continue; | |
if ( $image_settings['show_images'] != 0 && | |
'' !== ($im = $this->getBFIimage( $r, $get_content, $get_excerpt )) | |
) { | |
if ( $image_settings['image_cropping'] == 0 ) { | |
$r->image = $im; | |
} else { | |
if ( strpos( $im, "mshots/v1" ) === false && strpos( $im, ".gif" ) === false ) { | |
$bfi_params = array( 'width' => $image_settings['image_width'], | |
'height' => $image_settings['image_height'], | |
'crop' => true | |
); | |
if ( w_isset_def( $image_settings['image_transparency'], 1 ) != 1 ) | |
$bfi_params['color'] = wpdreams_rgb2hex( $image_settings['image_bg_color'] ); | |
$r->image = bfi_thumb( $im, $bfi_params ); | |
} else { | |
$r->image = $im; | |
} | |
} | |
} | |
} | |
/*---------------------------------------------------------------*/ | |
// For non-ajax searches, this is the cut off, no other post-processing required | |
if ( !$args['_ajax_search'] ) { | |
$this->results = $pageposts; | |
return $pageposts; | |
} | |
// VC 4.6+ fix: Shortcodes are not loaded in ajax responses | |
// class_exists() is mandatory, some PHP versions fail | |
if ( class_exists("WPBMap") && method_exists("WPBMap", "addAllMappedShortcodes") ) | |
WPBMap::addAllMappedShortcodes(); | |
//remove the search shortcode properly | |
add_shortcode( 'wpdreams_ajaxsearchpro', array( $this, 'return_empty_string' ) ); | |
aspDebug::start( '--searchContent-posptrocess' ); | |
/* Images, title, desc */ | |
foreach ( $pageposts as $k => &$r ) { | |
if ( isset( $args['_switch_on_preprocess'] ) && is_multisite() ) { | |
switch_to_blog( $r->blogid ); | |
} | |
// ---- URL FIX for WooCommerce product variations | |
$wc_prod_var_o = null; // Reset for each loop | |
if ( $r->post_type == 'product_variation' && class_exists( 'WC_Product_Variation' ) ) { | |
$wc_prod_var_o = wc_get_product( $r->id ); | |
$r->link = $wc_prod_var_o->get_permalink(); | |
} else { | |
$r->link = get_permalink( $r->id ); | |
} | |
// Filter it though WPML | |
if ( $args['_wpml_lang'] != '') | |
$r->link = apply_filters( 'wpml_permalink', $r->link, $args['_wpml_lang'] ); | |
// If no image and defined, remove the result here, to perevent JS confusions | |
if ( empty($r->image) && $sd['resultstype'] == "isotopic" && $sd['i_ifnoimage'] == 'removeres' ) { | |
unset($pageposts[ $k ]); | |
continue; | |
} | |
/* Same for polaroid mode */ | |
if (empty($r->image) && isset($sd['resultstype']) && | |
$sd['resultstype'] == 'polaroid' && $sd['pifnoimage'] == 'removeres') { | |
unset($pageposts[$k]); | |
continue; | |
} | |
$_t_keys = array('primary_titlefield', 'secondary_titlefield'); | |
foreach ($_t_keys as $tk) { | |
$sd[$tk] = $sd[$tk] . ''; // Convert for the switch statement | |
if ( $sd[$tk] == '-1' ) continue; | |
switch($sd[$tk]) { | |
case '0': | |
$r->title = get_the_title($r->id); | |
break; | |
case '1': | |
if ( ASP_mb::strlen( $r->excerpt ) >= 200 ) { | |
$r->title = wd_substr_at_word( $r->excerpt, 200 ); | |
} else { | |
$r->title = $r->excerpt; | |
} | |
break; | |
case 'c__f': | |
if ( $sd[$tk.'_cf'] == '' ) { | |
$r->title = get_the_title( $r->id ); | |
} else { | |
$field_val = ASP_Helpers::getCFValue($sd[$tk.'_cf'], $r, $com_options['use_acf_getfield'], $args); | |
if ( $field_val != '' ) { | |
$r->title = wd_strip_tags_ws( $field_val, $sd['striptagsexclude'] ); | |
} else { | |
$r->title = get_the_title($r->id); | |
} | |
} | |
break; | |
default: | |
$r->title = get_the_title($r->id); | |
} | |
if ($r->title != "") break; | |
} | |
if ( !empty($sd['advtitlefield']) ) | |
$r->title = $this->adv_field( | |
array( | |
'main_field_slug' => 'titlefield', | |
'main_field_value'=> $r->title, | |
'r' => $r, | |
'field_pattern' => stripslashes( $sd['advtitlefield'] ) | |
), | |
$com_options['use_acf_getfield'] | |
); | |
if ( ! isset( $sd['striptagsexclude'] ) ) { | |
$sd['striptagsexclude'] = "<a><span>"; | |
} | |
$_t_keys = array('primary_descriptionfield', 'secondary_descriptionfield'); | |
$_content = ''; | |
foreach ($_t_keys as $tk) { | |
$sd[$tk] = $sd[$tk] . ''; // Convert for the switch statement | |
if ( $sd[$tk] == '-1' ) continue; | |
switch ($sd[$tk]) { | |
case '1': | |
if ( function_exists( 'qtranxf_use' ) && $args['_qtranslate_lang'] != "" ) { | |
$r->excerpt = qtranxf_use($args['_qtranslate_lang'], $r->excerpt, false); | |
} | |
$_content = $r->excerpt; | |
break; | |
case '2': | |
$_content = strip_tags( get_the_title( $r->id ), $sd['striptagsexclude'] ); | |
break; | |
case 'c__f': | |
if ( $sd[$tk.'_cf'] == '' ) { | |
$_content = ''; | |
} else { | |
$field_val = ASP_Helpers::getCFValue($sd[$tk.'_cf'], $r, $com_options['use_acf_getfield'], $args); | |
if ( $field_val != '' ) { | |
$_content = $field_val; | |
} else { | |
$_content = ''; | |
} | |
} | |
break; | |
default: //including option '0', alias content | |
if ( function_exists( 'qtranxf_use' ) && $args['_qtranslate_lang'] != "" ) { | |
$r->content = qtranxf_use($args['_qtranslate_lang'], $r->content, false); | |
} | |
// For product variations, do something special | |
if ( isset($wc_prod_var_o) ) { | |
$r->content = $wc_prod_var_o->get_description(); | |
if ( $r->content == '') { | |
$_pprod = wc_get_product($wc_prod_var_o->get_parent_id()); | |
$r->content = $_pprod->get_description(); | |
} | |
} | |
$_content = $r->content; | |
break; | |
} | |
// Deal with the shortcodes here, for more accuracy | |
if ( $sd['shortcode_op'] == "remove" ) { | |
if ( $_content != "" ) { | |
// Remove shortcodes, keep the content, really fast and effective method | |
$_content = preg_replace("~(?:\[/?)[^\]]+/?\]~su", '', $_content); | |
} | |
} else { | |
if ( $_content != "" ) { | |
$_content = apply_filters( 'the_content', $_content, $searchId ); | |
} | |
} | |
if ( $_content != '') break; | |
} | |
// Remove inline styles and scripts | |
$_content = preg_replace( array( | |
'#<script(.*?)>(.*?)</script>#is', | |
'#<style(.*?)>(.*?)</style>#is' | |
), '', $_content ); | |
$_content = wd_strip_tags_ws( $_content, $sd['striptagsexclude'] ); | |
// Get the words from around the search phrase, or just the description | |
if ( $sd['description_context'] == 1 && count( $_s ) > 0 && $s != '') { | |
// Try for an exact match | |
$_ex_content = $this->context_find( | |
$_content, $s, | |
floor($sd['descriptionlength'] / 6), | |
$sd['descriptionlength'], | |
$sd['description_context_depth'], | |
true | |
); | |
if ( $_ex_content === false ) { | |
// No exact match, go with the first keyword | |
$_content = $this->context_find( | |
$_content, $_s[0], | |
floor($sd['descriptionlength'] / 6), | |
$sd['descriptionlength'], | |
$sd['description_context_depth'] | |
); | |
} else { | |
$_content = $_ex_content; | |
} | |
} else if ( $_content != '' && ( ASP_mb::strlen( $_content ) > $sd['descriptionlength'] ) ) { | |
$_content = wd_substr_at_word($_content, $sd['descriptionlength']) . "..."; | |
} | |
$_content = wd_closetags( $_content ); | |
if ( !empty($sd['advdescriptionfield']) ) | |
$r->content = $this->adv_field( | |
array( | |
'main_field_slug' => 'descriptionfield', | |
'main_field_value'=> $_content, | |
'r' => $r, | |
'field_pattern' => stripslashes( $sd['advdescriptionfield'] ) | |
), | |
$com_options['use_acf_getfield'] | |
); | |
// --------------------------------- DATE ----------------------------------- | |
if ($sd["showdate"] == 1) { | |
$post_time = strtotime($r->date); | |
if ( $sd['custom_date'] == 1) { | |
$date_format = w_isset_def($sd['custom_date_format'], "Y-m-d H:i:s"); | |
} else { | |
$date_format = get_option('date_format', "Y-m-d") . " " . get_option('time_format', "H:i:s"); | |
} | |
$r->date = @date_i18n($date_format, $post_time); | |
} | |
// -------------------------------------------------------------------------- | |
} | |
aspDebug::stop( '--searchContent-posptrocess' ); | |
if ( isset( $args['_switch_on_preprocess'] ) && is_multisite() ) { | |
restore_current_blog(); | |
} | |
$this->results = $pageposts; | |
return $pageposts; | |
} | |
/** | |
* Fetches an image for BFI class | |
* | |
* @param $post StdClass post object | |
* @param $get_content bool to request the post content | |
* @param $get_excerpt bool to request the post excerpt | |
* @return string image URL | |
*/ | |
protected function getBFIimage( $post, $get_content = false, $get_excerpt = false ) { | |
if ( ! isset( $post->image ) || $post->image == null ) { | |
$args = $this->args; | |
if ( !isset($args['_sd']['image_options']) ) | |
return ""; | |
$sd = $args['_sd']; | |
$image_settings = $args['_sd']['image_options']; | |
if ( ! isset( $post->id ) ) { | |
return ""; | |
} | |
$im = ""; | |
for ( $i = 1; $i < 6; $i ++ ) { | |
switch ( $image_settings[ 'image_source' . $i ] ) { | |
case "featured": | |
$size = $image_settings['image_source_featured'] == "original" ? 'full' : $image_settings['image_source_featured']; | |
if ( $post->post_type == 'attachment' ) { | |
$imx = wp_get_attachment_image_src($post->id, $size, false); | |
} else { | |
$imx = wp_get_attachment_image_src( | |
get_post_thumbnail_id($post->id), $size, false | |
); | |
} | |
if ( !is_wp_error($imx) && $imx !== false && isset($imx[0]) ) | |
$im = $imx[0]; | |
break; | |
case "content": | |
$content = $get_content ? get_post_field('post_content', $post->id) : $post->content; | |
if ( $image_settings['apply_content_filter'] == 1 ) | |
$content = apply_filters('the_content', $content); | |
$im = asp_get_image_from_content( $content, $sd['image_parser_image_number'], $sd['image_parser_exclude_filenames'] ); | |
break; | |
case "excerpt": | |
$excerpt = $get_excerpt ? get_post_field('post_excerpt', $post->id) : $post->excerpt; | |
$im = asp_get_image_from_content( $excerpt, $sd['image_parser_image_number'], $sd['image_parser_exclude_filenames'] ); | |
break; | |
case "screenshot": | |
$im = 'https://s.wordpress.com/mshots/v1/' . urlencode( get_permalink( $post->id ) ) . | |
'?w=' . $image_settings['image_width'] . '&h=' . $image_settings['image_height']; | |
break; | |
case "post_format": | |
$format = get_post_format( $post->id ); | |
switch ($format) { | |
case "audio": | |
$im = ASP_URL_NP . "img/post_format/audio.png"; | |
break; | |
case "video": | |
$im = ASP_URL_NP . "img/post_format/video.png"; | |
break; | |
case "quote": | |
$im = ASP_URL_NP . "img/post_format/quote.png"; | |
break; | |
case "image": | |
$im = ASP_URL_NP . "img/post_format/image.png"; | |
break; | |
case "gallery": | |
$im = ASP_URL_NP . "img/post_format/gallery.png"; | |
break; | |
case "link": | |
$im = ASP_URL_NP . "img/post_format/link.png"; | |
break; | |
default: | |
$im = ASP_URL_NP . "img/post_format/default.png"; | |
break; | |
} | |
break; | |
case "custom": | |
if ( $image_settings['image_custom_field'] != "" ) { | |
$val = get_post_meta( $post->id, $image_settings['image_custom_field'], true ); | |
if ( $val != null && $val != "" ) { | |
if ( is_numeric($val) ) { | |
$im = wp_get_attachment_url( $val ); | |
} else { | |
$im = $val; | |
} | |
} | |
} | |
break; | |
case "default": | |
if ( $image_settings['image_default'] != "" ) { | |
$im = $image_settings['image_default']; | |
} | |
break; | |
default: | |
$im = ""; | |
break; | |
} | |
if ( $im != null && $im != '' ) { | |
break; | |
} | |
} | |
if ( !is_wp_error($im) ) | |
return $im; | |
return ''; | |
} else { | |
return $post->image; | |
} | |
} | |
/** | |
* Generates the final field, based on the advanced field pattern | |
* | |
* @uses ASP_Helpers::getCFValue() | |
* @uses shortcode_parse_atts() | |
* | |
* @param array $f_args Field related arguments | |
* @param boolean $use_acf If true, uses ACF get_field() function to get the meta | |
* @param boolean $empty_on_missing If true, returns an empty string if any of the fields is empty. | |
* | |
* @return string Final post title | |
*/ | |
protected function adv_field( $f_args, $use_acf = false, $empty_on_missing = false ) { | |
$args = &$this->args; | |
$specials = array('__id', '__title', '__content', '__link', '__url', '__image', '__date', '__author'); | |
$f_args = wp_parse_args($f_args, array( | |
'main_field_slug' => 'titlefield', // The 'slug', aka the original field name | |
'main_field_value'=> '', // The default field value | |
'r' => null, // Result object | |
'field_pattern' => '{titlefield}' // The field pattern | |
)); | |
$_f_args = $f_args; | |
if ( $f_args['field_pattern'] == '' ) { | |
return $f_args['field_value']; | |
} | |
$field_pattern = $f_args['field_pattern']; // Lets not make changes to arguments, shall we. | |
// Find conditional patterns, like [prefix {field} suffix} | |
preg_match_all( "/(\[.*?\])/", $field_pattern, $matches ); | |
if ( isset( $matches[0] ) && isset( $matches[1] ) && is_array( $matches[1] ) ) { | |
foreach ( $matches[1] as $fieldset ) { | |
// Pass on each section to this function again, the code will never get here | |
$_f_args['field_pattern'] = str_replace(array('[', ']'), '', $fieldset); | |
$processed_fieldset = $this->adv_field( | |
$_f_args, | |
$use_acf, | |
true | |
); | |
// Replace the original with the processed version, first occurrence, in case of duplicates | |
$field_pattern = ASP_Helpers::replaceFirst($fieldset, $processed_fieldset, $field_pattern); | |
} | |
} | |
preg_match_all( "/{(.*?)}/", $field_pattern, $matches ); | |
if ( isset( $matches[0] ) && isset( $matches[1] ) && is_array( $matches[1] ) ) { | |
foreach ( $matches[1] as $complete_field ) { | |
$field_args = shortcode_parse_atts($complete_field); | |
if ( is_array($field_args) && isset($field_args[0]) ) { | |
$field = array_shift($field_args); | |
} else { | |
continue; | |
} | |
if ( $field == $f_args['main_field_slug'] ) { | |
$field_pattern = str_replace( '{'.$complete_field.'}', $f_args['main_field_value'], $field_pattern ); | |
} else { | |
if ( in_array($field, $specials) ) { | |
$r = $f_args['r']; | |
$val = ''; | |
switch ($field) { | |
case '__id': | |
$val = isset($r->id) ? $r->id : ''; | |
break; | |
case '__title': | |
$val = isset($r->title) ? $r->title : ''; | |
break; | |
case '__content': | |
$val = isset($r->content) ? $r->content : ''; | |
break; | |
case '__link': | |
case '__url': | |
$val = isset($r->link) ? $r->link : ''; | |
break; | |
case '__image': | |
$val = isset($r->image) ? $r->image : ''; | |
break; | |
case '__date': | |
if ( isset($r->date) ) { | |
if ( isset($field_args['date_format']) ) { | |
return date_i18n($field_args['date_format'], strtotime($r->date)); | |
} | |
return $r->date; | |
} | |
return ''; | |
break; | |
case '__author': | |
$val = isset($r->author) && $r->author != '' ? $r->author : get_the_author_meta( 'display_name' , get_post_field ('post_author', $r->id)); | |
break; | |
} | |
} else if(strpos($field, '_taxonomy_') === 0 || strpos($field, '__tax_') === 0) { | |
$taxonomy = str_replace(array('_taxonomy_', '__tax_'), '', $field); | |
if ($taxonomy == '') | |
continue; | |
$count = isset($field_args['count']) ? $field_args['count'] + 0 : 5; | |
$count = $count == 0 ? 5 : $count; | |
$separator = isset($field_args['separator']) ? $field_args['separator']: ', '; | |
$orderby = isset($field_args['orderby']) ? $field_args['orderby']: 'name'; | |
$order = isset($field_args['order']) ? $field_args['order']: 'ASC'; | |
$exclude = isset($field_args['exclude']) ? '1, '.$field_args['exclude']: '1'; | |
$hide_empty = isset($field_args['hide_empty']) ? $field_args['hide_empty'] == 1 : true; | |
$hierarchical = isset($field_args['hierarchical']) ? $field_args['hierarchical'] == 1 : true; | |
$childless = isset($field_args['childless']) ? $field_args['childless'] == 1 : false; | |
$val = ASP_Helpers::getTermsList($taxonomy, $count, $separator, array( | |
'orderby' => $orderby, | |
'order' => $order, | |
'object_ids'=> $f_args['r']->id, | |
'exclude' => $exclude, | |
'hide_empty'=> $hide_empty, | |
'hierarchical' => $hierarchical, | |
'childless' => $childless | |
)); | |
} else if ( strpos($field, '_pods_') === 0 || strpos($field, '_pod_') === 0 ) { | |
// PODs field | |
$val = ASP_Helpers::getPODsValue($field, $f_args['r']); | |
} else if ( strpos($field, '__um_') === 0 ) { | |
// User Meta Field | |
$um_field = str_replace('__um_', '', $field); | |
$author = get_post_field( 'post_author', $f_args['r']->id ); | |
$val = ASP_Helpers::getUserCFValue($um_field, $author, $use_acf); | |
}else { | |
// Probably a custom field? | |
$val = ASP_Helpers::getCFValue($field, $f_args['r'], $use_acf, $args, $field_args); | |
} | |
// For the recursive call to break, if any of the fields is empty | |
if ( $empty_on_missing && $val == '') | |
return ''; | |
// value, field name, post object, field arguments | |
$val = apply_filters('asp_cpt_advanced_field_value', $val, $field, $f_args['r'], $f_args); | |
$field_pattern = str_replace( '{' . $complete_field . '}', $val, $field_pattern ); | |
} | |
} | |
} | |
return $field_pattern; | |
} | |
/** | |
* An empty function to override individual shortcodes, this must be public | |
* | |
* @return string | |
*/ | |
public function return_empty_string() { | |
return ""; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment