2013-08-09 16:11:15 +00:00
< ? php
/**
2015-11-03 13:53:50 +00:00
* WooCommerce Terms
2013-08-09 16:11:15 +00:00
*
* Functions for handling terms / term meta .
*
* @ author WooThemes
* @ category Core
* @ package WooCommerce / Functions
* @ version 2.1 . 0
*/
2014-09-20 19:11:49 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ; // Exit if accessed directly
}
2013-08-09 16:11:15 +00:00
2016-11-17 19:00:56 +00:00
/**
* Helper to get cached object terms and filter by field using wp_list_pluck () .
* Works as a cached alternative for wp_get_post_terms () and wp_get_object_terms () .
*
* @ since 2.7 . 0
* @ param int $object_id Object ID .
* @ param string $taxonomy Taxonomy slug .
* @ param string $field Field name .
* @ param string $index_key Index key name .
* @ return array
*/
function wc_get_object_terms ( $object_id , $taxonomy , $field = null , $index_key = null ) {
// Test if terms exists.
// get_the_terms() return false when don't found terms.
if ( $terms = get_the_terms ( $object_id , $taxonomy ) ) {
if ( ! is_null ( $field ) ) {
$terms = wp_list_pluck ( $terms , $field , $index_key );
}
2016-11-21 14:16:55 +00:00
} else {
$terms = array ();
2016-11-17 19:00:56 +00:00
}
return $terms ;
}
/**
* Cached version of wp_get_post_terms () .
* This is a private function ( internal use ONLY ) .
*
* @ since 2.7 . 0
* @ param int $product_id Product ID .
* @ param string $taxonomy Taxonomy slug .
* @ param array $args Query arguments .
* @ return array
*/
function _wc_get_cached_product_terms ( $product_id , $taxonomy , $args = array () ) {
$cache_key = 'wc_' . $taxonomy . md5 ( json_encode ( $args ) );
$terms = wp_cache_get ( $product_id , $cache_key );
if ( false !== $terms ) {
return $terms ;
}
// @codingStandardsIgnoreStart
$terms = wp_get_post_terms ( $product_id , $taxonomy , $args );
// @codingStandardsIgnoreEnd
wp_cache_add ( $product_id , $terms , $cache_key );
return $terms ;
}
2013-09-13 11:07:54 +00:00
/**
2014-02-07 11:43:34 +00:00
* Wrapper for wp_get_post_terms which supports ordering by parent .
*
2015-11-03 13:31:20 +00:00
* NOTE : At this point in time , ordering by menu_order for example isn ' t possible with this function . wp_get_post_terms has no .
* filters which we can utilise to modify it ' s query . https :// core . trac . wordpress . org / ticket / 19094.
2014-09-20 19:11:49 +00:00
*
2016-11-17 19:00:56 +00:00
* @ param int $product_id Product ID .
* @ param string $taxonomy Taxonomy slug .
* @ param array $args Query arguments .
2013-11-25 13:30:20 +00:00
* @ return array
2013-09-13 11:07:54 +00:00
*/
function wc_get_product_terms ( $product_id , $taxonomy , $args = array () ) {
2014-05-12 13:31:25 +00:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
2013-11-25 13:30:20 +00:00
return array ();
2014-05-12 13:31:25 +00:00
}
2013-11-25 13:30:20 +00:00
2014-02-07 11:38:57 +00:00
if ( empty ( $args [ 'orderby' ] ) && taxonomy_is_product_attribute ( $taxonomy ) ) {
$args [ 'orderby' ] = wc_attribute_orderby ( $taxonomy );
2013-11-25 13:30:20 +00:00
}
2016-11-17 19:00:56 +00:00
// Support ordering by parent.
2014-11-27 14:48:58 +00:00
if ( ! empty ( $args [ 'orderby' ] ) && in_array ( $args [ 'orderby' ], array ( 'name_num' , 'parent' ) ) ) {
$fields = isset ( $args [ 'fields' ] ) ? $args [ 'fields' ] : 'all' ;
$orderby = $args [ 'orderby' ];
2013-11-25 13:30:20 +00:00
2016-11-17 19:00:56 +00:00
// Unset for wp_get_post_terms.
2013-11-25 13:30:20 +00:00
unset ( $args [ 'orderby' ] );
unset ( $args [ 'fields' ] );
2013-09-13 11:07:54 +00:00
2016-11-17 19:00:56 +00:00
$terms = _wc_get_cached_product_terms ( $product_id , $taxonomy , $args );
2013-09-13 11:07:54 +00:00
2014-11-27 14:48:58 +00:00
switch ( $orderby ) {
case 'name_num' :
usort ( $terms , '_wc_get_product_terms_name_num_usort_callback' );
break ;
case 'parent' :
usort ( $terms , '_wc_get_product_terms_parent_usort_callback' );
break ;
}
2013-09-13 11:07:54 +00:00
2013-11-25 13:30:20 +00:00
switch ( $fields ) {
case 'names' :
$terms = wp_list_pluck ( $terms , 'name' );
2014-02-12 11:47:56 +00:00
break ;
2013-11-25 13:30:20 +00:00
case 'ids' :
$terms = wp_list_pluck ( $terms , 'term_id' );
2014-02-12 11:47:56 +00:00
break ;
2013-11-25 13:30:20 +00:00
case 'slugs' :
$terms = wp_list_pluck ( $terms , 'slug' );
2014-02-12 11:47:56 +00:00
break ;
2013-11-25 13:30:20 +00:00
}
2016-09-07 22:32:24 +00:00
} elseif ( ! empty ( $args [ 'orderby' ] ) && 'menu_order' === $args [ 'orderby' ] ) {
2016-11-17 19:00:56 +00:00
// wp_get_post_terms doesn't let us use custom sort order.
$args [ 'include' ] = wc_get_object_terms ( $product_id , $taxonomy , 'id' );
2014-09-20 19:11:49 +00:00
2014-06-03 10:58:08 +00:00
if ( empty ( $args [ 'include' ] ) ) {
$terms = array ();
} else {
2016-11-17 19:00:56 +00:00
// This isn't needed for get_terms.
2014-06-03 10:58:08 +00:00
unset ( $args [ 'orderby' ] );
2014-05-12 13:31:25 +00:00
2016-11-17 19:00:56 +00:00
// Set args for get_terms.
2014-06-03 10:58:08 +00:00
$args [ 'menu_order' ] = isset ( $args [ 'order' ] ) ? $args [ 'order' ] : 'ASC' ;
$args [ 'hide_empty' ] = isset ( $args [ 'hide_empty' ] ) ? $args [ 'hide_empty' ] : 0 ;
$args [ 'fields' ] = isset ( $args [ 'fields' ] ) ? $args [ 'fields' ] : 'names' ;
2014-06-02 15:14:51 +00:00
2016-11-17 19:00:56 +00:00
// Ensure slugs is valid for get_terms - slugs isn't supported.
2016-09-07 22:32:24 +00:00
$args [ 'fields' ] = ( 'slugs' === $args [ 'fields' ] ) ? 'id=>slug' : $args [ 'fields' ];
2014-06-03 10:58:08 +00:00
$terms = get_terms ( $taxonomy , $args );
}
2014-02-12 11:47:56 +00:00
} else {
2016-11-17 19:00:56 +00:00
$terms = _wc_get_cached_product_terms ( $product_id , $taxonomy , $args );
2013-11-25 13:30:20 +00:00
}
2015-06-08 13:41:11 +00:00
return apply_filters ( 'woocommerce_get_product_terms' , $terms , $product_id , $taxonomy , $args );
2013-09-13 11:07:54 +00:00
}
2014-11-27 14:48:58 +00:00
/**
2015-11-03 13:31:20 +00:00
* Sort by name ( numeric ) .
2014-11-27 14:48:58 +00:00
* @ param WP_POST object $a
* @ param WP_POST object $b
* @ return int
*/
function _wc_get_product_terms_name_num_usort_callback ( $a , $b ) {
if ( $a -> name + 0 === $b -> name + 0 ) {
return 0 ;
}
return ( $a -> name + 0 < $b -> name + 0 ) ? - 1 : 1 ;
}
2016-12-15 14:09:01 +00:00
2013-09-13 11:07:54 +00:00
/**
2015-11-03 13:31:20 +00:00
* Sort by parent .
2013-11-25 13:30:20 +00:00
* @ param WP_POST object $a
* @ param WP_POST object $b
* @ return int
2013-09-13 11:07:54 +00:00
*/
function _wc_get_product_terms_parent_usort_callback ( $a , $b ) {
2014-05-17 04:12:34 +00:00
if ( $a -> parent === $b -> parent ) {
2013-09-13 11:07:54 +00:00
return 0 ;
2014-05-12 13:31:25 +00:00
}
2013-09-13 11:07:54 +00:00
return ( $a -> parent < $b -> parent ) ? 1 : - 1 ;
}
2013-08-09 16:11:15 +00:00
/**
2015-11-03 13:31:20 +00:00
* WooCommerce Dropdown categories .
2013-08-09 16:11:15 +00:00
*
2016-05-27 01:48:49 +00:00
* Stuck with this until a fix for https :// core . trac . wordpress . org / ticket / 13258.
2015-11-03 13:31:20 +00:00
* We use a custom walker , just like WordPress does .
2013-08-09 16:11:15 +00:00
*
2014-09-07 23:37:55 +00:00
* @ param int $deprecated_show_uncategorized ( default : 1 )
2013-08-09 16:11:15 +00:00
* @ return string
*/
2013-11-25 13:30:20 +00:00
function wc_product_dropdown_categories ( $args = array (), $deprecated_hierarchical = 1 , $deprecated_show_uncategorized = 1 , $deprecated_orderby = '' ) {
2014-05-28 10:28:20 +00:00
global $wp_query ;
2013-08-09 16:11:15 +00:00
2013-08-20 12:32:38 +00:00
if ( ! is_array ( $args ) ) {
2016-11-23 16:15:00 +00:00
wc_deprecated_argument ( 'wc_product_dropdown_categories()' , '2.1' , 'show_counts, hierarchical, show_uncategorized and orderby arguments are invalid - pass a single array of values instead.' );
2013-08-20 12:32:38 +00:00
2015-08-25 09:48:27 +00:00
$args [ 'show_count' ] = $args ;
2013-08-20 12:32:38 +00:00
$args [ 'hierarchical' ] = $deprecated_hierarchical ;
$args [ 'show_uncategorized' ] = $deprecated_show_uncategorized ;
$args [ 'orderby' ] = $deprecated_orderby ;
}
2016-01-29 12:26:10 +00:00
$current_product_cat = isset ( $wp_query -> query_vars [ 'product_cat' ] ) ? $wp_query -> query_vars [ 'product_cat' ] : '' ;
2014-05-28 10:28:20 +00:00
$defaults = array (
2013-08-20 12:32:38 +00:00
'pad_counts' => 1 ,
2015-08-25 09:48:27 +00:00
'show_count' => 1 ,
2013-08-20 12:32:38 +00:00
'hierarchical' => 1 ,
'hide_empty' => 1 ,
'show_uncategorized' => 1 ,
'orderby' => 'name' ,
2014-05-28 10:28:20 +00:00
'selected' => $current_product_cat ,
2016-08-27 01:46:45 +00:00
'menu_order' => false ,
2013-08-20 12:32:38 +00:00
);
$args = wp_parse_args ( $args , $defaults );
2013-08-09 16:11:15 +00:00
2016-09-07 22:32:24 +00:00
if ( 'order' === $args [ 'orderby' ] ) {
2014-02-28 15:27:20 +00:00
$args [ 'menu_order' ] = 'asc' ;
$args [ 'orderby' ] = 'name' ;
}
2013-08-09 16:11:15 +00:00
2014-05-28 10:28:20 +00:00
$terms = get_terms ( 'product_cat' , apply_filters ( 'wc_product_dropdown_categories_get_terms_args' , $args ) );
2013-08-09 16:11:15 +00:00
2016-06-06 18:39:23 +00:00
if ( empty ( $terms ) ) {
2013-08-09 16:11:15 +00:00
return ;
2014-05-28 10:28:20 +00:00
}
2013-08-09 16:11:15 +00:00
2014-08-22 19:39:10 +00:00
$output = " <select name='product_cat' class='dropdown_product_cat'> " ;
2016-09-01 20:50:14 +00:00
$output .= '<option value="" ' . selected ( $current_product_cat , '' , false ) . '>' . __ ( 'Select a category' , 'woocommerce' ) . '</option>' ;
2013-11-25 13:30:20 +00:00
$output .= wc_walk_category_dropdown_tree ( $terms , 0 , $args );
2014-05-28 10:28:20 +00:00
if ( $args [ 'show_uncategorized' ] ) {
$output .= '<option value="0" ' . selected ( $current_product_cat , '0' , false ) . '>' . __ ( 'Uncategorized' , 'woocommerce' ) . '</option>' ;
}
$output .= " </select> " ;
2013-08-09 16:11:15 +00:00
echo $output ;
}
/**
* Walk the Product Categories .
*
2013-11-27 18:20:31 +00:00
* @ return mixed
2013-08-09 16:11:15 +00:00
*/
2013-11-25 13:30:20 +00:00
function wc_walk_category_dropdown_tree () {
2016-08-10 12:00:20 +00:00
$args = func_get_args ();
2014-05-28 10:28:20 +00:00
if ( ! class_exists ( 'WC_Product_Cat_Dropdown_Walker' ) ) {
2013-11-25 14:01:32 +00:00
include_once ( WC () -> plugin_path () . '/includes/walkers/class-product-cat-dropdown-walker.php' );
2014-05-28 10:28:20 +00:00
}
2013-08-09 16:11:15 +00:00
// the user's options are the third parameter
2016-09-02 01:51:31 +00:00
if ( empty ( $args [ 2 ][ 'walker' ] ) || ! is_a ( $args [ 2 ][ 'walker' ], 'Walker' ) ) {
2013-08-09 16:11:15 +00:00
$walker = new WC_Product_Cat_Dropdown_Walker ;
2014-05-28 10:28:20 +00:00
} else {
2013-08-09 16:11:15 +00:00
$walker = $args [ 2 ][ 'walker' ];
2014-05-28 10:28:20 +00:00
}
2013-08-09 16:11:15 +00:00
2014-05-28 10:28:20 +00:00
return call_user_func_array ( array ( & $walker , 'walk' ), $args );
2013-08-09 16:11:15 +00:00
}
2015-03-05 11:27:58 +00:00
/**
* When a term is split , ensure meta data maintained .
* @ param int $old_term_id
* @ param int $new_term_id
* @ param string $term_taxonomy_id
* @ param string $taxonomy
*/
function wc_taxonomy_metadata_update_content_for_split_terms ( $old_term_id , $new_term_id , $term_taxonomy_id , $taxonomy ) {
global $wpdb ;
2015-11-06 15:33:02 +00:00
if ( get_option ( 'db_version' ) < 34370 ) {
if ( 'product_cat' === $taxonomy || taxonomy_is_product_attribute ( $taxonomy ) ) {
$old_meta_data = $wpdb -> get_results ( $wpdb -> prepare ( " SELECT * FROM { $wpdb -> prefix } woocommerce_termmeta WHERE woocommerce_term_id = %d; " , $old_term_id ) );
// Copy across to split term
if ( $old_meta_data ) {
foreach ( $old_meta_data as $meta_data ) {
$wpdb -> insert (
" { $wpdb -> prefix } woocommerce_termmeta " ,
array (
'woocommerce_term_id' => $new_term_id ,
'meta_key' => $meta_data -> meta_key ,
2016-08-27 01:46:45 +00:00
'meta_value' => $meta_data -> meta_value ,
2015-11-06 15:33:02 +00:00
)
);
}
2015-03-05 11:27:58 +00:00
}
}
}
}
add_action ( 'split_shared_term' , 'wc_taxonomy_metadata_update_content_for_split_terms' , 10 , 4 );
2013-08-09 16:11:15 +00:00
/**
2015-11-06 15:33:02 +00:00
* Migrate data from WC term meta to WP term meta
*
* When the database is updated to support term meta , migrate WC term meta data across .
* We do this when the new version is >= 34370 , and the old version is < 34370 ( 34370 is when term meta table was added ) .
*
* @ param string $wp_db_version The new $wp_db_version .
* @ param string $wp_current_db_version The old ( current ) $wp_db_version .
*/
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 " );
}
}
}
2015-11-06 15:35:25 +00:00
add_action ( 'wp_upgrade' , 'wc_taxonomy_metadata_migrate_data' , 10 , 2 );
2015-11-06 15:33:02 +00:00
/**
* WooCommerce Term Meta API
*
* WC tables for storing term meta are @ deprecated from WordPress 4.4 since 4.4 has its own table .
* This function serves as a wrapper , using the new table if present , or falling back to the WC table .
*
2013-08-09 16:11:15 +00:00
* @ param mixed $term_id
2014-09-07 23:37:55 +00:00
* @ param string $meta_key
2013-08-09 16:11:15 +00:00
* @ param mixed $meta_value
* @ param string $prev_value ( default : '' )
* @ return bool
*/
function update_woocommerce_term_meta ( $term_id , $meta_key , $meta_value , $prev_value = '' ) {
2016-03-02 18:24:49 +00:00
return function_exists ( 'update_term_meta' ) ? update_term_meta ( $term_id , $meta_key , $meta_value , $prev_value ) : update_metadata ( 'woocommerce_term' , $term_id , $meta_key , $meta_value , $prev_value );
2013-08-09 16:11:15 +00:00
}
/**
2015-11-06 15:33:02 +00:00
* WooCommerce Term Meta API
*
* WC tables for storing term meta are @ deprecated from WordPress 4.4 since 4.4 has its own table .
* This function serves as a wrapper , using the new table if present , or falling back to the WC table .
*
2013-08-09 16:11:15 +00:00
* @ param mixed $term_id
* @ param mixed $meta_key
* @ param mixed $meta_value
* @ param bool $unique ( default : false )
* @ return bool
*/
2016-08-27 04:47:24 +00:00
function add_woocommerce_term_meta ( $term_id , $meta_key , $meta_value , $unique = false ) {
2016-03-02 18:24:49 +00:00
return function_exists ( 'add_term_meta' ) ? add_term_meta ( $term_id , $meta_key , $meta_value , $unique ) : add_metadata ( 'woocommerce_term' , $term_id , $meta_key , $meta_value , $unique );
2013-08-09 16:11:15 +00:00
}
/**
2015-11-06 15:33:02 +00:00
* WooCommerce Term Meta API
*
* WC tables for storing term meta are @ deprecated from WordPress 4.4 since 4.4 has its own table .
* This function serves as a wrapper , using the new table if present , or falling back to the WC table .
*
2013-08-09 16:11:15 +00:00
* @ param mixed $term_id
2016-06-06 16:50:18 +00:00
* @ param string $meta_key
2013-08-09 16:11:15 +00:00
* @ param string $meta_value ( default : '' )
2015-11-06 15:33:02 +00:00
* @ param bool $deprecated ( default : false )
2013-08-09 16:11:15 +00:00
* @ return bool
*/
2015-11-06 15:33:02 +00:00
function delete_woocommerce_term_meta ( $term_id , $meta_key , $meta_value = '' , $deprecated = false ) {
2016-03-02 18:24:49 +00:00
return function_exists ( 'delete_term_meta' ) ? delete_term_meta ( $term_id , $meta_key , $meta_value ) : delete_metadata ( 'woocommerce_term' , $term_id , $meta_key , $meta_value );
2013-08-09 16:11:15 +00:00
}
/**
2015-11-06 15:33:02 +00:00
* WooCommerce Term Meta API
*
* WC tables for storing term meta are @ deprecated from WordPress 4.4 since 4.4 has its own table .
* This function serves as a wrapper , using the new table if present , or falling back to the WC table .
*
2013-08-09 16:11:15 +00:00
* @ param mixed $term_id
2014-09-07 23:37:55 +00:00
* @ param string $key
2013-08-09 16:11:15 +00:00
* @ param bool $single ( default : true )
* @ return mixed
*/
function get_woocommerce_term_meta ( $term_id , $key , $single = true ) {
2016-03-02 18:24:49 +00:00
return function_exists ( 'get_term_meta' ) ? get_term_meta ( $term_id , $key , $single ) : get_metadata ( 'woocommerce_term' , $term_id , $key , $single );
2013-08-09 16:11:15 +00:00
}
/**
2015-11-03 13:31:20 +00:00
* Move a term before the a given element of its hierarchy level .
2013-08-09 16:11:15 +00:00
*
* @ param int $the_term
* @ param int $next_id the id of the next sibling element in save hierarchy level
* @ param string $taxonomy
* @ param int $index ( default : 0 )
* @ param mixed $terms ( default : null )
* @ return int
*/
2013-11-25 13:30:20 +00:00
function wc_reorder_terms ( $the_term , $next_id , $taxonomy , $index = 0 , $terms = null ) {
2015-11-06 15:33:02 +00:00
if ( ! $terms ) $terms = get_terms ( $taxonomy , 'menu_order=ASC&hide_empty=0&parent=0' );
if ( empty ( $terms ) ) return $index ;
2013-08-09 16:11:15 +00:00
$id = $the_term -> term_id ;
$term_in_level = false ; // flag: is our term to order in this level of terms
2015-11-06 15:33:02 +00:00
foreach ( $terms as $term ) {
2013-08-09 16:11:15 +00:00
2015-11-06 15:33:02 +00:00
if ( $term -> term_id == $id ) { // our term to order, we skip
2013-08-09 16:11:15 +00:00
$term_in_level = true ;
continue ; // our term to order, we skip
}
// the nextid of our term to order, lets move our term here
2016-08-27 04:38:29 +00:00
if ( null !== $next_id && $term -> term_id == $next_id ) {
2016-03-04 10:53:48 +00:00
$index ++ ;
2016-09-02 01:51:31 +00:00
$index = wc_set_term_order ( $id , $index , $taxonomy , true );
2013-08-09 16:11:15 +00:00
}
// set order
2016-03-04 10:53:48 +00:00
$index ++ ;
2016-09-02 01:51:31 +00:00
$index = wc_set_term_order ( $term -> term_id , $index , $taxonomy );
2013-08-09 16:11:15 +00:00
// if that term has children we walk through them
2016-09-02 01:51:31 +00:00
$children = get_terms ( $taxonomy , " parent= { $term -> term_id } &menu_order=ASC&hide_empty=0 " );
2015-11-06 15:33:02 +00:00
if ( ! empty ( $children ) ) {
2013-12-05 16:07:44 +00:00
$index = wc_reorder_terms ( $the_term , $next_id , $taxonomy , $index , $children );
2013-08-09 16:11:15 +00:00
}
}
// no nextid meaning our term is in last position
2015-11-06 15:33:02 +00:00
if ( $term_in_level && null === $next_id ) {
$index = wc_set_term_order ( $id , $index + 1 , $taxonomy , true );
}
2013-08-09 16:11:15 +00:00
return $index ;
}
/**
2015-11-03 13:31:20 +00:00
* Set the sort order of a term .
2013-08-09 16:11:15 +00:00
*
* @ param int $term_id
* @ param int $index
* @ param string $taxonomy
* @ param bool $recursive ( default : false )
* @ return int
*/
2013-11-25 13:30:20 +00:00
function wc_set_term_order ( $term_id , $index , $taxonomy , $recursive = false ) {
2013-08-09 16:11:15 +00:00
$term_id = ( int ) $term_id ;
$index = ( int ) $index ;
// Meta name
if ( taxonomy_is_product_attribute ( $taxonomy ) )
2016-08-27 06:14:06 +00:00
$meta_name = 'order_' . esc_attr ( $taxonomy );
2013-08-09 16:11:15 +00:00
else
$meta_name = 'order' ;
update_woocommerce_term_meta ( $term_id , $meta_name , $index );
2016-08-27 04:35:04 +00:00
if ( ! $recursive ) return $index ;
2013-08-09 16:11:15 +00:00
2016-09-02 01:51:31 +00:00
$children = get_terms ( $taxonomy , " parent= $term_id &menu_order=ASC&hide_empty=0 " );
2013-08-09 16:11:15 +00:00
foreach ( $children as $term ) {
2016-03-04 10:53:48 +00:00
$index ++ ;
2016-09-02 01:51:31 +00:00
$index = wc_set_term_order ( $term -> term_id , $index , $taxonomy , true );
2013-08-09 16:11:15 +00:00
}
clean_term_cache ( $term_id , $taxonomy );
return $index ;
}
/**
2015-11-03 13:31:20 +00:00
* Add term ordering to get_terms .
2013-08-09 16:11:15 +00:00
*
* It enables the support a 'menu_order' parameter to get_terms for the product_cat taxonomy .
2015-11-03 13:31:20 +00:00
* By default it is 'ASC' . It accepts 'DESC' too .
2013-08-09 16:11:15 +00:00
*
2015-11-03 13:31:20 +00:00
* To disable it , set it ot false ( or 0 ) .
2013-08-09 16:11:15 +00:00
*
* @ param array $clauses
* @ param array $taxonomies
* @ param array $args
* @ return array
*/
2013-11-25 13:30:20 +00:00
function wc_terms_clauses ( $clauses , $taxonomies , $args ) {
2014-06-08 20:33:11 +00:00
global $wpdb ;
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// No sorting when menu_order is false.
2016-12-15 14:09:01 +00:00
if ( isset ( $args [ 'menu_order' ] ) && ( false === $args [ 'menu_order' ] || 'false' === $args [ 'menu_order' ] ) ) {
2014-02-07 11:38:57 +00:00
return $clauses ;
}
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// No sorting when orderby is non default.
2016-09-07 22:32:24 +00:00
if ( isset ( $args [ 'orderby' ] ) && 'name' !== $args [ 'orderby' ] ) {
2014-02-07 11:38:57 +00:00
return $clauses ;
}
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// No sorting in admin when sorting by a column.
2014-02-07 11:38:57 +00:00
if ( is_admin () && isset ( $_GET [ 'orderby' ] ) ) {
return $clauses ;
}
2013-08-09 16:11:15 +00:00
2016-06-21 12:19:49 +00:00
// No need to filter counts
if ( strpos ( 'COUNT(*)' , $clauses [ 'fields' ] ) !== false ) {
return $clauses ;
}
2017-01-03 18:43:48 +00:00
// WordPress should give us the taxonomies asked when calling the get_terms function. Only apply to categories and pa_ attributes.
2013-08-09 16:11:15 +00:00
$found = false ;
foreach ( ( array ) $taxonomies as $taxonomy ) {
if ( taxonomy_is_product_attribute ( $taxonomy ) || in_array ( $taxonomy , apply_filters ( 'woocommerce_sortable_taxonomies' , array ( 'product_cat' ) ) ) ) {
$found = true ;
break ;
}
}
2014-02-07 11:38:57 +00:00
if ( ! $found ) {
return $clauses ;
}
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// Meta name.
2013-08-09 16:11:15 +00:00
if ( ! empty ( $taxonomies [ 0 ] ) && taxonomy_is_product_attribute ( $taxonomies [ 0 ] ) ) {
2015-11-06 15:33:02 +00:00
$meta_name = 'order_' . esc_attr ( $taxonomies [ 0 ] );
2013-08-09 16:11:15 +00:00
} else {
$meta_name = 'order' ;
}
2016-05-11 22:33:55 +00:00
// Query fields.
2017-01-03 18:43:48 +00:00
$clauses [ 'fields' ] = 'DISTINCT ' . $clauses [ 'fields' ] . ', tm.meta_value' ;
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// Query join.
2015-11-06 15:33:02 +00:00
if ( get_option ( 'db_version' ) < 34370 ) {
$clauses [ 'join' ] .= " LEFT JOIN { $wpdb -> woocommerce_termmeta } AS tm ON (t.term_id = tm.woocommerce_term_id AND tm.meta_key = ' " . esc_sql ( $meta_name ) . " ') " ;
} else {
$clauses [ 'join' ] .= " LEFT JOIN { $wpdb -> termmeta } AS tm ON (t.term_id = tm.term_id AND tm.meta_key = ' " . esc_sql ( $meta_name ) . " ') " ;
}
2013-08-09 16:11:15 +00:00
2016-05-11 22:33:55 +00:00
// Default to ASC.
if ( ! isset ( $args [ 'menu_order' ] ) || ! in_array ( strtoupper ( $args [ 'menu_order' ] ), array ( 'ASC' , 'DESC' ) ) ) {
2014-02-07 11:38:57 +00:00
$args [ 'menu_order' ] = 'ASC' ;
}
2013-08-09 16:11:15 +00:00
2016-03-04 10:53:48 +00:00
$order = " ORDER BY tm.meta_value+0 " . $args [ 'menu_order' ];
2013-08-09 16:11:15 +00:00
2015-11-06 15:33:02 +00:00
if ( $clauses [ 'orderby' ] ) {
2016-03-04 10:53:48 +00:00
$clauses [ 'orderby' ] = str_replace ( 'ORDER BY' , $order . ',' , $clauses [ 'orderby' ] );
2015-11-06 15:33:02 +00:00
} else {
2013-08-09 16:11:15 +00:00
$clauses [ 'orderby' ] = $order ;
2015-11-06 15:33:02 +00:00
}
2013-08-09 16:11:15 +00:00
return $clauses ;
}
2016-05-11 22:33:55 +00:00
2013-11-25 13:30:20 +00:00
add_filter ( 'terms_clauses' , 'wc_terms_clauses' , 10 , 3 );
2013-08-09 16:11:15 +00:00
/**
* Function for recounting product terms , ignoring hidden products .
2016-01-06 16:11:09 +00:00
* @ param array $terms
* @ param string $taxonomy
* @ param bool $callback
* @ param bool $terms_are_term_taxonomy_ids
2013-08-09 16:11:15 +00:00
*/
2013-11-25 13:30:20 +00:00
function _wc_term_recount ( $terms , $taxonomy , $callback = true , $terms_are_term_taxonomy_ids = true ) {
WIP - Product CRUD (#12065)
* Created function to get the catalog visibility options
* First methods for WP_Product crud
* Product set methods
* Fixed several erros while setting data
* First methods for WP_Product crud
* Product set methods
* Fixed several erros while setting data
* Hardcode the get_type per product class
* Initial look through getters and setters and abstract data
* Missing var
* Add related product functions and deprecate those in class.
* No need to exclude ID
* Fixed coding standards and improved the docblocks
* Get cached terms from wc_get_related_terms()
* Fixed wrong variable in wc_get_related_terms
* Use count() instead of sizeof()
* Sanitize ids later
* Remove unneeded comments
* wc_get_product_term_ids instead of related wording and use in other places.
get_the_terms is used here and also handles caching, something
wp_get_post_terms does not.
* Clean up the abstract product class a bit, deprecate two functions we have renamed, make update & create work properly, and add some tests for it.
* Bump template version
* Handle PR feedback: Remove duplicate regular_price update, allow changing of post status for products, remove deprecation for get_title since we might still offer it as a function
* Made abstract function useful
* External Product CRUD
* _virtual meta should be 'no', not taxable, in product unit test helper
* Grouped product class
* Tests
* Move children to meta and update test
* Use get_upsell_ids
* Spacing in query
* Moving and refactoring methods
* Availability html
* Tidy/add todos
* Rename method
* Put back review functions (still todo)
* missing $this
* get_price_including_tax/excluding_tax functions
* wc_get_price_to_display
* Price handling
* [Product CRUD] Variable (#12146)
* [Product CRUD] Variable Products
* Handle PR feedback.
* [Product CRUD] Grouped Handling (#12151)
* Handle grouped product saving
* Update routine
* [Product CRUD] Product crud terms (#12149)
* Category and tag id handling
* Replace template functions
* Remove todo
* Handle default name in save function
* Product crud admin save routine (#12174)
* Initial props
* Work on admin saving
* Set/get attributes
* Atom was moaning about this before but no longer.
* Update get_shipping_class
* WC_Product_Attribute
* Use getter in admin panel
* Fix attribute saving
* Spacing
* Fix comment
* wc_implode_text_attributes helper function
* [Product CRUD] Product crud admin use getters (#12196)
* Initial props
* Work on admin saving
* Set/get attributes
* Atom was moaning about this before but no longer.
* Update get_shipping_class
* WC_Product_Attribute
* Use getter in admin panel
* Fix attribute saving
* Move settings into new files
* Refactor panels and use getters
* Use getters for variation panel
* Revert save variation changes for now
* Add todos
* Fix downloads
* REST API CRUD Updates
* Additional API updates/fixes. Added some todos
* Fix final failing tests and implementing setters/getters and attributes functionality.
* Fix comparison for is_on_sale and remove download_type from WC_Product.
* Add a wc_get_products wrapper.
* Remove the download type input from the product data metabox for downloadable products. (#12221)
* [Product CRUD] Variations - setters, getters and admin. (#12228)
* Started on variation changes
* Stock functions
* Variation class
* Bulk change ->id to get_id() to fix variation form display
* Missing status
* Fix add to cart
* Start on stored data save
* save variation
* Save_variations
* Variation edit panel
* Save variations code works.
* Remove stored data code and fix save
* Improve legacy class
* wc_bool_to_string
* prepare_set_attributes
* Use wc_get_products
* More feedback fixes
* Feedback fixes
* Implement CRUD in the legacy REST API
* Handle PR feedback
* [Product CRUD] Getter setter proxy methods (#12236)
* Started on variation changes
* Stock functions
* Variation class
* Bulk change ->id to get_id() to fix variation form display
* Missing status
* Fix add to cart
* Start on stored data save
* save variation
* Save_variations
* Variation edit panel
* Save variations code works.
* Remove stored data code and fix save
* Improve legacy class
* wc_bool_to_string
* prepare_set_attributes
* Use wc_get_products
* More feedback fixes
* get_prop implementation in abstract and data classes
* Implement set_prop
* Change handling
* Array key exists
* set_object_read
* Use get_the_terms() instead of wp_get_post_terms()
wp_get_post_terms() is a wrapper around wp_get_object_terms() which does not
use the object cache, and generates a database query every time it is used.
get_the_terms() however can use data from the object cache if present.
* Allow WP_Query to preload post data, and meta in wc_get_products()
Allow WP_Query to bulk query for post data and meta if more than
just IDs are requested from wc_get_products(). Reduces query count
significantly.
* [Product CRUD] Variable, variation, notices, and stock handling (#12277)
* No longer needed
* Remove old todos
* Use getters in admin list
* Related and upsells update for CRUD
* Fix notice in gallery
* Variable fixes and todos
* Context
* Price sync
* Revert variation attributes change
* Return parent data in view context
* Defer term counting
* wc_find_matching_product_variation
* Stock manage tweaks
* Stock fixes
* Correct id
* correct id
* Better sync
* Data logic setter fix
* feedback
* First methods for WP_Product crud
* Product set methods
* Fixed several erros while setting data
* Hardcode the get_type per product class
* Initial look through getters and setters and abstract data
* Missing var
* Fixed coding standards and improved the docblocks
* Get cached terms from wc_get_related_terms()
* Fixed wrong variable in wc_get_related_terms
* Use count() instead of sizeof()
* Add related product functions and deprecate those in class.
* No need to exclude ID
* Sanitize ids later
* Clean up the abstract product class a bit, deprecate two functions we have renamed, make update & create work properly, and add some tests for it.
* Remove unneeded comments
* wc_get_product_term_ids instead of related wording and use in other places.
get_the_terms is used here and also handles caching, something
wp_get_post_terms does not.
* Handle PR feedback: Remove duplicate regular_price update, allow changing of post status for products, remove deprecation for get_title since we might still offer it as a function
* External Product CRUD
* _virtual meta should be 'no', not taxable, in product unit test helper
* Bump template version
* Made abstract function useful
* Grouped product class
* Tests
* Move children to meta and update test
* Use get_upsell_ids
* Spacing in query
* Moving and refactoring methods
* Availability html
* Tidy/add todos
* Rename method
* Put back review functions (still todo)
* missing $this
* get_price_including_tax/excluding_tax functions
* wc_get_price_to_display
* Price handling
* [Product CRUD] Variable (#12146)
* [Product CRUD] Variable Products
* Handle PR feedback.
* [Product CRUD] Grouped Handling (#12151)
* Handle grouped product saving
* Update routine
* [Product CRUD] Product crud terms (#12149)
* Category and tag id handling
* Replace template functions
* Remove todo
* Handle default name in save function
* Product crud admin save routine (#12174)
* Initial props
* Work on admin saving
* Set/get attributes
* Atom was moaning about this before but no longer.
* Update get_shipping_class
* WC_Product_Attribute
* Use getter in admin panel
* Fix attribute saving
* Spacing
* Fix comment
* wc_implode_text_attributes helper function
* [Product CRUD] Product crud admin use getters (#12196)
* Initial props
* Work on admin saving
* Set/get attributes
* Atom was moaning about this before but no longer.
* Update get_shipping_class
* WC_Product_Attribute
* Use getter in admin panel
* Fix attribute saving
* Move settings into new files
* Refactor panels and use getters
* Use getters for variation panel
* Revert save variation changes for now
* Add todos
* Fix downloads
* REST API CRUD Updates
* Additional API updates/fixes. Added some todos
* Fix final failing tests and implementing setters/getters and attributes functionality.
* Fix comparison for is_on_sale and remove download_type from WC_Product.
* Add a wc_get_products wrapper.
* Remove the download type input from the product data metabox for downloadable products. (#12221)
* [Product CRUD] Variations - setters, getters and admin. (#12228)
* Started on variation changes
* Stock functions
* Variation class
* Bulk change ->id to get_id() to fix variation form display
* Missing status
* Fix add to cart
* Start on stored data save
* save variation
* Save_variations
* Variation edit panel
* Save variations code works.
* Remove stored data code and fix save
* Improve legacy class
* wc_bool_to_string
* prepare_set_attributes
* Use wc_get_products
* More feedback fixes
* Feedback fixes
* Implement CRUD in the legacy REST API
* Handle PR feedback
* [Product CRUD] Getter setter proxy methods (#12236)
* Started on variation changes
* Stock functions
* Variation class
* Bulk change ->id to get_id() to fix variation form display
* Missing status
* Fix add to cart
* Start on stored data save
* save variation
* Save_variations
* Variation edit panel
* Save variations code works.
* Remove stored data code and fix save
* Improve legacy class
* wc_bool_to_string
* prepare_set_attributes
* Use wc_get_products
* More feedback fixes
* get_prop implementation in abstract and data classes
* Implement set_prop
* Change handling
* Array key exists
* set_object_read
* Use get_the_terms() instead of wp_get_post_terms()
wp_get_post_terms() is a wrapper around wp_get_object_terms() which does not
use the object cache, and generates a database query every time it is used.
get_the_terms() however can use data from the object cache if present.
* [Product CRUD] Variable, variation, notices, and stock handling (#12277)
* No longer needed
* Remove old todos
* Use getters in admin list
* Related and upsells update for CRUD
* Fix notice in gallery
* Variable fixes and todos
* Context
* Price sync
* Revert variation attributes change
* Return parent data in view context
* Defer term counting
* wc_find_matching_product_variation
* Stock manage tweaks
* Stock fixes
* Correct id
* correct id
* Better sync
* Data logic setter fix
* feedback
* Prevent notices
* Handle image_id from parent
* Fix error
* Remove _wc_save_product_price
* Remove todo
* Fixed wrong variation URLs
* Fixed undefined $image_id in WC_Product_Variation::get_image_id()
* Allow wc_rest_prepare_date_response() handle timestamps
* Updated get methods on REST API for variations
* Use variations CRUD to save variations metadata
* [Product CRUD] Abstract todos (#12305)
* Get dimensions and weights, with soft deprecation
* Product attributes
* Ratings
* Fix read method
* Downloads
* Feedback
* Revert "[Product CRUD] Abstract todos (#12305)"
This reverts commit 9a6136fcf88fec16f97457b7c8a4388f7587bfa2.
* Remove deprecated get_variation_id()
* New default attributes method
* [Product CRUD] Product Datastore (#12317)
* Fix up tests in the product/* folder.
* Handle data store updates for grouped, variable, external, simple, and general data store updates for products.
* Variations & variable changes.
* Update -functions.php calls to use data store.
* Add an interface for the public product data store methods.
* Finished product factory tests
* Correctly delete in the api, fix up some comments, and implement an interface for the public variable methods.
* Fix up delete in all versions of the api
* Handle feedback
* Match protected decloration to parent
* Product crud abstract todos (#12316)
* Get dimensions and weights, with soft deprecation
* Product attributes
* Ratings
* Fix read method
* Downloads
* Feedback
* Fix up store
* Fixed method returning in write context
* Fix error in variation admin
* Check for parent value - fixes tax class
* Remove old/complete todos
* Allow set tax class as "parent"
* Removed duplicated sync
* Fixed wrong variation URLs
* Fixed undefined $image_id in WC_Product_Variation::get_image_id()
* Allow wc_rest_prepare_date_response() handle timestamps
* Updated get methods on REST API for variations
* Use variations CRUD to save variations metadata
* Remove deprecated get_variation_id()
* New default attributes method
* Fixed method returning in write context
* Allow set tax class as "parent"
* Removed duplicated sync
* Fixed coding standards
* TODO is not accurate.
* Should pass WC_Product instancies to WC_Comments methods (#12327)
* Use new method in abstract order class to prevent headers sent issue in tests
* Fixed variable description in REST API
* Updated how create initial product variation
* Fixed a few fatal errors and warnings in Products CRUD (#12329)
* Fixed a few fatal errors and warnings in Products CRUD
* Fixed sync functions
* Add variations CRUD to legacy API (#12331)
* Apply crud to variable products in legacy API v1
* New REST API do not need fallback for default attributes
* Apply variations CRUD to legacy API v2
* Legacy v2 - save default attributes
* Variations in legacy API v2 do not have descriptions
* Fixed legacy API v2 variations params
* Applied variations CRUD to legacy API v3
* Sync before save in legacy apis
* Punc
* Removed API todos
* Removed test
* Products endpoint tweaks (#12354)
* Var type already normalized on CRUD
* Let Product CRUD handle with validation, sanitization and conditional checks
* Set downloads using WC_Product_Download
* Stop try catch exceptions more than one time
* Handle WC_Data_Exception in legacy API
* Complete remove products when fails on creating
* On creating I mean!
* Already have a method to complete delete products
* Fixed standards using WP CodeSniffer
* get_the_terms() returns false when empty
* get_manage_stock returns boolean
@claudiosanches
* Merge conflict
* Variations API endpoint fixes
* Product CRUD improvements (#12359)
* args is not used any more - remove todo
* Added test for attributes
* wc_get_price_excluding_tax usage
* parent usage
* Fix rating counts
* Test fixes
* Cleanup after tests
* Make sure status transition code runs even during API calls, not just in admin.
* Default visibility
* Fix attribute setting in API
* Use get name instead of get title
* variation id usage
* Improved cross sell templates
* variation_data
* Grouped product sync
* Notices
* Sync is not needed in API
* Delete
* Rename interfaces
* Update counts in data store
2016-11-16 12:38:24 +00:00
global $wpdb , $wc_allow_term_recount ;
// Don't recount unless CRUD is calling this.
if ( empty ( $wc_allow_term_recount ) ) {
return ;
}
2013-08-09 16:11:15 +00:00
// Standard callback
2014-03-17 14:38:09 +00:00
if ( $callback ) {
2013-08-09 16:11:15 +00:00
_update_post_term_count ( $terms , $taxonomy );
2014-03-17 14:38:09 +00:00
}
2013-08-09 16:11:15 +00:00
// Main query
2013-10-22 15:20:40 +00:00
$count_query = "
2013-08-09 16:11:15 +00:00
SELECT COUNT ( DISTINCT posts . ID ) FROM { $wpdb -> posts } as posts
2014-02-13 14:51:43 +00:00
LEFT JOIN { $wpdb -> term_relationships } AS rel ON posts . ID = rel . object_ID
LEFT JOIN { $wpdb -> term_taxonomy } AS tax USING ( term_taxonomy_id )
2013-10-22 15:20:40 +00:00
WHERE post_status = 'publish'
AND post_type = 'product'
" ;
2013-08-09 16:11:15 +00:00
2016-12-08 17:01:39 +00:00
$product_visibility_term_ids = wc_get_product_visibility_term_ids ();
if ( $product_visibility_term_ids [ 'exclude-from-catalog' ] ) {
2016-12-12 13:10:29 +00:00
$count_query .= " AND term_taxonomy_id != " . $product_visibility_term_ids [ 'exclude-from-catalog' ];
2016-12-08 10:56:45 +00:00
}
2016-12-08 17:01:39 +00:00
if ( 'yes' === get_option ( 'woocommerce_hide_out_of_stock_items' ) && $product_visibility_term_ids [ 'outofstock' ] ) {
2016-12-12 13:10:29 +00:00
$count_query .= " AND term_taxonomy_id != " . $product_visibility_term_ids [ 'outofstock' ];
2016-12-08 10:56:45 +00:00
}
2013-08-09 16:11:15 +00:00
// Pre-process term taxonomy ids
2014-03-17 14:38:09 +00:00
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 ;
}
}
2013-08-09 16:11:15 +00:00
2014-03-17 14:38:09 +00:00
// Exit if we have no terms to count
2016-06-06 18:39:23 +00:00
if ( empty ( $terms ) ) {
2014-03-17 14:38:09 +00:00
return ;
}
2013-08-09 16:11:15 +00:00
2013-10-22 15:20:40 +00:00
// Ancestors need counting
2014-03-17 14:38:09 +00:00
if ( is_taxonomy_hierarchical ( $taxonomy -> name ) ) {
2013-10-22 15:20:40 +00:00
foreach ( $terms as $term_id ) {
2013-10-29 11:29:17 +00:00
$terms = array_merge ( $terms , get_ancestors ( $term_id , $taxonomy -> name ) );
2013-08-09 16:11:15 +00:00
}
}
2014-03-17 14:38:09 +00:00
// Unique terms only
2013-10-22 15:20:40 +00:00
$terms = array_unique ( $terms );
2013-08-09 16:11:15 +00:00
2013-10-22 15:20:40 +00:00
// Count the terms
2014-03-17 14:38:09 +00:00
foreach ( $terms as $term_id ) {
$terms_to_count = array ( absint ( $term_id ) );
2013-08-09 16:11:15 +00:00
2014-03-17 14:38:09 +00:00
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 ) ) );
2013-10-22 15:20:40 +00:00
}
2014-03-17 14:38:09 +00:00
}
2013-08-09 16:11:15 +00:00
2014-03-17 14:38:09 +00:00
// Generate term query
2016-12-12 13:10:29 +00:00
$term_query = ' AND term_id IN ( ' . implode ( ',' , $terms_to_count ) . ' )' ;
2013-08-09 16:11:15 +00:00
2014-03-17 14:38:09 +00:00
// Get the count
$count = $wpdb -> get_var ( $count_query . $term_query );
2013-08-09 16:11:15 +00:00
2014-03-17 14:38:09 +00:00
// Update the count
update_woocommerce_term_meta ( $term_id , 'product_count_' . $taxonomy -> name , absint ( $count ) );
2013-08-09 16:11:15 +00:00
}
2014-06-19 10:38:57 +00:00
delete_transient ( 'wc_term_counts' );
2013-08-09 16:11:15 +00:00
}
/**
2015-11-03 13:31:20 +00:00
* Recount terms after the stock amount changes .
2015-07-16 19:55:48 +00:00
*
* @ param int $product_id
2013-08-09 16:11:15 +00:00
*/
2013-11-25 13:30:20 +00:00
function wc_recount_after_stock_change ( $product_id ) {
2016-12-08 10:56:45 +00:00
if ( 'yes' !== get_option ( 'woocommerce_hide_out_of_stock_items' ) ) {
2013-10-22 15:20:40 +00:00
return ;
2016-12-08 10:56:45 +00:00
}
2013-08-09 16:11:15 +00:00
$product_terms = get_the_terms ( $product_id , 'product_cat' );
if ( $product_terms ) {
2014-11-19 19:01:06 +00:00
$product_cats = array ();
foreach ( $product_terms as $term ) {
2013-08-09 16:11:15 +00:00
$product_cats [ $term -> term_id ] = $term -> parent ;
2014-11-19 19:01:06 +00:00
}
2013-08-09 16:11:15 +00:00
2013-11-25 13:30:20 +00:00
_wc_term_recount ( $product_cats , get_taxonomy ( 'product_cat' ), false , false );
2013-08-09 16:11:15 +00:00
}
$product_terms = get_the_terms ( $product_id , 'product_tag' );
if ( $product_terms ) {
2014-11-19 19:01:06 +00:00
$product_tags = array ();
foreach ( $product_terms as $term ) {
2013-08-09 16:11:15 +00:00
$product_tags [ $term -> term_id ] = $term -> parent ;
2014-11-19 19:01:06 +00:00
}
2013-08-09 16:11:15 +00:00
2013-11-25 13:30:20 +00:00
_wc_term_recount ( $product_tags , get_taxonomy ( 'product_tag' ), false , false );
2013-08-09 16:11:15 +00:00
}
}
2013-11-25 13:30:20 +00:00
add_action ( 'woocommerce_product_set_stock_status' , 'wc_recount_after_stock_change' );
2013-08-09 16:11:15 +00:00
/**
2015-11-03 13:31:20 +00:00
* Overrides the original term count for product categories and tags with the product count .
2013-08-09 16:11:15 +00:00
* that takes catalog visibility into account .
*
* @ param array $terms
2014-11-20 00:43:09 +00:00
* @ param string | array $taxonomies
2013-08-09 16:11:15 +00:00
* @ return array
*/
2014-11-20 00:43:09 +00:00
function wc_change_term_counts ( $terms , $taxonomies ) {
2014-03-17 16:52:06 +00:00
if ( is_admin () || is_ajax () ) {
2013-08-09 16:11:15 +00:00
return $terms ;
2014-03-17 16:52:06 +00:00
}
2013-08-09 16:11:15 +00:00
2014-03-17 16:52:06 +00:00
if ( ! isset ( $taxonomies [ 0 ] ) || ! in_array ( $taxonomies [ 0 ], apply_filters ( 'woocommerce_change_term_counts' , array ( 'product_cat' , 'product_tag' ) ) ) ) {
2013-08-09 16:11:15 +00:00
return $terms ;
2014-03-17 16:52:06 +00:00
}
2013-08-09 16:11:15 +00:00
$term_counts = $o_term_counts = get_transient ( 'wc_term_counts' );
foreach ( $terms as & $term ) {
2014-03-17 16:52:06 +00:00
if ( is_object ( $term ) ) {
$term_counts [ $term -> term_id ] = isset ( $term_counts [ $term -> term_id ] ) ? $term_counts [ $term -> term_id ] : get_woocommerce_term_meta ( $term -> term_id , 'product_count_' . $taxonomies [ 0 ] , true );
2013-08-09 16:11:15 +00:00
2016-09-07 22:32:24 +00:00
if ( '' !== $term_counts [ $term -> term_id ] ) {
2014-03-17 16:52:06 +00:00
$term -> count = absint ( $term_counts [ $term -> term_id ] );
}
}
2013-08-09 16:11:15 +00:00
}
// Update transient
2014-03-17 16:52:06 +00:00
if ( $term_counts != $o_term_counts ) {
2015-02-24 12:02:56 +00:00
set_transient ( 'wc_term_counts' , $term_counts , DAY_IN_SECONDS * 30 );
2014-03-17 16:52:06 +00:00
}
2013-08-09 16:11:15 +00:00
return $terms ;
}
2014-11-20 00:43:09 +00:00
add_filter ( 'get_terms' , 'wc_change_term_counts' , 10 , 2 );
2015-11-14 16:25:09 +00:00
/**
* Return products in a given term , and cache value .
*
* To keep in sync , product_count will be cleared on " set_object_terms " .
*
* @ param int $term_id
* @ param string $taxonomy
* @ return array
*/
function wc_get_term_product_ids ( $term_id , $taxonomy ) {
$product_ids = get_woocommerce_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_woocommerce_term_meta ( $term_id , 'product_ids' , $product_ids );
}
return $product_ids ;
}
/**
* When a post is updated and terms recounted ( called by _update_post_term_count ), clear the ids .
* @ param int $object_id Object ID .
* @ param array $terms An array of object terms .
* @ param array $tt_ids An array of term taxonomy IDs .
* @ param string $taxonomy Taxonomy slug .
* @ param bool $append Whether to append new terms to the old terms .
* @ param array $old_tt_ids Old array of term taxonomy 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_woocommerce_term_meta ( $term_id , 'product_ids' );
}
foreach ( $tt_ids as $term_id ) {
delete_woocommerce_term_meta ( $term_id , 'product_ids' );
}
}
add_action ( 'set_object_terms' , 'wc_clear_term_product_ids' , 10 , 6 );
2016-12-08 17:01:39 +00:00
/**
* Get full list of product visibilty term ids .
*
* @ since 2.7 . 0
* @ return int []
*/
function wc_get_product_visibility_term_ids () {
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 ,
2016-12-09 15:43:25 +00:00
'rated-1' => 0 ,
'rated-2' => 0 ,
'rated-3' => 0 ,
'rated-4' => 0 ,
'rated-5' => 0 ,
2016-12-08 17:01:39 +00:00
)
) );
}