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' ) && 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; } } ?>