From 6892d73ea939cbe93ceb87da871670df57e3c3bd Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Sat, 14 Nov 2015 16:25:09 +0000 Subject: [PATCH] Store product ids for terms in term meta rather than transient Data is kept in sync by looking at when terms are set for an object and then clearing the meta for old and new terms. --- includes/wc-term-functions.php | 40 +++++++++++++++++++ includes/wc-user-functions.php | 8 ++-- .../widgets/class-wc-widget-layered-nav.php | 28 +++---------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/includes/wc-term-functions.php b/includes/wc-term-functions.php index 115ccd992cc..d36ff54b6a0 100644 --- a/includes/wc-term-functions.php +++ b/includes/wc-term-functions.php @@ -623,3 +623,43 @@ function wc_change_term_counts( $terms, $taxonomies ) { return $terms; } add_filter( 'get_terms', 'wc_change_term_counts', 10, 2 ); + +/** + * 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 $term_id + * @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 ); diff --git a/includes/wc-user-functions.php b/includes/wc-user-functions.php index 1421b6700f3..448b24aebb3 100644 --- a/includes/wc-user-functions.php +++ b/includes/wc-user-functions.php @@ -206,10 +206,8 @@ function wc_paying_customer( $order_id ) { } add_action( 'woocommerce_order_status_completed', 'wc_paying_customer' ); - /** - * Checks if a user (by email) has bought an item. - * + * Checks if a user (by email or ID or both) has bought an item. * @param string $customer_email * @param int $user_id * @param int $product_id @@ -252,11 +250,11 @@ function wc_customer_bought_product( $customer_email, $user_id, $product_id ) { AND im.meta_value != 0 AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' ) " ); - $result = array_map( 'intval', $result ); + $result = array_map( 'absint', $result ); set_transient( $transient_name, $result, DAY_IN_SECONDS * 30 ); } - return in_array( (int) $product_id, $result ); + return in_array( absint( $product_id ), $result ); } /** diff --git a/includes/widgets/class-wc-widget-layered-nav.php b/includes/widgets/class-wc-widget-layered-nav.php index 82f15fff62a..26abf96bad3 100644 --- a/includes/widgets/class-wc-widget-layered-nav.php +++ b/includes/widgets/class-wc-widget-layered-nav.php @@ -187,17 +187,9 @@ class WC_Widget_Layered_Nav extends WC_Widget { continue; } - // Get count based on current view - uses transients - $transient_name = 'wc_ln_count_' . md5( sanitize_key( $taxonomy ) . sanitize_key( $term->term_taxonomy_id ) ); - - if ( false === ( $_products_in_term = get_transient( $transient_name ) ) ) { - - $_products_in_term = get_objects_in_term( $term->term_id, $taxonomy ); - - set_transient( $transient_name, $_products_in_term, DAY_IN_SECONDS * 30 ); - } - - $option_is_set = ( isset( $_chosen_attributes[ $taxonomy ] ) && in_array( $term->term_id, $_chosen_attributes[ $taxonomy ]['terms'] ) ); + // Get count based on current view + $_products_in_term = wc_get_term_product_ids( $term->term_id, $taxonomy ); + $option_is_set = ( isset( $_chosen_attributes[ $taxonomy ] ) && in_array( $term->term_id, $_chosen_attributes[ $taxonomy ]['terms'] ) ); // If this is an AND query, only show options with count > 0 if ( 'and' == $query_type ) { @@ -245,16 +237,8 @@ class WC_Widget_Layered_Nav extends WC_Widget { foreach ( $terms as $term ) { // Get count based on current view - uses transients - $transient_name = 'wc_ln_count_' . md5( sanitize_key( $taxonomy ) . sanitize_key( $term->term_taxonomy_id ) ); - - if ( false === ( $_products_in_term = get_transient( $transient_name ) ) ) { - - $_products_in_term = get_objects_in_term( $term->term_id, $taxonomy ); - - set_transient( $transient_name, $_products_in_term ); - } - - $option_is_set = ( isset( $_chosen_attributes[ $taxonomy ] ) && in_array( $term->term_id, $_chosen_attributes[ $taxonomy ]['terms'] ) ); + $_products_in_term = wc_get_term_product_ids( $term->term_id, $taxonomy ); + $option_is_set = ( isset( $_chosen_attributes[ $taxonomy ] ) && in_array( $term->term_id, $_chosen_attributes[ $taxonomy ]['terms'] ) ); // skip the term for the current archive if ( $current_term == $term->term_id ) { @@ -396,7 +380,7 @@ class WC_Widget_Layered_Nav extends WC_Widget { } // End display type conditional $this->widget_end( $args ); - + if ( ! $found ) { ob_end_clean(); } else {