Fix average product rating when ratings are not required

If ratings are not required, the total rating count was counting all
reviews which skewed the average rating. In other words, reviews with
no rating were counted as a “zero” rating in the average rating
calculation. This bug was introduced in
83a457b29c which provided a fix for #6839.

This change introduces a new product method `get_review_count()` which
can be used to accurately calculate the total number of reviews for a
product. Some instances of `get_rating_count()` were replaced with
`get_review_count()` where appropriate. Additionally, the
`single-product/rating.php` template was adjusted to display the
correct number of customer reviews and ratings in rich snippets. I’ve
also included the `bestRating` rich snippet detailed
[here](http://schema.org/AggregateRating). The version number was
adjusted to 2.3.2 on that template as I think this is a larger change.
This commit is contained in:
Tamara Zuk 2015-02-11 17:55:16 -05:00
parent dd0d8b7b26
commit 7eaae2d561
5 changed files with 47 additions and 29 deletions

View File

@ -1072,26 +1072,13 @@ class WC_Product {
$where_meta_value = $value ? $wpdb->prepare( " AND meta_value = %d", $value ) : " AND meta_value > 0";
if ( get_option( 'woocommerce_enable_review_rating' ) == 'yes' && get_option( 'woocommerce_review_rating_required' ) == 'yes' ) {
$count = $wpdb->get_var( $wpdb->prepare("
SELECT COUNT(meta_value) FROM $wpdb->commentmeta
LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID
WHERE meta_key = 'rating'
AND comment_post_ID = %d
AND comment_approved = '1'
", $this->id ) . $where_meta_value );
} else {
$count = $wpdb->get_var( $wpdb->prepare("
SELECT COUNT(*) FROM $wpdb->comments
WHERE comment_parent = 0
AND comment_post_ID = %d
AND comment_approved = '1'
", $this->id ) );
}
$count = $wpdb->get_var( $wpdb->prepare("
SELECT COUNT(meta_value) FROM $wpdb->commentmeta
LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID
WHERE meta_key = 'rating'
AND comment_post_ID = %d
AND comment_approved = '1'
", $this->id ) . $where_meta_value );
set_transient( $transient_name, $count, YEAR_IN_SECONDS );
}
@ -1126,6 +1113,34 @@ class WC_Product {
}
/**
* Get the total amount (COUNT) of reviews.
*
* @since 2.3.2
* @return int The total numver of product reviews
*/
public function get_review_count() {
$transient_name = 'wc_review_count_' . $this->id . WC_Cache_Helper::get_transient_version( 'product' );
if ( false === ( $count = get_transient( $transient_name ) ) ) {
global $wpdb;
$count = $wpdb->get_var( $wpdb->prepare("
SELECT COUNT(*) FROM $wpdb->comments
WHERE comment_parent = 0
AND comment_post_ID = %d
AND comment_approved = '1'
", $this->id ) );
set_transient( $transient_name, $count, YEAR_IN_SECONDS );
}
return apply_filters( 'woocommerce_product_review_count', $count, $this );
}
/**
* Returns the upsell product ids.
*

View File

@ -217,6 +217,7 @@ class WC_Comments {
delete_transient( 'wc_rating_count_' . $post_id . '_3' . $transient_version );
delete_transient( 'wc_rating_count_' . $post_id . '_4' . $transient_version );
delete_transient( 'wc_rating_count_' . $post_id . '_5' . $transient_version );
delete_transient( 'wc_review_count_' . $post_id . $transient_version );
}
/**

View File

@ -964,7 +964,7 @@ if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
// Reviews tab - shows comments
if ( comments_open() ) {
$tabs['reviews'] = array(
'title' => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_rating_count() ),
'title' => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ),
'priority' => 30,
'callback' => 'comments_template'
);

View File

@ -4,7 +4,7 @@
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.1.0
* @version 2.3.2
*/
global $product;
@ -20,7 +20,7 @@ if ( ! comments_open() ) {
<div id="reviews">
<div id="comments">
<h2><?php
if ( get_option( 'woocommerce_enable_review_rating' ) === 'yes' && ( $count = $product->get_rating_count() ) )
if ( get_option( 'woocommerce_enable_review_rating' ) === 'yes' && ( $count = $product->get_review_count() ) )
printf( _n( '%s review for %s', '%s reviews for %s', $count, 'woocommerce' ), $count, get_the_title() );
else
_e( 'Reviews', 'woocommerce' );

View File

@ -4,7 +4,7 @@
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.2.6
* @version 2.3.2
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -17,18 +17,20 @@ if ( get_option( 'woocommerce_enable_review_rating' ) === 'no' ) {
return;
}
$count = $product->get_rating_count();
$average = $product->get_average_rating();
$rating_count = $product->get_rating_count();
$review_count = $product->get_review_count();
$average = $product->get_average_rating();
if ( $count > 0 ) : ?>
if ( $rating_count > 0 ) : ?>
<div class="woocommerce-product-rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<div class="star-rating" title="<?php printf( __( 'Rated %s out of 5', 'woocommerce' ), $average ); ?>">
<span style="width:<?php echo ( ( $average / 5 ) * 100 ); ?>%">
<strong itemprop="ratingValue" class="rating"><?php echo esc_html( $average ); ?></strong> <?php _e( 'out of 5', 'woocommerce' ); ?>
<strong itemprop="ratingValue" class="rating"><?php echo esc_html( $average ); ?></strong> <?php printf( __( 'out of %s5%s', 'woocommerce' ), '<span itemprop="bestRating">', '</span>' ); ?>
<?php printf( _n( 'based on %s customer rating', 'based on %s customer ratings', $rating_count, 'woocommerce' ), '<span itemprop="ratingCount" class="rating">' . $rating_count . '</span>' ); ?>
</span>
</div>
<?php if ( comments_open() ) : ?><a href="#reviews" class="woocommerce-review-link" rel="nofollow">(<?php printf( _n( '%s customer review', '%s customer reviews', $count, 'woocommerce' ), '<span itemprop="ratingCount" class="count">' . $count . '</span>' ); ?>)</a><?php endif ?>
<?php if ( comments_open() ) : ?><a href="#reviews" class="woocommerce-review-link" rel="nofollow">(<?php printf( _n( '%s customer review', '%s customer reviews', $review_count, 'woocommerce' ), '<span itemprop="reviewCount" class="count">' . $review_count . '</span>' ); ?>)</a><?php endif ?>
</div>
<?php endif; ?>