<?php defined('ABSPATH') || exit; function wc_change_get_terms_defaults($defaults, $taxonomies) { if (is_array($taxonomies) && 1 < count($taxonomies)) { return $defaults; } $taxonomy = is_array($taxonomies) ? (string) current($taxonomies) : $taxonomies; $orderby = 'name'; if (taxonomy_is_product_attribute($taxonomy)) { $orderby = wc_attribute_orderby($taxonomy); } elseif (in_array($taxonomy, apply_filters('woocommerce_sortable_taxonomies', array('product_cat')), true)) { $orderby = 'menu_order'; } switch ($orderby) { case 'menu_order': case 'name_num': case 'parent': $defaults['orderby'] = $orderby; break; } return $defaults; } add_filter('get_terms_defaults', 'wc_change_get_terms_defaults', 10, 2); function wc_change_pre_get_terms($terms_query) { $args =& $terms_query->query_vars; if ('menu_order' === $args['orderby']) { $args['orderby'] = 'name'; $args['force_menu_order_sort'] = true; } if ('name_num' === $args['orderby']) { $args['orderby'] = 'name'; $args['force_numeric_name'] = true; } if ('count' === $args['fields']) { return; } if (!empty($args['menu_order'])) { $args['order'] = 'DESC' === strtoupper($args['menu_order']) ? 'DESC' : 'ASC'; $args['force_menu_order_sort'] = true; } if (!empty($args['force_menu_order_sort'])) { $args['orderby'] = 'meta_value_num'; $args['meta_key'] = 'order'; $terms_query->meta_query->parse_query_vars($args); } } add_action('pre_get_terms', 'wc_change_pre_get_terms', 10, 1); function wc_terms_clauses($clauses, $taxonomies, $args) { global $wpdb; if (strpos($clauses['fields'], 'COUNT(*)') !== false) { return $clauses; } if (!empty($args['force_numeric_name'])) { $clauses['orderby'] = str_replace('ORDER BY t.name', 'ORDER BY t.name+0', $clauses['orderby']); } if (!empty($args['force_menu_order_sort'])) { $clauses['join'] = str_replace("INNER JOIN {$wpdb->termmeta} ON ( t.term_id = {$wpdb->termmeta}.term_id )", "LEFT JOIN {$wpdb->termmeta} ON ( t.term_id = {$wpdb->termmeta}.term_id AND {$wpdb->termmeta}.meta_key='order')", $clauses['join']); $clauses['where'] = str_replace("{$wpdb->termmeta}.meta_key = 'order'", "( {$wpdb->termmeta}.meta_key = 'order' OR {$wpdb->termmeta}.meta_key IS NULL )", $clauses['where']); $clauses['orderby'] = 'DESC' === $args['order'] ? str_replace('meta_value+0', 'meta_value+0 DESC, t.name', $clauses['orderby']) : str_replace('meta_value+0', 'meta_value+0 ASC, t.name', $clauses['orderby']); } return $clauses; } add_filter('terms_clauses', 'wc_terms_clauses', 99, 3); function wc_get_object_terms($object_id, $taxonomy, $field = null, $index_key = null) { $terms = get_the_terms($object_id, $taxonomy); if (!$terms || is_wp_error($terms)) { return array(); } return is_null($field) ? $terms : wp_list_pluck($terms, $field, $index_key); } function _wc_get_cached_product_terms($product_id, $taxonomy, $args = array()) { $cache_key = 'wc_' . $taxonomy . md5(wp_json_encode($args)); $cache_group = WC_Cache_Helper::get_cache_prefix('product_' . $product_id) . $product_id; $terms = wp_cache_get($cache_key, $cache_group); if (false !== $terms) { return $terms; } $terms = wp_get_post_terms($product_id, $taxonomy, $args); wp_cache_add($cache_key, $terms, $cache_group); return $terms; } function wc_get_product_terms($product_id, $taxonomy, $args = array()) { if (!taxonomy_exists($taxonomy)) { return array(); } return apply_filters('woocommerce_get_product_terms', _wc_get_cached_product_terms($product_id, $taxonomy, $args), $product_id, $taxonomy, $args); } function _wc_get_product_terms_name_num_usort_callback($a, $b) { $a_name = (float) $a->name; $b_name = (float) $b->name; if (abs($a_name - $b_name) < 0.001) { return 0; } return $a_name < $b_name ? -1 : 1; } function _wc_get_product_terms_parent_usort_callback($a, $b) { if ($a->parent === $b->parent) { return 0; } return $a->parent < $b->parent ? 1 : -1; } function wc_product_dropdown_categories($args = array()) { global $wp_query; $args = wp_parse_args($args, array('pad_counts' => 1, 'show_count' => 1, 'hierarchical' => 1, 'hide_empty' => 1, 'show_uncategorized' => 1, 'orderby' => 'name', 'selected' => isset($wp_query->query_vars['product_cat']) ? $wp_query->query_vars['product_cat'] : '', 'show_option_none' => __('Select a category', 'woocommerce'), 'option_none_value' => '', 'value_field' => 'slug', 'taxonomy' => 'product_cat', 'name' => 'product_cat', 'class' => 'dropdown_product_cat')); if ('order' === $args['orderby']) { $args['orderby'] = 'meta_value_num'; $args['meta_key'] = 'order'; } wp_dropdown_categories($args); } function wc_walk_category_dropdown_tree(...$args) { if (!class_exists('WC_Product_Cat_Dropdown_Walker', false)) { include_once WC()->plugin_path() . '/includes/walkers/class-wc-product-cat-dropdown-walker.php'; } if (empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker')) { $walker = new WC_Product_Cat_Dropdown_Walker(); } else { $walker = $args[2]['walker']; } return $walker->walk(...$args); } function wc_taxonomy_metadata_migrate_data($wp_db_version, $wp_current_db_version) { if ($wp_db_version >= 34370 && $wp_current_db_version < 34370) { global $wpdb; if ($wpdb->query("INSERT INTO {$wpdb->termmeta} ( term_id, meta_key, meta_value ) SELECT woocommerce_term_id, meta_key, meta_value FROM {$wpdb->prefix}woocommerce_termmeta;")) { $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_termmeta"); } } } add_action('wp_upgrade', 'wc_taxonomy_metadata_migrate_data', 10, 2); function wc_reorder_terms($the_term, $next_id, $taxonomy, $index = 0, $terms = null) { if (!$terms) { $terms = get_terms($taxonomy, 'hide_empty=0&parent=0&menu_order=ASC'); } if (empty($terms)) { return $index; } $id = intval($the_term->term_id); $term_in_level = false; foreach ($terms as $term) { $term_id = intval($term->term_id); if ($term_id === $id) { $term_in_level = true; continue; } if (null !== $next_id && $term_id === $next_id) { $index++; $index = wc_set_term_order($id, $index, $taxonomy, true); } $index++; $index = wc_set_term_order($term_id, $index, $taxonomy); do_action('woocommerce_after_set_term_order', $term, $index, $taxonomy); $children = get_terms($taxonomy, "parent={$term_id}&hide_empty=0&menu_order=ASC"); if (!empty($children)) { $index = wc_reorder_terms($the_term, $next_id, $taxonomy, $index, $children); } } if ($term_in_level && null === $next_id) { $index = wc_set_term_order($id, $index + 1, $taxonomy, true); } return $index; } function wc_set_term_order($term_id, $index, $taxonomy, $recursive = false) { $term_id = (int) $term_id; $index = (int) $index; update_term_meta($term_id, 'order', $index); if (!$recursive) { return $index; } $children = get_terms($taxonomy, "parent={$term_id}&hide_empty=0&menu_order=ASC"); foreach ($children as $term) { $index++; $index = wc_set_term_order($term->term_id, $index, $taxonomy, true); } clean_term_cache($term_id, $taxonomy); return $index; } function _wc_term_recount($terms, $taxonomy, $callback = true, $terms_are_term_taxonomy_ids = true) { global $wpdb; if (!apply_filters('woocommerce_product_recount_terms', '__return_true')) { return; } if ($callback) { _update_post_term_count($terms, $taxonomy); } $exclude_term_ids = array(); $product_visibility_term_ids = wc_get_product_visibility_term_ids(); if ($product_visibility_term_ids['exclude-from-catalog']) { $exclude_term_ids[] = $product_visibility_term_ids['exclude-from-catalog']; } if ('yes' === get_option('woocommerce_hide_out_of_stock_items') && $product_visibility_term_ids['outofstock']) { $exclude_term_ids[] = $product_visibility_term_ids['outofstock']; } $query = array('fields' => "\n\t\t\tSELECT COUNT( DISTINCT ID ) FROM {$wpdb->posts} p\n\t\t", 'join' => '', 'where' => "\n\t\t\tWHERE 1=1\n\t\t\tAND p.post_status = 'publish'\n\t\t\tAND p.post_type = 'product'\n\n\t\t"); if (count($exclude_term_ids)) { $query['join'] .= " LEFT JOIN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ( " . implode(',', array_map('absint', $exclude_term_ids)) . ' ) ) AS exclude_join ON exclude_join.object_id = p.ID'; $query['where'] .= ' AND exclude_join.object_id IS NULL'; } if (!$terms_are_term_taxonomy_ids) { $terms = array_filter((array) array_keys($terms)); } else { $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; } } if (empty($terms)) { return; } if (is_taxonomy_hierarchical($taxonomy->name)) { foreach ($terms as $term_id) { $terms = array_merge($terms, get_ancestors($term_id, $taxonomy->name)); } } $terms = array_unique($terms); foreach ($terms as $term_id) { $terms_to_count = array(absint($term_id)); if (is_taxonomy_hierarchical($taxonomy->name)) { $children = get_term_children($term_id, $taxonomy->name); if ($children && !is_wp_error($children)) { $terms_to_count = array_unique(array_map('absint', array_merge($terms_to_count, $children))); } } $term_query = $query; $term_query['join'] .= " INNER JOIN ( SELECT object_id FROM {$wpdb->term_relationships} INNER JOIN {$wpdb->term_taxonomy} using( term_taxonomy_id ) WHERE term_id IN ( " . implode(',', array_map('absint', $terms_to_count)) . ' ) ) AS include_join ON include_join.object_id = p.ID'; $count = $wpdb->get_var(implode(' ', $term_query)); update_term_meta($term_id, 'product_count_' . $taxonomy->name, absint($count)); } delete_transient('wc_term_counts'); } function wc_recount_after_stock_change($product_id) { if ('yes' !== get_option('woocommerce_hide_out_of_stock_items')) { return; } _wc_recount_terms_by_product($product_id); } add_action('woocommerce_product_set_stock_status', 'wc_recount_after_stock_change'); function wc_change_term_counts($terms, $taxonomies) { if (is_admin() || is_ajax()) { return $terms; } if (!isset($taxonomies[0]) || !in_array($taxonomies[0], apply_filters('woocommerce_change_term_counts', array('product_cat', 'product_tag')), true)) { return $terms; } $o_term_counts = get_transient('wc_term_counts'); $term_counts = $o_term_counts; foreach ($terms as &$term) { if (is_object($term)) { $term_counts[$term->term_id] = isset($term_counts[$term->term_id]) ? $term_counts[$term->term_id] : get_term_meta($term->term_id, 'product_count_' . $taxonomies[0], true); if ('' !== $term_counts[$term->term_id]) { $term->count = absint($term_counts[$term->term_id]); } } } if ($term_counts !== $o_term_counts) { set_transient('wc_term_counts', $term_counts, DAY_IN_SECONDS * 30); } return $terms; } add_filter('get_terms', 'wc_change_term_counts', 10, 2); function wc_get_term_product_ids($term_id, $taxonomy) { $product_ids = get_term_meta($term_id, 'product_ids', true); if (false === $product_ids || !is_array($product_ids)) { $product_ids = get_objects_in_term($term_id, $taxonomy); update_term_meta($term_id, 'product_ids', $product_ids); } return $product_ids; } function wc_clear_term_product_ids($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids) { foreach ($old_tt_ids as $term_id) { delete_term_meta($term_id, 'product_ids'); } foreach ($tt_ids as $term_id) { delete_term_meta($term_id, 'product_ids'); } } add_action('set_object_terms', 'wc_clear_term_product_ids', 10, 6); function wc_get_product_visibility_term_ids() { if (!taxonomy_exists('product_visibility')) { wc_doing_it_wrong(__FUNCTION__, 'wc_get_product_visibility_term_ids should not be called before taxonomies are registered (woocommerce_after_register_post_type action).', '3.1'); return array(); } return array_map('absint', wp_parse_args(wp_list_pluck(get_terms(array('taxonomy' => 'product_visibility', 'hide_empty' => false)), 'term_taxonomy_id', 'name'), array('exclude-from-catalog' => 0, 'exclude-from-search' => 0, 'featured' => 0, 'outofstock' => 0, 'rated-1' => 0, 'rated-2' => 0, 'rated-3' => 0, 'rated-4' => 0, 'rated-5' => 0))); } function wc_recount_all_terms() { $product_cats = get_terms('product_cat', array('hide_empty' => false, 'fields' => 'id=>parent')); _wc_term_recount($product_cats, get_taxonomy('product_cat'), true, false); $product_tags = get_terms('product_tag', array('hide_empty' => false, 'fields' => 'id=>parent')); _wc_term_recount($product_tags, get_taxonomy('product_tag'), true, false); } function _wc_recount_terms_by_product($product_id = '') { if (empty($product_id)) { return; } $product_terms = get_the_terms($product_id, 'product_cat'); if ($product_terms) { $product_cats = array(); foreach ($product_terms as $term) { $product_cats[$term->term_id] = $term->parent; } _wc_term_recount($product_cats, get_taxonomy('product_cat'), false, false); } $product_terms = get_the_terms($product_id, 'product_tag'); if ($product_terms) { $product_tags = array(); foreach ($product_terms as $term) { $product_tags[$term->term_id] = $term->parent; } _wc_term_recount($product_tags, get_taxonomy('product_tag'), false, false); } }