/**
  * Query the products and return them.
  * @param  array $args
  * @param  array $instance
  * @return WP_Query
  */
 public function get_products($args, $instance)
 {
     $number = !empty($instance['number']) ? absint($instance['number']) : $this->settings['number']['std'];
     $show = !empty($instance['show']) ? sanitize_title($instance['show']) : $this->settings['show']['std'];
     $orderby = !empty($instance['orderby']) ? sanitize_title($instance['orderby']) : $this->settings['orderby']['std'];
     $order = !empty($instance['order']) ? sanitize_title($instance['order']) : $this->settings['order']['std'];
     $product_visibility_term_ids = wc_get_product_visibility_term_ids();
     $query_args = array('posts_per_page' => $number, 'post_status' => 'publish', 'post_type' => 'product', 'no_found_rows' => 1, 'order' => $order, 'meta_query' => array(), 'tax_query' => array('relation' => 'AND'));
     if (empty($instance['show_hidden'])) {
         $query_args['tax_query'][] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => is_search() ? $product_visibility_term_ids['exclude-from-search'] : $product_visibility_term_ids['exclude-from-catalog'], 'operator' => 'NOT IN');
         $query_args['post_parent'] = 0;
     }
     if (!empty($instance['hide_free'])) {
         $query_args['meta_query'][] = array('key' => '_price', 'value' => 0, 'compare' => '>', 'type' => 'DECIMAL');
     }
     if ('yes' === get_option('woocommerce_hide_out_of_stock_items')) {
         $query_args['tax_query'] = array(array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['outofstock'], 'operator' => 'NOT IN'));
     }
     switch ($show) {
         case 'featured':
             $query_args['tax_query'][] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['featured']);
             break;
         case 'onsale':
             $product_ids_on_sale = wc_get_product_ids_on_sale();
             $product_ids_on_sale[] = 0;
             $query_args['post__in'] = $product_ids_on_sale;
             break;
     }
     switch ($orderby) {
         case 'price':
             $query_args['meta_key'] = '_price';
             $query_args['orderby'] = 'meta_value_num';
             break;
         case 'rand':
             $query_args['orderby'] = 'rand';
             break;
         case 'sales':
             $query_args['meta_key'] = 'total_sales';
             $query_args['orderby'] = 'meta_value_num';
             break;
         default:
             $query_args['orderby'] = 'date';
     }
     return new WP_Query(apply_filters('woocommerce_products_widget_query_args', $query_args));
 }
 /**
  * Count products after other filters have occured by adjusting the main query.
  * @param  int $rating
  * @return int
  */
 protected function get_filtered_product_count($rating)
 {
     global $wpdb;
     $tax_query = WC_Query::get_main_tax_query();
     $meta_query = WC_Query::get_main_meta_query();
     // Unset current rating filter.
     foreach ($tax_query as $key => $query) {
         if (!empty($query['rating_filter'])) {
             unset($tax_query[$key]);
             break;
         }
     }
     // Set new rating filter.
     $product_visibility_terms = wc_get_product_visibility_term_ids();
     $tax_query[] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_terms['rated-' . $rating], 'operator' => 'IN', 'rating_filter' => true);
     $meta_query = new WP_Meta_Query($meta_query);
     $tax_query = new WP_Tax_Query($tax_query);
     $meta_query_sql = $meta_query->get_sql('post', $wpdb->posts, 'ID');
     $tax_query_sql = $tax_query->get_sql($wpdb->posts, 'ID');
     $sql = "SELECT COUNT( DISTINCT {$wpdb->posts}.ID ) FROM {$wpdb->posts} ";
     $sql .= $tax_query_sql['join'] . $meta_query_sql['join'];
     $sql .= " WHERE {$wpdb->posts}.post_type = 'product' AND {$wpdb->posts}.post_status = 'publish' ";
     $sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
     return absint($wpdb->get_var($sql));
 }
 /**
  * Builds the related posts query.
  *
  * @since 2.7.0
  * @param array $cats_array  List of categories IDs.
  * @param array $tags_array  List of tags IDs.
  * @param array $exclude_ids Excluded IDs.
  * @param int   $limit       Limit of results.
  * @return string
  */
 public function get_related_products_query($cats_array, $tags_array, $exclude_ids, $limit)
 {
     global $wpdb;
     // Arrays to string.
     $exclude_ids = implode(',', array_map('absint', $exclude_ids));
     $cats_array = implode(',', array_map('absint', $cats_array));
     $tags_array = implode(',', array_map('absint', $tags_array));
     $limit = absint($limit);
     $query = array();
     $query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p";
     $query['join'] = " INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)";
     $query['join'] .= " INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)";
     $query['join'] .= " INNER JOIN {$wpdb->terms} t ON (t.term_id = tt.term_id)";
     $query['where'] = ' WHERE 1=1';
     $query['where'] .= " AND p.post_status = 'publish'";
     $query['where'] .= " AND p.post_type = 'product'";
     $query['where'] .= " AND p.ID NOT IN ( {$exclude_ids} )";
     $product_visibility_term_ids = wc_get_product_visibility_term_ids();
     if ($product_visibility_term_ids['exclude-from-catalog']) {
         $query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['exclude-from-catalog'];
     }
     if ('yes' === get_option('woocommerce_hide_out_of_stock_items') && $product_visibility_term_ids['outofstock']) {
         $query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['outofstock'];
     }
     if ($cats_array || $tags_array) {
         $query['where'] .= ' AND (';
         if ($cats_array) {
             $query['where'] .= " ( tt.taxonomy = 'product_cat' AND t.term_id IN ( {$cats_array} ) ) ";
             if ($tags_array) {
                 $query['where'] .= ' OR ';
             }
         }
         if ($tags_array) {
             $query['where'] .= " ( tt.taxonomy = 'product_tag' AND t.term_id IN ( {$tags_array} ) ) ";
         }
         $query['where'] .= ')';
     }
     $query['limits'] = " LIMIT {$limit} ";
     return $query;
 }
 /**
  * Appends tax queries to an array.
  * @param array $tax_query
  * @param bool  $main_query
  * @return array
  */
 public function get_tax_query($tax_query = array(), $main_query = false)
 {
     if (!is_array($tax_query)) {
         $tax_query = array('relation' => 'AND');
     }
     // Layered nav filters on terms.
     if ($main_query && ($_chosen_attributes = $this->get_layered_nav_chosen_attributes())) {
         foreach ($_chosen_attributes as $taxonomy => $data) {
             $tax_query[] = array('taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $data['terms'], 'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN', 'include_children' => false);
         }
     }
     $product_visibility_terms = wc_get_product_visibility_term_ids();
     $product_visibility_not_in = array(is_search() && $main_query ? $product_visibility_terms['exclude-from-search'] : $product_visibility_terms['exclude-from-catalog']);
     $product_visibility_in = array();
     // Hide out of stock products.
     if ('yes' === get_option('woocommerce_hide_out_of_stock_items')) {
         $product_visibility_not_in[] = $product_visibility_terms['outofstock'];
     }
     // Filter by rating.
     if (isset($_GET['rating_filter'])) {
         $rating_filter = array_filter(array_map('absint', explode(',', $_GET['rating_filter'])));
         $rating_terms = array();
         for ($i = 1; $i <= 5; $i++) {
             if (in_array($i, $rating_filter) && isset($product_visibility_terms['rated-' . $i])) {
                 $rating_terms[] = $product_visibility_terms['rated-' . $i];
             }
         }
         if (!empty($rating_terms)) {
             $tax_query[] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $rating_terms, 'operator' => 'IN', 'rating_filter' => true);
         }
     }
     if (!empty($product_visibility_not_in)) {
         $tax_query[] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_not_in, 'operator' => 'NOT IN');
     }
     return array_filter(apply_filters('woocommerce_product_query_tax_query', $tax_query, $this));
 }
