limit = absint( DGWT_WCAS()->settings->get_opt( 'suggestions_limit', 10 ) );
$this->slots = $this->limit; // Free slots for the results. Default 10
add_filter( 'posts_search', array( $this, 'search_filters' ), 501, 2 );
add_filter( 'posts_join', array( $this, 'search_filters_join' ), 501, 2 );
add_filter( 'pre_get_posts', array( $this, 'change_wp_search_size' ), 500 );
add_filter( 'pre_get_posts', array( $this, 'set_search_results_query' ), 501 );
// Search results ajax action
if ( DGWT_WCAS_WC_AJAX_ENDPOINT ) {
add_action( 'wc_ajax_' . DGWT_WCAS_SEARCH_ACTION, array( $this, 'get_search_results' ) );
} else {
add_action( 'wp_ajax_nopriv_' . DGWT_WCAS_SEARCH_ACTION, array( $this, 'get_search_results' ) );
add_action( 'wp_ajax_' . DGWT_WCAS_SEARCH_ACTION, array( $this, 'get_search_results' ) );
}
}
/*
* Get search results via ajax
*/
public function get_search_results() {
global $woocommerce;
if ( !defined( 'DGWT_WCAS_AJAX' ) ) {
define( 'DGWT_WCAS_AJAX', true );
}
$output = array();
$results = array();
$keyword = sanitize_text_field( $_REQUEST[ 'dgwt_wcas_keyword' ] );
//@todo Get results from cache
/* SEARCH IN WOO CATEGORIES */
if ( DGWT_WCAS()->settings->get_opt( 'search_in_woo_categories' ) === 'on' ) {
$results = array_merge( $this->get_categories( $keyword ), $results );
// Update slots
$this->slots = $this->slots - count( $results );
} /* END SEARCH IN WOO CATEGORIES */
/* SEARCH IN WOO TAGS */
if ( $this->slots > 0 ) {
if ( DGWT_WCAS()->settings->get_opt( 'search_in_woo_tags' ) === 'on' ) {
$results = array_merge( $this->get_tags( $keyword ), $results );
// Update slots
$this->slots = $this->slots - count( $results );
}
}/* END SEARCH IN WOO TAGS */
// Continue searching in products if there are room in the slots
/* SEARCH IN PRODUCTS */
if ( $this->slots > 0 ) {
$ordering_args = $woocommerce->query->get_catalog_ordering_args( 'title', 'asc' );
$args = array(
's' => $keyword,
'post_type' => DGWT_WCAS_WOO_PRODUCT_POST_TYPE,
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'orderby' => $ordering_args[ 'orderby' ],
'order' => $ordering_args[ 'order' ],
'suppress_filters' => false,
'meta_query' => $this->get_meta_query()
);
$products = get_posts( $args );
if ( !empty( $products ) ) {
foreach ( $products as $post ) {
$product = wc_get_product( $post );
$r = array(
'post_id' => $product->id,
'value' => strip_tags( $product->get_title() ),
'url' => $product->get_permalink(),
);
// Get thumb HTML
if ( DGWT_WCAS()->settings->get_opt( 'show_product_image' ) === 'on' ) {
$r[ 'thumb_html' ] = $product->get_image( array( 60, 60 ) );
}
// Get price
if ( DGWT_WCAS()->settings->get_opt( 'show_product_price' ) === 'on' ) {
$r[ 'price' ] = $product->get_price_html();
}
// Get description
if ( DGWT_WCAS()->settings->get_opt( 'show_product_desc' ) === 'on' ) {
if ( DGWT_WCAS()->settings->get_opt( 'show_details_box' ) === 'on' ) {
$this->desc_limit = 60;
}
$r[ 'desc' ] = dgwt_wcas_get_product_desc( $product->id, $this->desc_limit );
}
// Get SKU
if ( DGWT_WCAS()->settings->get_opt( 'show_product_sku' ) === 'on' ) {
$r[ 'sku' ] = $product->get_sku();
}
// Is on sale
if ( DGWT_WCAS()->settings->get_opt( 'show_sale_badge' ) === 'on' ) {
$r[ 'on_sale' ] = $product->is_on_sale();
}
// Is featured
if ( DGWT_WCAS()->settings->get_opt( 'show_featured_badge' ) === 'on' ) {
$r[ 'featured' ] = $product->is_featured();
}
$results[] = apply_filters( 'dgwt_wcas_products_suggestions', $r, $product );
}
}
wp_reset_postdata();
} /* END SEARCH IN PRODUCTS */
// Show nothing on empty results
//@todo show 'No results' as option
if ( empty( $results ) ) {
$results[] = array(
'value' => __( 'No results', DGWT_WCAS_DOMAIN ),
);
}
//@todo Add results to the wp cache
$output[ 'suggestions' ] = $results;
echo json_encode( $output );
die();
}
/*
* Get meta query
*
* return array
*/
private function get_meta_query() {
$meta_query = array(
'relation' => 'AND',
1 => array(
'key' => '_visibility',
'value' => array( 'search', 'visible' ),
'compare' => 'IN'
),
2 => array(
'relation' => 'OR',
array(
'key' => '_visibility',
'value' => array( 'search', 'visible' ),
'compare' => 'IN'
)
)
);
// Exclude out of stock products from suggestions
if ( DGWT_WCAS()->settings->get_opt( 'exclude_out_of_stock' ) === 'on' ) {
$meta_query[ 2 ] = array(
'key' => '_stock_status',
'value' => 'outofstock',
'compare' => 'NOT IN'
);
};
return $meta_query;
}
/*
* Search for matching category
*
* @param string $keyword
*
* @return array
*/
public function get_categories( $keyword ) {
$results = array();
$args = array(
'taxonomy' => DGWT_WCAS_WOO_PRODUCT_CATEGORY
);
$product_categories = get_terms( DGWT_WCAS_WOO_PRODUCT_CATEGORY, $args );
// Compare keyword and term name
$i = 0;
foreach ( $product_categories as $cat ) {
if ( $i < $this->limit ) {
$pos = strpos( strtolower( $cat->name ), strtolower( $keyword ) );
if ( $pos !== false ) {
$results[ $i ] = array(
'term_id' => $cat->term_id,
'taxonomy' => DGWT_WCAS_WOO_PRODUCT_CATEGORY,
'value' => preg_replace( sprintf( "/(%s)/", $keyword ), "$1", $cat->name ),
'url' => get_term_link( $cat, DGWT_WCAS_WOO_PRODUCT_CATEGORY ),
'parents' => ''
);
// Add category parents info
$parents = $this->get_taxonomy_parent_string( $cat->term_id, DGWT_WCAS_WOO_PRODUCT_CATEGORY, array(), array( $cat->term_id ) );
if ( !empty( $parents ) ) {
$results[ $i ][ 'parents' ] = sprintf( ' %s %s', __( 'in', DGWT_WCAS_DOMAIN ), mb_substr( $parents, 0, -3 ) );
}
}
}
$i++;
}
return $results;
}
/*
* Extend research in the Woo tags
*
* @param strong $keyword
*
* @return array
*/
public function get_tags( $keyword ) {
$results = array();
$args = array(
'taxonomy' => DGWT_WCAS_WOO_PRODUCT_TAG
);
$product_tags = get_terms( DGWT_WCAS_WOO_PRODUCT_TAG, $args );
// Compare keyword and term name
$i = 0;
foreach ( $product_tags as $tag ) {
if ( $i < $this->limit ) {
$pos = strpos( strtolower( $tag->name ), strtolower( $keyword ) );
if ( $pos !== false ) {
$results[ $i ] = array(
'term_id' => $tag->term_id,
'taxonomy' => DGWT_WCAS_WOO_PRODUCT_TAG,
'value' => preg_replace( sprintf( "/(%s)/", $keyword ), "$1", $tag->name ),
'url' => get_term_link( $tag, DGWT_WCAS_WOO_PRODUCT_TAG ),
'parents' => ''
);
// Add taxonomy parents info
$parents = $this->get_taxonomy_parent_string( $tag->term_id, DGWT_WCAS_WOO_PRODUCT_TAG, array(), array( $tag->term_id ) );
if ( !empty( $parents ) ) {
$results[ $i ][ 'parents' ] = sprintf( ' %s %s', __( 'in', DGWT_WCAS_DOMAIN ), mb_substr( $parents, 0, -3 ) );
}
}
}
$i++;
}
return $results;
}
/*
* Set search product limit
*/
public function change_wp_search_size( $query ) {
if ( defined( 'DGWT_WCAS_AJAX' ) ) {
if ( $query->is_search )
$query->query_vars[ 'posts_per_page' ] = $this->slots;
}
return $query;
}
/*
* Search only in products titles
*
* @param string $search SQL
* @param object $wp_query
*
* @return string prepared SQL
*/
public function search_filters( $search, &$wp_query ) {
global $wpdb;
if ( empty( $search ) ) {
return $search; // skip processing - there is no keyword
}
if ( defined( 'DGWT_WCAS_AJAX' ) || is_search() ) {
$q = $wp_query->query_vars;
if ( $q[ 'post_type' ] !== DGWT_WCAS_WOO_PRODUCT_POST_TYPE ) {
return $search; // skip processing - on Woo products
}
$n = !empty( $q[ 'exact' ] ) ? '' : '%';
$search = $searchand = '';
foreach ( (array) $q[ 'search_terms' ] as $term ) {
$term = esc_sql( $wpdb->esc_like( $term ) );
$search .= "{$searchand} (";
// Search in title
$search .= "($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')";
// Search in content
if ( DGWT_WCAS()->settings->get_opt( 'search_in_product_content' ) === 'on' ) {
$search .= " OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}')";
}
// Search in excerpt
if ( DGWT_WCAS()->settings->get_opt( 'search_in_product_excerpt' ) === 'on' ) {
$search .= " OR ($wpdb->posts.post_excerpt LIKE '{$n}{$term}{$n}')";
}
// Search in SKU
if ( DGWT_WCAS()->settings->get_opt( 'search_in_product_sku' ) === 'on' ) {
$search .= " OR (dgwt_wcasmsku.meta_key='_sku' AND dgwt_wcasmsku.meta_value LIKE '{$n}{$term}{$n}')";
}
$search .= ")";
$searchand = ' AND ';
}
if ( !empty( $search ) ) {
$search = " AND ({$search}) ";
if ( !is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
}
return $search;
}
/*
* Join the postmeta column in the search posts SQL
*/
public function search_filters_join( $join, $query ) {
global $wpdb;
if ( defined( 'DGWT_WCAS_AJAX' ) || is_search() ) {
if ( DGWT_WCAS()->settings->get_opt( 'search_in_product_sku' ) === 'on' ) {
$join .= " INNER JOIN $wpdb->postmeta AS dgwt_wcasmsku ON ( $wpdb->posts.ID = dgwt_wcasmsku.post_id )";
}
}
return $join;
}
/*
* Get taxonomy parent
*
* @param int $term_id
* @param string $taxonomy
*
* @return string
*/
private function get_taxonomy_parent_string( $term_id, $taxonomy, $visited = array(), $exclude = array() ) {
$chain = '';
$separator = ' > ';
$parent = get_term( $term_id, $taxonomy );
if ( empty( $parent ) || !isset( $parent->name ) ) {
return '';
}
$name = $parent->name;
if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
$visited[] = $parent->parent;
$chain .= $this->get_taxonomy_parent_string( $parent->parent, $taxonomy, $visited );
}
if ( !in_array( $parent->term_id, $exclude ) ) {
$chain .= $name . $separator;
}
return $chain;
}
/*
* Change default search query on the search results page
*
* @since 1.0.3
*
* @param object $query
*
* @return object
*/
public function set_search_results_query( $query ) {
if ( !defined( 'DGWT_WCAS_AJAX' ) && $query->is_search ) {
if(!empty($_GET['dgwt_wcas']) && !empty($_GET['s'])){
$query->query_vars[ 'post_type' ] = DGWT_WCAS_WOO_PRODUCT_POST_TYPE;
$query->query_vars[ 'meta_query' ] = $this->get_meta_query();
}
}
return $query;
}
}
?>