Store rating and reviews in postmeta rather than transients

These don’t change often, and as long as we listen for comment count
update events will be kept in sync.
This commit is contained in:
Mike Jolley 2015-11-13 20:41:20 +00:00
parent 70d9f58811
commit 3ceed757bd
2 changed files with 29 additions and 39 deletions

View File

@ -1044,22 +1044,15 @@ class WC_Product {
} }
/** /**
* Get the average rating of product. * Get the average rating of product. This is calculated once and stored in postmeta.
*
* @return string * @return string
*/ */
public function get_average_rating() { public function get_average_rating() {
$transient_name = 'wc_average_rating_' . $this->id . WC_Cache_Helper::get_transient_version( 'product' ); global $wpdb;
if ( false === ( $average_rating = get_transient( $transient_name ) ) ) {
global $wpdb;
$average_rating = '';
$count = $this->get_rating_count();
if ( $count > 0 ) {
// No meta date? Do the calculation
if ( ! metadata_exists( 'post', $this->id, '_wc_average_rating' ) ) {
if ( $count = $this->get_rating_count() ) {
$ratings = $wpdb->get_var( $wpdb->prepare(" $ratings = $wpdb->get_var( $wpdb->prepare("
SELECT SUM(meta_value) FROM $wpdb->commentmeta SELECT SUM(meta_value) FROM $wpdb->commentmeta
LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID
@ -1068,28 +1061,28 @@ class WC_Product {
AND comment_approved = '1' AND comment_approved = '1'
AND meta_value > 0 AND meta_value > 0
", $this->id ) ); ", $this->id ) );
$average = number_format( $ratings / $count, 2 );
$average_rating = number_format( $ratings / $count, 2 ); } else {
$average = 0;
} }
update_post_meta( $this->id, '_wc_average_rating', $average );
set_transient( $transient_name, $average_rating, DAY_IN_SECONDS * 30 ); } else {
$average = get_post_meta( $this->id, '_wc_average_rating', true );
} }
return $average_rating; return $average;
} }
/** /**
* Get the total amount (COUNT) of ratings. * Get the total amount (COUNT) of ratings.
* * @param int $value Optional. Rating value to get the count for. By default returns the count of all rating values.
* @param int $value Optional. Rating value to get the count for. By default
* returns the count of all rating values.
* @return int * @return int
*/ */
public function get_rating_count( $value = null ) { public function get_rating_count( $value = null ) {
$transient_name = 'wc_rating_count_' . $this->id . WC_Cache_Helper::get_transient_version( 'product' ); global $wpdb;
if ( ! is_array( $counts = get_transient( $transient_name ) ) ) { // No meta date? Do the calculation
global $wpdb; if ( ! metadata_exists( 'post', $this->id, '_wc_rating_count' ) ) {
$counts = array(); $counts = array();
$raw_counts = $wpdb->get_results( $wpdb->prepare(" $raw_counts = $wpdb->get_results( $wpdb->prepare("
SELECT meta_value, COUNT( * ) as meta_value_count FROM $wpdb->commentmeta SELECT meta_value, COUNT( * ) as meta_value_count FROM $wpdb->commentmeta
@ -1105,7 +1098,9 @@ class WC_Product {
$counts[ $count->meta_value ] = $count->meta_value_count; $counts[ $count->meta_value ] = $count->meta_value_count;
} }
set_transient( $transient_name, $counts, DAY_IN_SECONDS * 30 ); update_post_meta( $this->id, '_wc_rating_count', $counts );
} else {
$counts = get_post_meta( $this->id, '_wc_rating_count', true );
} }
if ( is_null( $value ) ) { if ( is_null( $value ) ) {
@ -1141,7 +1136,6 @@ class WC_Product {
return apply_filters( 'woocommerce_product_get_rating_html', $rating_html, $rating ); return apply_filters( 'woocommerce_product_get_rating_html', $rating_html, $rating );
} }
/** /**
* Get the total amount (COUNT) of reviews. * Get the total amount (COUNT) of reviews.
* *
@ -1149,13 +1143,10 @@ class WC_Product {
* @return int The total numver of product reviews * @return int The total numver of product reviews
*/ */
public function get_review_count() { public function get_review_count() {
global $wpdb;
$transient_name = 'wc_review_count_' . $this->id . WC_Cache_Helper::get_transient_version( 'product' ); // No meta date? Do the calculation
if ( ! metadata_exists( 'post', $this->id, '_wc_review_count' ) ) {
if ( false === ( $count = get_transient( $transient_name ) ) ) {
global $wpdb;
$count = $wpdb->get_var( $wpdb->prepare(" $count = $wpdb->get_var( $wpdb->prepare("
SELECT COUNT(*) FROM $wpdb->comments SELECT COUNT(*) FROM $wpdb->comments
WHERE comment_parent = 0 WHERE comment_parent = 0
@ -1163,13 +1154,14 @@ class WC_Product {
AND comment_approved = '1' AND comment_approved = '1'
", $this->id ) ); ", $this->id ) );
set_transient( $transient_name, $count, DAY_IN_SECONDS * 30 ); update_post_meta( $this->id, '_wc_review_count', $count );
} else {
$count = get_post_meta( $this->id, '_wc_review_count', true );
} }
return apply_filters( 'woocommerce_product_review_count', $count, $this ); return apply_filters( 'woocommerce_product_review_count', $count, $this );
} }
/** /**
* Returns the upsell product ids. * Returns the upsell product ids.
* *

View File

@ -226,15 +226,13 @@ class WC_Comments {
} }
/** /**
* Clear transients for a review. * Ensure product average rating and review count is kept up to date.
* @param int $post_id * @param int $post_id
*/ */
public static function clear_transients( $post_id ) { public static function clear_transients( $post_id ) {
$post_id = absint( $post_id ); delete_post_meta( $post_id, '_wc_average_rating' );
$transient_version = WC_Cache_Helper::get_transient_version( 'product' ); delete_post_meta( $post_id, '_wc_rating_count' );
delete_transient( 'wc_average_rating_' . $post_id . $transient_version ); delete_post_meta( $post_id, '_wc_review_count' );
delete_transient( 'wc_rating_count_' . $post_id . $transient_version );
delete_transient( 'wc_review_count_' . $post_id . $transient_version );
} }
/** /**