| Server IP : 68.183.124.220 / Your IP : 216.73.216.141 Web Server : Apache/2.4.18 (Ubuntu) System : Linux Sandbox-A 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : gavin ( 1000) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/wp-content/plugins/ajax-search-lite/includes/classes/search/ |
Upload File : |
<?php
/* Prevent direct access */
defined( 'ABSPATH' ) or die( "You can't access this file directly." );
if ( ! class_exists( 'wpdreams_searchContent' ) ) {
class wpdreams_searchContent extends wpdreams_search {
private $remaining_limit;
/**
* @var array of query parts
*/
private $parts = array();
protected function do_search() {
global $wpdb;
global $q_config;
$options = $this->options;
$sd = $this->searchData;
$types = array();
//$post_types = "";
$term_query = "(1)";
//$post_statuses = "";
//$term_join = "";
$postmeta_join = "";
$kw_logic = strtolower( $sd['keyword_logic'] );
// Prefixes and suffixes
$pre_field = $this->pre_field;
$suf_field = $this->suf_field;
$pre_like = $this->pre_like;
$suf_like = $this->suf_like;
$s = $this->s; // full keyword
$_s = $this->_s; // array of keywords
$wcl = '%'; // Wildcard Left
$wcr = '%'; // Wildcard right
if ( $options['set_exactonly'] == 1 ) {
if ( $sd['exact_match_location'] == 'start' )
$wcl = '';
else if ( $sd['exact_match_location'] == 'end' )
$wcr = '';
}
if ( isset($options['non_ajax_search']) )
$this->remaining_limit = 99999; // since it's not adjustable, make it irreally high
else
$this->remaining_limit = $sd['maxresults'];
$q_config['language'] = $options['qtranslate_lang'];
/*------------------------- Statuses ----------------------------*/
$post_statuses_arr = explode(',', str_replace(' ', '', w_isset_def($sd['post_status'], 'publish')) );
// Do not allow private posts for non-editors
if ( !current_user_can('read_private_posts') )
$post_statuses_arr = array_diff($post_statuses_arr, array('private'));
$post_statuses = "'".implode( "','", $post_statuses_arr )."'";
$post_statuses = "( $wpdb->posts.post_status IN ($post_statuses) )";
/*---------------------------------------------------------------*/
/*----------------------- Gather Types --------------------------*/
if ($options['set_inposts'] == 1)
$types[] = "post";
if ($options['set_inpages'])
$types[] = "page";
if (isset($options['customset']) && count($options['customset']) > 0)
$types = array_merge($types, $options['customset']);
if (count($types) < 1) {
return '';
} else {
$words = implode("','", $types);
if ( in_array('product_variation', $types) && class_exists('WooCommerce') ) {
$_post_types = $types;
$_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('publish') )
) $or_ptypes
))";
} else {
$post_types = "( $wpdb->posts.post_type IN ('$words') )";
}
}
/*---------------------------------------------------------------*/
/*------------- Custom Fields with Custom selectors -------------*/
$cf_select = '';
if ( $sd['woo_exclude_outofstock'] == 1 ) {
$cf_select = $this->build_cff_query($wpdb->posts . ".ID", array(
'post_meta_filter' => array(
array(
'key' => '_stock_status',
'value' => 'instock',
'operator' => 'ELIKE'
)
)
));
$cf_select = $cf_select != '' ? ' AND ' . $cf_select : '';
}
/*---------------------------------------------------------------*/
$words = $options['set_exactonly'] == 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 ( $options['set_exactonly'] == 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 = $options['set_exactonly'] == 1 || ( count($words) > 1 && $k == 0 && ($kw_logic == 'or' || $kw_logic == 'and') );
/*----------------------- Title query ---------------------------*/
if ( $options['set_intitle'] ) {
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 ( $options['set_incontent'] ) {
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 ( $sd['search_in_permalinks'] ) {
$parts[] = "( " . $pre_field . $wpdb->posts . ".post_name" . $suf_field . " LIKE $pre_like'$wcl" . $word . "$wcr'$suf_like )";
}
/*---------------------------------------------------------------*/
/*---------------------- Excerpt query --------------------------*/
if ($options['set_inexcerpt']) {
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 ($options['searchinterms']) {
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 --------------------------*/
$selected_customfields = isset( $sd['selected-customfields'] ) ? $sd['selected-customfields'] : array();
if ( $sd['search_all_cf'] == 1 )
$selected_customfields = array("all");
if ( is_array($selected_customfields) && count($selected_customfields) > 0 ) {
$postmeta_join = "LEFT JOIN $wpdb->postmeta ON $wpdb->postmeta.post_id = $wpdb->posts.ID";
foreach ( $selected_customfields as $cfield ) {
$key_part = $sd['search_all_cf'] == 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 ( $sd['search_in_ids'] )
$parts[] = "($wpdb->posts.ID LIKE '$word')";
/*---------------------------------------------------------------*/
$this->parts[] = array( $parts, $relevance_parts );
$relevance_added = true;
}
// ------------------------ Categories/taxonomies ----------------------
if ( ! isset( $options['categoryset'] ) || $options['categoryset'] == "" ) {
$options['categoryset'] = array();
}
if ( ! isset( $options['termset'] ) || $options['termset'] == "" ) {
$options['termset'] = array();
}
$term_logic = 'and';
$exclude_categories = array();
$sd['selected-exsearchincategories'] = w_isset_def( $sd['selected-exsearchincategories'], array() );
$sd['selected-excludecategories'] = w_isset_def( $sd['selected-excludecategories'], array() );
// New solution
if ( count( $sd['selected-exsearchincategories'] ) > 0 ||
count( $sd['selected-excludecategories'] ) > 0 ||
count( $options['categoryset'] ) > 0 ||
$sd['showsearchincategories'] == 1
) {
// If the category settings are invisible, ignore the excluded frontend categories, reset to empty array
if ( $sd['showsearchincategories'] == 0 ) {
$sd['selected-exsearchincategories'] = array();
}
$_all_cat = get_terms( 'category', array( 'fields' => 'ids' ) );
$_needed_cat = array_diff( $_all_cat, $sd['selected-exsearchincategories'] );
$_needed_cat = ! is_array( $_needed_cat ) ? array() : $_needed_cat;
// I am pretty sure this is where the devil is born
/*
AND -> Posts NOT in an array of term ids
OR -> Posts in an array of term ids
*/
if ( $sd['showsearchincategories'] == 1 ) // If the settings is visible, count for the options
{
$exclude_categories = array_diff( array_merge( $_needed_cat, $sd['selected-excludecategories'] ), $options['categoryset'] );
} else // ..if the settings is not visible, then only the excluded categories count
{
$exclude_categories = $sd['selected-excludecategories'];
}
}
$exclude_terms = array();
/*if (w_isset_def($sd['exclude_term_ids'], "") != "") {
$exclude_terms = explode( ",", str_replace( array("\r", "\n"), '', $sd['exclude_term_ids'] ) );
}*/
$all_terms = array_unique( array_merge( $exclude_categories, $exclude_terms ) );
/**
* New method
*
* This is way more efficient, despite it looks more complicated.
* Multiple sub-select is not an issue, since the query can use PRIMARY keys as indexes
*/
if ( count( $all_terms ) > 0 ) {
$words = implode( ',', $all_terms );
// 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 category)
if ( $term_logic == 'and' ) {
$empty_term_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 = 'category')
WHERE
xt.object_id = $wpdb->posts.ID
) OR ";
$term_query = " (
$empty_term_query
$wpdb->posts.ID 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 = 'category')
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 = 'category')
WHERE tts.term_id IN ($words)
)
)
)";
} else {
$term_query = "( $wpdb->posts.ID IN ( SELECT DISTINCT(tr.object_id) FROM wp_term_relationships AS tr WHERE tr.term_taxonomy_id IN ($words) ) )";
}
}
/*------------------- WooCommerce Visibility --------------------*/
$woo_visibility_query = '';
if ( class_exists('WooCommerce') && $sd['exclude_woo_hidden'] == 1 ) {
// Check if this is version > 3.0
if ( asp_woo_version_check('3.0') ) {
$_t = get_terms(array(
'slug' => array('exclude-from-search'),
'hide_empty' => 0,
'fields' => 'ids'
));
if ( !is_wp_error($_t) && count($_t) > 0) {
$woo_visibility_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 = 'product_visibility')
WHERE
xt.object_id = $wpdb->posts.ID
) OR ";
$woo_visibility_query = " AND (
$woo_visibility_query
$wpdb->posts.ID 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 = 'product_visibility')
WHERE
tt.term_id NOT IN (".implode(', ', $_t).")
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 = 'product_visibility')
WHERE tts.term_id IN (".implode(', ', $_t).")
)
)
)";
}
} else {
// Fallback to < 3.0
$qry = "( $wpdb->postmeta.meta_value IN ('visible', 'search') )";
$woo_visibility_query .= "
AND ((
SELECT IF(meta_key IS NULL, 1, IF($qry, COUNT(post_id), 0))
FROM $wpdb->postmeta
WHERE $wpdb->postmeta.post_id = $wpdb->posts.ID AND $wpdb->postmeta.meta_key='_visibility'
) >= 1)
";
}
}
/*---------------------------------------------------------------*/
/*------------------------ Exclude id's -------------------------*/
if ( isset( $sd['excludeposts'] ) && $sd['excludeposts'] != "" ) {
$exclude_post_ids = array_unique(
explode(',', str_replace(' ', '', $sd['excludeposts']))
);
foreach ( $exclude_post_ids as $k=>$v ) {
if ( $v == '' ) {
unset($exclude_post_ids[$k]);
}
}
if ( count($exclude_post_ids) > 0 )
$exclude_posts = " AND ($wpdb->posts.ID NOT IN (" . implode(',', $exclude_post_ids) . "))";
} else {
$exclude_posts = "";
}
/*---------------------------------------------------------------*/
/*------------------------ Term JOIN -------------------------*/
// If the search in terms is not active, we don't need this unnecessary big join
$term_join = "";
if ( $options['searchinterms'] ) {
$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";
}
/*---------------------------------------------------------------*/
/*------------------------- Build like --------------------------*/
/*$like_query = implode( ' OR ', $parts );
if ( $like_query == "" ) {
$like_query = "(1)";
} else {
$like_query = "($like_query)";
}*/
/*---------------------------------------------------------------*/
/*---------------------- Build relevance ------------------------*/
/*$relevance = implode( ' + ', $relevance_parts );
if ( $relevance == "" ) {
$relevance = "(1)";
} else {
$relevance = "($relevance)";
}*/
/*---------------------------------------------------------------*/
/*------------------------- WPML filter -------------------------*/
$wpml_query = "(1)";
if ( isset( $options['wpml_lang'] )
&& w_isset_def( $sd['wpml_compatibility'], 1 ) == 1
) {
global $sitepress;
$site_lang_selected = false;
$wpml_post_types_arr = array();
foreach ($types 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() == $options['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', $types) ) {
$_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->base_prefix . "icl_translations as wpml
WHERE
$_wpml_query_id_field = wpml.element_id AND
wpml.language_code = '" . ASL_Helpers::escape( $options['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->base_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 (isset( $options['polylang_lang'] ) &&
$options['polylang_lang'] != "" &&
$sd['polylang_compatibility'] == 1
) {
$languages = get_terms('language', array(
'hide_empty' => false,
'fields' => 'ids',
'orderby' => 'term_group',
'slug' => $options['polylang_lang'])
);
if ( !empty($languages) && !is_wp_error($languages) && isset($languages[0]) ) {
if ( in_array('product_variation', $types) && 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]
) )";
}
}
/*---------------------------------------------------------------*/
/*--------------------- Other Query stuff -----------------------*/
// If the content is hidden, why select it..
if ($sd['showdescription'] == 0)
$select_content = "''";
else
$select_content = $wpdb->posts. ".post_content";
// Dont select excerpt if its not used at all
$select_excerpt = (
w_isset_def($sd['titlefield'], 0) == 1 ||
w_isset_def($sd['descriptionfield'], 0) == 1 ||
wd_in_array_r('excerpt', $this->imageSettings)
) ? $wpdb->posts. ".post_excerpt" : "''";
/*---------------------------------------------------------------*/
$querystr = "
SELECT
{args_fields}
$wpdb->posts.post_title as title,
$wpdb->posts.ID as id,
$wpdb->posts.post_date as date,
$select_content as content,
$select_excerpt as excerpt,
'pagepost' as content_type,
(SELECT
$wpdb->users.display_name as author
FROM $wpdb->users
WHERE $wpdb->users.ID = $wpdb->posts.post_author
) as author,
'' as ttid,
$wpdb->posts.post_type as post_type,
{relevance_query} as relevance
FROM $wpdb->posts
$postmeta_join
$term_join
{args_join}
WHERE
$post_types
$woo_visibility_query
$cf_select
AND $post_statuses
AND $term_query
AND {like_query}
$exclude_posts
AND ( $wpml_query )
$polylang_query
{args_where}
GROUP BY
{args_groupby} $wpdb->posts.ID
ORDER BY
{args_orderby} ".$sd['orderby_primary'].", ".$sd['orderby_secondary'].", id DESC
LIMIT " . $this->remaining_limit;
$_qargs = array(
'fields' => '',
'join' => '',
'where' => '',
'orderby' => '',
'groupby' => ''
);
$_qargs = apply_filters('asl_query_add_args', $_qargs, $sd, $options);
// Place the argument query fields
if ( is_array($_qargs) ) {
$querystr = str_replace(
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}', '{args_groupby}'),
array($_qargs['fields'], $_qargs['join'], $_qargs['where'], $_qargs['orderby'], $_qargs['groupby']),
$querystr
);
} else {
$querystr = str_replace(
array('{args_fields}', '{args_join}', '{args_where}', '{args_orderby}', '{args_groupby}'),
'',
$querystr
);
}
$querystr = $this->build_query( $this->parts, $querystr, array(
'keyword_logic' => $kw_logic,
'_post_use_relevance' => 1
));
$pageposts = $wpdb->get_results( $querystr, OBJECT );
wd_asl()->debug->pushData(
array(
"phrase" => $s,
"options" => $options,
"query" => $querystr,
"results" => count($pageposts)
),
"queries", false, true, false, 5
);
$this->results = $pageposts;
return $pageposts;
}
/**
* Builds the query from the parts
*
* @param $parts array LIKE and Relevance parts
* @param $query string the search query
* @param $argp array arguments passed
*
* @return string query
*/
protected function build_query( $parts, $query, $argp = array() ) {
$args = array_merge(array(
'keyword_logic' => 'OR',
'_post_use_relevance' => 1
), $argp);
$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, $this->limit_start) ) {
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 ),
$query
);
}
protected function build_cff_query( $post_id_field, $args ) {
global $wpdb;
$defaults = array(
'_post_meta_allow_null' => 1,
'_post_meta_logic' => 'AND',
'post_meta_filter' => array()
);
$args = wp_parse_args( $args, $defaults );
$parts = array();
$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) {
switch ($operator) {
case 'datetime =':
$current_part = "($wpdb->postmeta.meta_value BETWEEN '$posted 00:00:00' AND '$posted 23:59:59')";
break;
case 'datetime <>':
$current_part = "($wpdb->postmeta.meta_value NOT BETWEEN '$posted 00:00:00' AND '$posted 23:59:59')";
break;
case 'datetime <':
$current_part = "($wpdb->postmeta.meta_value < '$posted 00:00:00')";
break;
case 'datetime >':
$current_part = "($wpdb->postmeta.meta_value > '$posted 23:59:59')";
break;
default:
$current_part = "($wpdb->postmeta.meta_value < '$posted 00:00:00')";
break;
}
// Is this a special case of timestamp?
} else if (strpos($operator, "timestamp") === 0) {
switch ($operator) {
case 'timestamp =':
$current_part = "($wpdb->postmeta.meta_value BETWEEN $posted AND ".($posted + 86399).")";
break;
case 'timestamp <>':
$current_part = "($wpdb->postmeta.meta_value NOT BETWEEN $posted AND ".($posted + 86399).")";
break;
case 'timestamp <':
$current_part = "($wpdb->postmeta.meta_value < $posted)";
break;
case 'timestamp >':
$current_part = "($wpdb->postmeta.meta_value > ".($posted + 86399).")";
break;
default:
$current_part = "($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") {
if ($values != '') {
$values .= " $logic $wpdb->postmeta.meta_value $operator '" . $v . "'";
} else {
$values .= "$wpdb->postmeta.meta_value $operator '" . $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") {
$current_part = "($wpdb->postmeta.meta_value LIKE '$posted')";
// Numeric operations or problematic stuff left
} else {
$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 = "";
$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 ) {
$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
$field = $part[0]; // Field name
$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 ) . " )";
}
return $cf_select;
}
protected function post_process() {
$pageposts = is_array( $this->results ) ? $this->results : array();
$options = $this->options;
$sd = $this->searchData;
$s = $this->s;
$_s = $this->_s;
// No post processing is needed on non-ajax search
if ( isset($options['non_ajax_search']) ) {
$this->results = $pageposts;
return $pageposts;
}
$performance_options = get_option('asl_performance');
$comp_options = wd_asl()->o['asl_compatibility'];
/* Images, title, desc */
foreach ( $pageposts as $k => $v ) {
// Let's simplify things
$r = &$pageposts[ $k ];
// -------------------------- Woocommerce Fixes -----------------------------
// ---- URL FIX for WooCommerce product variations
$wc_prod_var_o = null; // Reset for each loop
if ( $r->post_type == 'product_variation' && function_exists('wc_get_product') ) {
$wc_prod_var_o = wc_get_product( $r->id );
$r->link = $wc_prod_var_o->get_permalink();
} else {
$r->link = get_permalink( $v->id );
}
// --------------------------------------------------------------------------
// Filter it though WPML
if ( isset( $options['wpml_lang'] )
&& w_isset_def( $sd['wpml_compatibility'], 1 ) == 1
)
$r->link = apply_filters( 'wpml_permalink', $r->link, ASL_Helpers::escape( $options['wpml_lang'] ) );
$image_settings = $sd['image_options'];
if ( $image_settings['show_images'] != 0 ) {
$im = $this->getBFIimage( $r );
if ( $im != '' && strpos( $im, "mshots/v1" ) === false && w_isset_def($performance_options['image_cropping'], 0) == 1 ) {
if ( w_isset_def( $image_settings['image_transparency'], 1 ) == 1 ) {
$bfi_params = array( 'width' => $image_settings['image_width'],
'height' => $image_settings['image_height'],
'crop' => true
);
} else {
$bfi_params = array( 'width' => $image_settings['image_width'],
'height' => $image_settings['image_height'],
'crop' => true,
'color' => wpdreams_rgb2hex( $image_settings['image_bg_color'] )
);
}
$r->image = bfi_thumb( $im, $bfi_params );
} else {
$r->image = $im;
}
}
switch($sd['titlefield']) {
case '0':
if ( isset($wc_prod_var_o) ) {
$r->title = $wc_prod_var_o->get_title();
} else {
$r->title = get_the_title($r->id);
}
break;
case '1':
if ( ASL_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['titlefield_cf'] != '' ) {
if ( $comp_options['use_acf_getfield'] == 1 && function_exists('get_field') ) {
$mykey_values = get_field($sd['titlefield_cf'], $r->id, true);
if (!is_null($mykey_values) && $mykey_values != '' && $mykey_values !== false ) {
if (is_array($mykey_values)) {
if (!is_object($mykey_values[0])) {
$r->title = implode(', ', $mykey_values);
break;
}
} else {
$r->title = $mykey_values;
break;
}
}
} else {
$mykey_values = get_post_custom_values($sd['titlefield_cf'], $r->id);
if (isset($mykey_values[0])) {
$r->title = $mykey_values[0];
break;
}
}
}
break;
default:
if ( isset($wc_prod_var_o) ) {
$r->title = $wc_prod_var_o->get_title();
} else {
$r->title = get_the_title($r->id);
}
break;
}
if ( ! isset( $sd['striptagsexclude'] ) ) {
$sd['striptagsexclude'] = "<a><span>";
}
$_content = '';
switch ($sd['descriptionfield']) {
case '1':
if (function_exists('qtranxf_use')) {
global $q_config;
$r->excerpt = qtranxf_use($q_config['default_language'], $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['descriptionfield_cf'] != '') {
if ($comp_options['use_acf_getfield'] == 1 && function_exists('get_field')) {
$mykey_values = get_field($sd['descriptionfield_cf'], $r->id, true);
if (!is_null($mykey_values) && $mykey_values != '' && $mykey_values !== false ) {
if ( is_array($mykey_values) ) {
if ( !is_object($mykey_values[0]) ) {
$_content = implode(', ', $mykey_values);
break;
}
} else {
$_content = $mykey_values;
break;
}
}
} else {
$mykey_values = get_post_custom_values($sd['descriptionfield_cf'], $r->id);
if (isset($mykey_values[0])) {
$_content = $mykey_values[0];
break;
}
}
}
break;
default: //including option '0', alias content
if ( function_exists( 'qtranxf_use' ) ) {
global $q_config;
$r->content = qtranxf_use($q_config['default_language'], $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;
}
if ( $_content == "" && $r->content != '') {
$_content = $r->content;
}
// 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 );
}
}
// Remove styles and scripts
$_content = preg_replace( array(
'#<script(.*?)>(.*?)</script>#is',
'#<style(.*?)>(.*?)</style>#is'
), '', $_content );
$_content = strip_tags( $_content );
// Get the words from around the search phrase, or just the description
if ( w_isset_def($sd['description_context'], 1) == 1 && count( $_s ) > 0 && $s != '' ) {
// Try for an exact match
$_ex_content = $this->context_find(
$_content, $s,
floor($sd['descriptionlength'] / 6),
$sd['descriptionlength'],
50000,
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'],
50000
);
} else {
$_content = $_ex_content;
}
} else if ( $_content != '' && ( strlen( $_content ) > $sd['descriptionlength'] ) ) {
$_content = wd_substr_at_word($_content, $sd['descriptionlength']) . "...";
}
$post_time = strtotime($r->date);
$date_format = get_option('date_format', "Y-m-d") . " " . get_option('time_format', "H:i:s");
$r->date = @date_i18n($date_format, $post_time);
$_content = wd_closetags( $_content );
$r->content = $_content;
}
/* !Images, title, desc */
$this->results = $pageposts;
return $pageposts;
}
protected function group() {
return $this->results;
}
/**
* Fetches an image for BFI class
* @param $post WP_POst Post object
* @return string image URL
*/
protected function getBFIimage( $post ) {
if ( ! isset( $post->image ) || $post->image == null ) {
if ( ! isset( $post->id ) ) {
return "";
}
$im = "";
for ( $i = 1; $i < 6; $i ++ ) {
switch ( $this->imageSettings[ 'image_source' . $i ] ) {
case "featured":
if ( $this->imageSettings['image_source_featured'] == "original" ) {
$im = wp_get_attachment_url(get_post_thumbnail_id($post->id));
} else {
$imx = wp_get_attachment_image_src(
get_post_thumbnail_id($post->id), $this->imageSettings['image_source_featured'], false
);
if ( $imx !== false && isset($imx[0]) )
$im = $imx[0];
}
break;
case "content":
$content = apply_filters('the_content', get_post_field('post_content', $post->id));
$im = wpdreams_get_image_from_content( $content, 0 );
if ( is_multisite() ) {
$im = str_replace( home_url(), network_home_url(), $im );
}
break;
case "excerpt":
$excerpt = get_post_field('post_excerpt', $post->id);
$im = wpdreams_get_image_from_content( $excerpt, 0 );
if ( is_multisite() ) {
$im = str_replace( home_url(), network_home_url(), $im );
}
break;
case "screenshot":
$im = 'http://s.wordpress.com/mshots/v1/' . urlencode( get_permalink( $post->id ) ) .
'?w=' . $this->imageSettings['image_width'] . '&h=' . $this->imageSettings['image_height'];
break;
case "custom":
if ( $this->imageSettings['image_custom_field'] != "" ) {
$val = get_post_meta( $post->id, $this->imageSettings['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 ( $this->imageSettings['image_default'] != "" ) {
$im = $this->imageSettings['image_default'];
}
break;
default:
$im = "";
break;
}
if ( $im != null && $im != '' ) {
break;
}
}
return $im;
} else {
return $post->image;
}
}
/**
* Returns the context of a phrase within a text.
* Uses preg_split method to iterate through strings.
*
* @param $str string context
* @param $needle string context
* @param $context int length of the context
* @param $maxlength int maximum length of the string in characters
* @param $str_length_limit int source string maximum length
* @param $false_on_no_match bool to return boolean false if no matches were found
* @return string
*/
public function context_find($str, $needle, $context, $maxlength, $str_length_limit = 25000, $false_on_no_match = false) {
$haystack = ' '.trim($str).' ';
// To prevent memory overflow, we need to limit the hay to relatively low count
$haystack = wd_substr_at_word(ASL_mb::strtolower($haystack), $str_length_limit);
$needle = ASL_mb::strtolower($needle);
if ( $needle == "" ) return $str;
/**
* This is an interesting issue. Turns out mb_substr($hay, $start, 1) is very ineffective.
* the preg_split(..) method is far more efficient in terms of speed, however it needs much more
* memory. In our case speed is the top priority. However to prevent memory overflow, the haystack
* is reduced to 10000 characters (roughly 1500 words) first.
*
* Reference ticket: https://wp-dreams.com/forums/topic/search-speed/
* Speed tests: http://stackoverflow.com/questions/3666306/how-to-iterate-utf-8-string-in-php
*/
$chrArray = preg_split('//u', $haystack, -1, PREG_SPLIT_NO_EMPTY);
$hay_length = count($chrArray) - 1;
if ( $i = ASL_mb::strpos($haystack, $needle) ) {
$start=$i;
$end=$i;
$spaces=0;
while ($spaces < ((int) $context/2) && $start > 0) {
$start--;
if ($chrArray[$start] == ' ') {
$spaces++;
}
}
while ($spaces < ($context +1) && $end < $hay_length) {
$end++;
if ($chrArray[$end] == ' ') {
$spaces++;
}
}
while ($spaces < ($context +1) && $start > 0) {
$start--;
if ($chrArray[$start] == ' ') {
$spaces++;
}
}
$str_start = ($start - 1) < 0 ? 0 : ($start -1);
$str_end = ($end - 1) < 0 ? 0 : ($end -1);
$result = trim( ASL_mb::substr($str, $str_start, ($str_end - $str_start)) );
// Somewhere inbetween..
if ( $start != 0 && $end < $hay_length )
return "..." . $result . "...";
// Beginning
if ( $start == 0 && $end < $hay_length )
return $result . "...";
// End
if ( $start != 0 && $end == $hay_length )
return "..." . $result;
// If it is too long, strip it
if ( ASL_mb::strlen($result) > $maxlength)
return wd_substr_at_word( $result, $maxlength ) . "...";
// Else, it is the whole
return $result;
} else {
if ( $false_on_no_match )
return false;
// If it is too long, strip it
if ( ASL_mb::strlen($str) > $maxlength)
return wd_substr_at_word( $str, $maxlength ) . "...";
return $str;
}
}
/**
* An empty function to override individual shortcodes, this must be public
*
* @return string
*/
public function return_empty_string() {
return "";
}
}
}