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