File: /home/icsla/public_html/wp-content/plugins/ajax-search-pro/includes/classes/Search/SearchIndex.php
<?php
/** @noinspection RegExpRedundantEscape */
namespace WPDRMS\ASP\Search;
use stdClass;
use WPDRMS\ASP\Misc\Priorities;
use WPDRMS\ASP\Utils\MB;
use WPDRMS\ASP\Utils\Str;
defined('ABSPATH') or die("You can't access this file directly.");
class SearchIndex extends SearchPostTypes {
/**
* @var array of query parts
*/
protected $parts = array();
/**
* @var array of custom field query parts
*/
protected $cf_parts = array();
/**
* @var array results from the index table
*/
protected $raw_results = array();
/**
* Content search function
*
* @return array|string
*/
protected function doSearch() {
global $wpdb;
global $q_config;
$current_blog_id = get_current_blog_id();
$args = &$this->args;
// Check if there is anything left to look for
if ( $args['_limit'] > 0 ) {
$limit = $args['_limit'];
} else {
if ( $args['_ajax_search'] )
$limit = $args['posts_limit'];
else
$limit = $args['posts_limit_override'];
}
if ( $limit <= 0 )
return array();
$sd = $args["_sd"] ?? array();
$kw_logic = $args['keyword_logic'];
$q_config['language'] = $args['_qtranslate_lang'];
$s = $this->s; // full keyword
$_s = $this->_s; // array of keywords
$sr = $this->sr; // full reversed keyword
$_sr = $this->_sr; // array of reversed keywords
$group_priority_select = $this->buildPgpQuery('asp_index.doc');
$group_priority_select = $group_priority_select . " AS group_priority,";
/**
* Determine if the priorities table should be used or not.
*/
$priority_select = Priorities::count() > 0 ? "
IFNULL((
SELECT
aspp.priority
FROM ".wd_asp()->db->table('priorities')." as aspp
WHERE aspp.post_id = asp_index.doc AND aspp.blog_id = " . get_current_blog_id() . "
), 100)
" : 100;
/*------------------------- Statuses ----------------------------*/
// Removed - it is already considered at index generation
/*---------------------------------------------------------------*/
/*----------------------- Gather Types --------------------------*/
/*
* @TODO: Cross-check with selected custom post types on the index table options panel, as if they match,
* this query is not needed at all!
*/
$page_q = "";
if ( $args['_exclude_page_parent_child'] != '' )
$page_q = " AND ( IF(asp_index.post_type <> 'page', 1,
EXISTS (
SELECT ID FROM $wpdb->posts xxp WHERE
xxp.ID = asp_index.doc AND
xxp.post_parent NOT IN (" . str_replace('|', ',', $args['_exclude_page_parent_child']) . ") AND
xxp.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']);
$post_types = "(asp_index.post_type IN ('$words') $page_q)";
}
/*---------------------------------------------------------------*/
$post_fields_query = '';
if ( !in_array('attachment', $args['post_type']) ) {
$exc_fields = array_diff(array('title', 'content', 'excerpt'), $args['post_fields']);
if ( count($exc_fields) > 0 ) {
$post_fields_arr = array_map(function ($field) {
return "asp_index.$field = 0";
}, $exc_fields);
$post_fields_query = 'AND (' . implode(' AND ', $post_fields_arr) . ') ';
}
}
// ------------------------ Categories/tags/taxonomies ----------------------
$term_query = $this->buildTermQuery("asp_index.doc", "asp_index.post_type");
// ---------------------------------------------------------------------
/*------------- Custom Fields with Custom selectors -------------*/
if ( count($args['post_type']) == 1 && in_array('attachment', $args['post_type']) && $args['attachments_cf_filters'] == 0 ) {
$cf_select = '(1)';
} else {
$cf_select = $this->buildCffQuery("asp_index.doc");
}
/*---------------------------------------------------------------*/
/*------------------------ Include id's -------------------------*/
if ( !empty($args['post_in']) ) {
$include_posts = " AND (asp_index.doc IN (" . (is_array($args['post_in']) ? implode(",", $args['post_in']) : $args['post_in']) . "))";
} else {
$include_posts = "";
}
/*---------------------------------------------------------------*/
/*------------------------ Exclude id's -------------------------*/
if ( !empty($args['post_not_in']) ) {
$exclude_posts = " AND (asp_index.doc 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 (asp_index.doc NOT IN (" . implode(",", $args['post_not_in2']) . "))";
/*---------------------------------------------------------------*/
/*------------------------ Term JOIN -------------------------*/
// No need, this should be indexed...
/*---------------------------------------------------------------*/
/*------------------------- WPML filter -------------------------*/
$wpml_query = "";
if ( $args['_wpml_lang'] != "" ) {
global $sitepress;
$site_lang_selected = false;
if ( is_object($sitepress) && method_exists($sitepress, 'get_default_language') ) {
$site_lang_selected = $sitepress->get_default_language() == $args['_wpml_lang'];
}
$wpml_query = "asp_index.lang = '" . Str::escape($args['_wpml_lang']) . "'";
/**
* Imported or some custom post types might have missing translations for the site default language.
* If the user currently searches on the default language, empty translation string is allowed.
*/
if ( $site_lang_selected )
$wpml_query .= " OR asp_index.lang = ''";
$wpml_query = " AND (" . $wpml_query . ")";
}
/*---------------------------------------------------------------*/
/*----------------------- POLYLANG filter -----------------------*/
$polylang_query = "";
if ( $args['_polylang_lang'] != "" && $wpml_query == "" ) {
$polylang_query = " AND (asp_index.lang = '" . Str::escape($args['_polylang_lang']) . "')";
}
/*---------------------------------------------------------------*/
/*----------------------- Date filtering ------------------------*/
$date_query = "";
$date_query_parts = $this->get_date_query_parts("ddpp");
if ( count($date_query_parts) > 0 )
$date_query = " AND EXISTS( SELECT 1 FROM $wpdb->posts as ddpp WHERE " . implode(" AND ", $date_query_parts) . " AND ddpp.ID = asp_index.doc) ";
/*---------------------------------------------------------------*/
/*---------------------- Blog switching? ------------------------*/
$blog_query = '';
if ( is_multisite() ) {
if ( isset($args['_switch_on_preprocess']) )
$blog_query = "AND asp_index.blogid IN (" . implode(',', $args['_selected_blogs']) . ")";
else
$blog_query = "AND asp_index.blogid = " . $current_blog_id;
}
/*---------------------------------------------------------------*/
/*---------------------- Relevance Values -----------------------*/
$rel_val_title = w_isset_def($sd["it_title_weight"], 10);
$rel_val_content = w_isset_def($sd["it_content_weight"], 8);
$rel_val_excerpt = w_isset_def($sd["it_excerpt_weight"], 5);
$rel_val_permalinks = w_isset_def($sd["it_terms_weight"], 3);
$rel_val_terms = w_isset_def($sd["it_terms_weight"], 3);
$rel_val_cf = w_isset_def($sd["it_cf_weight"], 3);
$rel_val_author = w_isset_def($sd["it_author_weight"], 2);
/*---------------------------------------------------------------*/
/*------------------- 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 asp_index.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=asp_index.doc
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=asp_index.doc
LIMIT 1
) ";
}
/*---------------------------------------------------------------*/
/*--------------------- Post parent IDs -------------------------*/
$post_parents_select = '';
if ( count($args['post_parent']) > 0 ) {
$post_parents_select = "AND EXISTS (
SELECT 1 FROM $wpdb->posts
WHERE
$wpdb->posts.ID = asp_index.doc AND
$wpdb->posts.post_parent IN (" . implode(',', $args['post_parent']) . ")
) ";
}
/*---------------------------------------------------------------*/
/*--------------------- Post parent IDs -------------------------*/
$post_parents_exclude_select = '';
if ( count($args['post_parent_exclude']) > 0 ) {
$post_parents_exclude_select = "AND NOT EXISTS (
SELECT 1 FROM $wpdb->posts
WHERE
$wpdb->posts.ID = asp_index.doc AND
$wpdb->posts.post_parent IN (" . implode(',', $args['post_parent_exclude']) . ")
) ";
}
/*---------------------------------------------------------------*/
/*----------------------- Exclude USER id -----------------------*/
$user_select = "0";
$user_join = "";
$user_query = "";
if ( isset($args['post_user_filter']['include']) ) {
if ( !in_array(-1, $args['post_user_filter']['include']) )
$user_query = "AND pj.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 pj.post_author NOT IN (" . implode(", ", $args['post_user_filter']['exclude']) . ") ";
else
return array();
}
if ( $user_query != "" ) {
$user_select = "pj.post_author";
$user_join = "LEFT JOIN $wpdb->posts pj ON pj.ID = asp_index.doc";
}
/*---------------------------------------------------------------*/
/*-------------- Additional Query parts by Filters --------------*/
/**
* Use these filters to add additional parts to the select, join or where
* parts of the search query.
*/
$add_select = apply_filters('asp_it_query_add_select', '', $args, $s, $_s);
$add_join = apply_filters('asp_it_query_add_join', '', $args, $s, $_s);
$add_where = apply_filters('asp_it_query_add_where', '', $args, $s, $_s);
/*---------------------------------------------------------------*/
/**
* 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];
$this->query = "
SELECT
{args_fields}
$add_select
asp_index.doc as id,
asp_index.blogid as blogid,
'pagepost' as content_type,
$priority_select AS priority,
$p_type_priority AS p_type_priority,
$user_select AS post_author,
$custom_field_selectp as customfp,
$custom_field_selects as customfs,
'' as date,
0 as menu_order,
'' as title,
asp_index.post_type AS post_type,
$group_priority_select
(
asp_index.title * $rel_val_title * {rmod} +
asp_index.content * $rel_val_content * {rmod} +
asp_index.excerpt * $rel_val_excerpt * {rmod} +
asp_index.comment * $rel_val_terms * {rmod} +
asp_index.link * $rel_val_permalinks * {rmod} +
asp_index.tag * $rel_val_terms * {rmod} +
asp_index.customfield * $rel_val_cf * {rmod} +
asp_index.author * $rel_val_author * {rmod}
) AS relevance
FROM
".wd_asp()->db->table('index')." as asp_index
$user_join
$add_join
{args_join}
WHERE
({like_query})
AND $post_types
$blog_query
$wpml_query
$polylang_query
$term_query
$user_query
AND $cf_select
$exclude_posts
$include_posts
$post_parents_select
$post_parents_exclude_select
$date_query
$post_fields_query
$add_where
{args_where}
LIMIT {limit}";
// Place the argument query fields
if ( isset($args['cpt_query']) && is_array($args['cpt_query']) ) {
$_mod_q = $args['cpt_query'];
foreach ($_mod_q as &$qv) {
$qv = str_replace($wpdb->posts . '.ID', 'asp_index.doc', $qv);
}
$this->query = str_replace(
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}'),
array($_mod_q['fields'], $_mod_q['join'], $_mod_q['where'], $_mod_q['orderby']),
$this->query
);
} else {
$this->query = str_replace(
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}'),
'',
$this->query
);
}
$queries = array();
$results_arr = array();
//$words = $options['set_exactonly'] == 1 ? array($s) : $_s;
$words = $_s;
if ( $kw_logic == "orex" ) {
$rmod = 1;
$like_query = "(asp_index.term = '" . implode("' OR asp_index.term = '", $words) . "') AND asp_index.term_reverse <> ''";
$queries[] = str_replace(array('{like_query}', '{rmod}', '{limit}'), array($like_query, $rmod, $this->getPoolSize()), $this->query);
} else if ( $kw_logic == "andex" ) {
foreach ($words as $wk => $word) {
$rmod = 10 - ($wk * 8) < 1 ? 1 : 10 - ($wk * 8);
$like_query = "asp_index.term = '$word' AND asp_index.term_reverse <> ''";
$queries[] = str_replace(array('{like_query}', '{rmod}', '{limit}'), array($like_query, $rmod, $this->getPoolSize($word)), $this->query);
}
} else {
foreach ($words as $wk => $word) {
$rmod = 10 - ($wk * 8) < 1 ? 1 : 10 - ($wk * 8);
$like_query = "asp_index.term LIKE '" . $word . "%' AND asp_index.term_reverse <> ''";
$queries[] = str_replace(array('{like_query}', '{rmod}', '{limit}'), array($like_query, $rmod, $this->getPoolSize($word)), $this->query);
$like_query = "asp_index.term_reverse LIKE '" . ($_sr[$wk] ?? $sr) . "%' AND asp_index.term_reverse <> ''";
$queries[] = str_replace(array('{like_query}', '{rmod}', '{limit}'), array($like_query, intval($rmod / 2), $this->getPoolSize($word)), $this->query);
}
}
/*---------------------- Post CPT IDs ---------------------------*/
if ( in_array("ids", $args['post_fields']) ) {
$queries[] = str_replace(array('{like_query}', '{rmod}', '{limit}'), array("asp_index.doc LIKE '$s'", 1, $this->getPoolSize()), $this->query);
}
/*---------------------------------------------------------------*/
/*----------------------- Improved title and custom field search query ------------------*/
if ( in_array('title', $args['post_fields']) && (MB::strlen($s) > 2 || count($_s) == 0) ) {
$rmod = 1000;
// Re-calculate the limit to slice the results to the real size
if ( $args['_limit'] > 0 ) {
$limit = $args['_limit'];
} else {
if ( $args['_ajax_search'] )
$limit = $args['posts_limit'];
else
$limit = $args['posts_limit_override'];
}
if ( !$args['_ajax_search'] || $args['_show_more_results'] )
$limit = $limit * $this->remaining_limit_mod;
// Exact title query
$single_delimiter = count($_s) == 1 ? '___' : '';
$title_query = str_replace(
array('{like_query}', '{rmod}', '{limit}', 'asp_index.doc as id'),
array("(asp_index.term_reverse = '' AND asp_index.term LIKE '" . $s . $single_delimiter . "')", $rmod * 2, $limit, 'DISTINCT asp_index.doc as id'),
$this->query);
$results_arr[99998] = $wpdb->get_results($title_query);
// We reached the required limit, reset the other queries, as we don't need them
if ( count($results_arr[99998]) >= $limit ) {
$queries = array();
} else {
// partial query on "OR" and "AND"
if ( $kw_logic == "or" || $kw_logic == "and" ) {
$title_query = str_replace(
array('{like_query}', '{rmod}', '{limit}', 'asp_index.doc as id'),
array("(asp_index.term_reverse = '' AND asp_index.term LIKE '$s%')", $rmod, $limit, 'DISTINCT asp_index.doc as id'),
$this->query);
} else { // partial query (starting with) until the first keyword for OREX and ANDEX
$title_query = str_replace(
array('{like_query}', '{rmod}', '{limit}', 'asp_index.doc as id'),
array("(asp_index.term_reverse = '' AND asp_index.term LIKE '$s %')", $rmod, $limit, 'DISTINCT asp_index.doc as id'),
$this->query);
}
$results_arr[99999] = $wpdb->get_results($title_query);
// We reached the required limit, reset the other queries, as we don't need them
if ( count($results_arr[99999]) >= $limit )
$queries = array();
}
}
/*---------------------------------------------------------------*/
if ( count($queries) > 0 ) {
foreach ($queries as $k => $query) {
$query = apply_filters('asp_query_indextable', $query, $args, $args['_id'], $args['_ajax_search']);
$results_arr[$k] = $wpdb->get_results($query);
}
}
// Merge results depending on the logic
$results_arr = $this->mergeRawResults($results_arr, $kw_logic);
// We need to save this array with keys, will need the values later.
$this->raw_results = $results_arr;
// Do primary ordering here, because the results will slice, and we need the correct ones on the top
self::orderBy($results_arr, array(
'primary_ordering' => $args['post_primary_order'],
'primary_ordering_metatype' => $args['post_primary_order_metatype'],
'secondary_ordering' => $args['post_primary_order'] // PRIMARY ORDER ON PURPOSE!! -> Secondary does not apply when primary == secondary
));
// Re-calculate the limit to slice the results to the real size
if ( $args['_limit'] > 0 ) {
$limit = $args['_limit'];
} else {
if ( $args['_ajax_search'] )
$limit = $args['posts_limit'];
else
$limit = $args['posts_limit_override'];
}
$this->results_count = count($results_arr) > $limit * $this->remaining_limit_mod ? $limit * $this->remaining_limit_mod : count($results_arr);
// 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 > $limit ) {
$this->results_count = $limit;
}
// Apply new limit, but perserve the keys
$results_arr = array_slice($results_arr, $args['_call_num'] * $limit, $limit, true);
$this->results = $results_arr;
// Do some pre-processing
$this->preProcessResults();
// Were there items removed in the pre-process? In that case we need to lower the number of reported results.
/*if ( count($this->results) < count($results_arr) ) {
$this->results_count = $this->results_count - count($results_arr) + count($this->results);
}*/
$this->return_count = count($this->results);
return $this->results;
}
/**
* Merges the initial results array, creating a union or intersection.
*
* The function also adds up the relevance values of the results object.
*
* @param array $results_arr
* @param string $kw_logic keyword logic (and, or, andex, orex)
* @return array results array
*/
protected function mergeRawResults(array $results_arr, string $kw_logic = "or"): array {
// Store the improved title and cf results array temporarily
// We want these items to be the part of results, no matter what
$start_with_results = array();
$exact_results = array();
if ( isset($results_arr[99999]) ) {
$start_with_results = $results_arr[99999];
unset($results_arr[99999]);
}
if ( isset($results_arr[99998]) ) {
$exact_results = $results_arr[99998];
unset($results_arr[99998]);
}
/*
* When using the "and" logic, the $results_arr contains the results in [term, term_reverse]
* results format. These should not be intersected with each other, so this small code
* snippet here divides the results array by groups of 2, then it merges ever pair to one result.
* This way it turns into [term1, term1_reverse, term2 ...] array to [term1 union term1_reversed, ...]
*
* This is only neccessary with the "and" logic. Others work fine.
*/
if ( $kw_logic == 'and' ) {
$new_ra = array();
$i = 0;
$tmp_v = array();
foreach ($results_arr as $_v) {
if ( $i & 1 ) {
// odd, so merge the previous with the current
$new_ra[] = array_merge($tmp_v, $_v);
}
$tmp_v = $_v;
$i++;
}
$results_arr = $new_ra;
}
$final_results = array();
foreach ($results_arr as $results) {
foreach ($results as $r) {
if ( isset($final_results[$r->blogid . "x" . $r->id]) ) {
$final_results[$r->blogid . "x" . $r->id]->relevance += $r->relevance;
} else {
$final_results[$r->blogid . "x" . $r->id] = $r;
}
}
}
foreach ($start_with_results as $r) {
if ( isset($final_results[$r->blogid . "x" . $r->id]) ) {
$final_results[$r->blogid . "x" . $r->id]->relevance += $r->relevance;
} else {
$final_results[$r->blogid . "x" . $r->id] = $r;
}
}
foreach ($exact_results as $r) {
if ( isset($final_results[$r->blogid . "x" . $r->id]) ) {
$final_results[$r->blogid . "x" . $r->id]->relevance += $r->relevance;
} else {
$final_results[$r->blogid . "x" . $r->id] = $r;
}
}
if ( $kw_logic == 'or' || $kw_logic == 'orex' )
return $final_results;
foreach ($results_arr as $results) {
/**
* array_merge($results, $title_results) - why?
* -> Because here is an AND or ANDEX logic, so array intersections will be returned.
* All elements in the $title_results array not necessarily are a union of subset of each $results array.
* To make sure that the elements of $title_results are indeed used, merge it with the actual $results
* array. The $final_results at the end will contain all items from $title_results at all times.
*/
$final_results = array_uintersect($final_results, array_merge($results, $start_with_results, $exact_results), array($this, 'compareResults'));
}
return $final_results;
}
public function getPoolSize($s = false) {
$args = $this->args;
$len = MB::strlen($s);
if ( $s === false ) {
$pool_size = $args['it_pool_size_rest'];
} else if ( $len <= 1 ) {
$pool_size = $args['it_pool_size_one'];
} else if ( $len == 2 ) {
$pool_size = $args['it_pool_size_two'];
} else if ( $len == 3 ) {
$pool_size = $args['it_pool_size_three'];
} else {
$pool_size = $args['it_pool_size_rest'];
}
return $pool_size < 100 ? 100 : $pool_size;
}
/**
* A custom comparison function for results intersection
*
* @param $a
* @param $b
*
* @return mixed
*/
protected function compareResults($a, $b) {
if ( $a->blogid === $b->blogid )
return $b->id - $a->id;
// For different blogids return difference
return $b->blogid - $a->blogid;
}
private function preProcessResults() {
// No results, save some resources
if ( count($this->results) == 0 ) {
return;
}
$pageposts = array();
$post_ids = array();
$the_posts = array();
$args = $this->args;
$sd = $args["_sd"] ?? array();
if ( $args['_ajax_search'] ) {
$start = 0;
$end = count($this->results);
} else {
/**
* Offset =>
* Positive -> Number of Index Table results displayed up until the current page
* Negative -> (abs) Number of other result types displayed up until (and including) the current page
*/
$offset = ( ( $args['page'] - 1 ) * $args['posts_per_page'] ) - $args['global_found_posts'];
$start = $offset < 0 ? 0 : $offset;
$end = $start + $args['posts_per_page'] + ($offset < 0 ? $offset : 0);
$end = $end > count($this->results) ? count($this->results) : $end;
}
$this->start_offset = $start;
/**
* Do not use a for loop here, as the $this->results does not have numeric keys
*/
$k = 0;
foreach ( $this->results as $r ) {
if ( $k >= $start && $k < $end ) {
$post_ids[$r->blogid][] = $r->id;
}
if ( $k >= $end ) {
break;
}
$k++;
}
// Get the post IDs
/*for ( $k=$start; $k<$end; $k++ ) {
$post_ids[$this->results[$k]->blogid][] = $this->results[$k]->id;
}*/
foreach ($post_ids as $blogid => $the_ids) {
if ( isset($args['_switch_on_preprocess']) && is_multisite() )
switch_to_blog($blogid);
$pargs = array(
'post__in' => $the_ids,
// DO NOT use orderby=post__in, causes problems
'posts_per_page' => -1,
'post_status' => 'any',
// WARNING: Do NOT use "any" as post_type, it will not work!!!
'post_type' => $args['_exclude_page_parent_child'] != '' ?
array_merge($args['post_type'], array('page')) : $args['post_type']
);
/**
* Polylang workaround
* - Force any language, as the correct items are already returned by the index
* table engine.
* url: https://polylang.pro/doc/developpers-how-to/#all
*/
if ( function_exists('pll_the_languages') ) {
$pargs['lang'] = '';
}
$get_posts = get_posts($pargs);
foreach ($get_posts as $gv) {
/** @noinspection PhpUndefinedFieldInspection */
$gv->blogid = $blogid;
}
// Resort by ID, because orderby=post__in causes issues in some cases
$sorted_get_posts = array();
foreach ( $the_ids as $id ) {
foreach ($get_posts as $gp) {
if ( $gp->ID == $id ) {
$sorted_get_posts[] = $gp;
break;
}
}
}
$the_posts = array_merge($the_posts, $sorted_get_posts);
}
if ( isset($args['_switch_on_preprocess']) && is_multisite() )
restore_current_blog();
// Merge the posts with the raw results to a new array
foreach ($the_posts as $r) {
$new_result = new stdClass();
$new_result->id = w_isset_def($r->ID, null);
$new_result->blogid = $r->blogid;
$new_result->title = w_isset_def($r->post_title, null);
$new_result->post_title = $new_result->title;
$new_result->content = w_isset_def($r->post_content, null);
$new_result->excerpt = w_isset_def($r->post_excerpt, null);
$new_result->image = null;
if ( isset($sd) && $sd['showauthor'] == 1 ) {
$post_user = get_user_by("id", $r->post_author);
if ( $post_user !== false ) {
if ( $sd['author_field'] == "display_name" )
$new_result->author = $post_user->data->display_name;
else
$new_result->author = $post_user->data->user_login;
} else {
$new_result->author = null;
}
}
$new_result->date = w_isset_def($r->post_date, null);
$new_result->post_date = $new_result->date;
$new_result->menu_order = w_isset_def($r->menu_order, 0);
// Get the relevance and priority values
$new_result->relevance = (int)$this->raw_results[$new_result->blogid . "x" . $new_result->id]->relevance;
$new_result->priority = (int)$this->raw_results[$new_result->blogid . "x" . $new_result->id]->priority;
$new_result->group_priority = (int)$this->raw_results[$new_result->blogid . "x" . $new_result->id]->group_priority;
$new_result->p_type_priority = (int)$this->raw_results[$new_result->blogid . "x" . $new_result->id]->p_type_priority;
$new_result->post_type = $this->raw_results[$new_result->blogid . "x" . $new_result->id]->post_type;
if ( isset($this->raw_results[$new_result->blogid . "x" . $new_result->id]->average_rating) )
$new_result->average_rating = (float)$this->raw_results[$new_result->blogid . "x" . $new_result->id]->average_rating;
if ( isset($this->raw_results[$new_result->blogid . "x" . $new_result->id]->customfp) )
$new_result->customfp = $this->raw_results[$new_result->blogid . "x" . $new_result->id]->customfp;
if ( isset($this->raw_results[$new_result->blogid . "x" . $new_result->id]->customfs) )
$new_result->customfs = $this->raw_results[$new_result->blogid . "x" . $new_result->id]->customfs;
$new_result->content_type = "pagepost";
$new_result->g_content_type = "post_page_cpt";
$pageposts[] = $new_result;
}
self::orderBy($pageposts, array(
'primary_ordering' => $args['post_primary_order'],
'primary_ordering_metatype' => $args['post_primary_order_metatype'],
'secondary_ordering' => $args['post_secondary_order'],
'secondary_ordering_metatype' => $args['post_secondary_order_metatype']
));
$this->results = $pageposts;
}
}