/** * 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'); }