/**
 * Function for recounting product terms, ignoring hidden products.
 * @param  array $terms
 * @param  string $taxonomy
 * @param  bool $callback
 * @param  bool $terms_are_term_taxonomy_ids
 */
function _wc_term_recount($terms, $taxonomy, $callback = true, $terms_are_term_taxonomy_ids = true)
{
    global $wpdb, $wc_allow_term_recount;
    // Don't recount unless CRUD is calling this.
    if (empty($wc_allow_term_recount)) {
        return;
    }
    // Standard callback
    if ($callback) {
        _update_post_term_count($terms, $taxonomy);
    }
    // Main query
    $count_query = "\n\t\tSELECT COUNT( DISTINCT posts.ID ) FROM {$wpdb->posts} as posts\n\t\tLEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID\n\t\tLEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )\n\t\tWHERE \tpost_status = 'publish'\n\t\tAND \tpost_type \t= 'product'\n\t";
    $product_visibility_term_ids = wc_get_product_visibility_term_ids();
    if ($product_visibility_term_ids['exclude-from-catalog']) {
        $count_query .= " AND term_taxonomy_id !=" . $product_visibility_term_ids['exclude-from-catalog'];
    }
    if ('yes' === get_option('woocommerce_hide_out_of_stock_items') && $product_visibility_term_ids['outofstock']) {
        $count_query .= " AND term_taxonomy_id !=" . $product_visibility_term_ids['outofstock'];
    }
    // Pre-process term taxonomy ids
    if (!$terms_are_term_taxonomy_ids) {
        // We passed in an array of TERMS in format id=>parent
        $terms = array_filter((array) array_keys($terms));
    } else {
        // If we have term taxonomy IDs we need to get the term ID
        $term_taxonomy_ids = $terms;
        $terms = array();
        foreach ($term_taxonomy_ids as $term_taxonomy_id) {
            $term = get_term_by('term_taxonomy_id', $term_taxonomy_id, $taxonomy->name);
            $terms[] = $term->term_id;
        }
    }
    // Exit if we have no terms to count
    if (empty($terms)) {
        return;
    }
    // Ancestors need counting
    if (is_taxonomy_hierarchical($taxonomy->name)) {
        foreach ($terms as $term_id) {
            $terms = array_merge($terms, get_ancestors($term_id, $taxonomy->name));
        }
    }
    // Unique terms only
    $terms = array_unique($terms);
    // Count the terms
    foreach ($terms as $term_id) {
        $terms_to_count = array(absint($term_id));
        if (is_taxonomy_hierarchical($taxonomy->name)) {
            // We need to get the $term's hierarchy so we can count its children too
            if (($children = get_term_children($term_id, $taxonomy->name)) && !is_wp_error($children)) {
                $terms_to_count = array_unique(array_map('absint', array_merge($terms_to_count, $children)));
            }
        }
        // Generate term query
        $term_query = ' AND term_id IN ( ' . implode(',', $terms_to_count) . ' )';
        // Get the count
        $count = $wpdb->get_var($count_query . $term_query);
        // Update the count
        update_woocommerce_term_meta($term_id, 'product_count_' . $taxonomy->name, absint($count));
    }
    delete_transient('wc_term_counts');
}