Drupal Answers is a question and answer site for Drupal developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

When using the Fivestar module, I can show the result in three ways:

1) "Stars" - This has an additional setting called "Text to display under the stars". For example, it'll look like the following if I choose "Average vote":

*****
Average: 4.1 (235 votes)

2) "Rating" - There is no additional option whatsoever, so the above example will just look like the following:

4.1/5

3) "Percentage" - I don't use this, so let's just ignore it.

Is there a way to make the "Rating" option show the total number of votes like the following?

4.1/5 (235 votes)

UPDATE 1:

I have to overwrite the function theme_fivestar_summary on line 126, and add lines 279-301 right before return $output;:

function theme_fivestar_formatter_rating($variables) {
  $element = $variables['element'];

  if (empty($element['#item']['average'])) {
    $element['#item']['average'] = 0;
  }
  // Get number of stars.
  $stars = (empty($element['#instance_settings']['stars'])) ? 5 : $element['#instance_settings']['stars'];
  $average = $element['#item']['average'];
  // Rating is X out of Y stars.
  $rating = round(($average/100) * $stars, 1);
  $output = $rating . '/' . $stars;

  $votes = 235;
  if (isset($votes)) {
    if (!isset($user_rating) && !isset($average_rating)) {
      $div_class = 'count';
    }
    if ($votes === 0) {
      $output = '<span class="empty">'. t('No votes yet') .'</span>';
    }
    else {
      if (!empty($microdata['rating_count']['#attributes'])) {
        $rating_count_microdata = drupal_attributes($microdata['rating_count']['#attributes']);
      }
      // We don't directly substitute $votes (i.e. use '@count') in format_plural,
      // because it has a span around it which is not translatable.
      $votes_str = format_plural($votes, '!cnt vote', '!cnt votes', array(
        '!cnt' => '<span ' . $rating_count_microdata . '>' . intval($votes) . '</span>'));
      if (isset($user_rating) || isset($average_rating)) {
        $output .= ' <span class="total-votes">(' . $votes_str . ')</span>';
      }
      else {
        $output .= ' <span class="total-votes">' . $votes_str . '</span>';
      }
    }
  }

  return $output;
}

But the big problem is that I have no idea how to pass the $votes variable, so I hardcoded $votes = 235; right above if (isset($votes)) {, just to see if the code works so far, which it does:

4.1/5 235 votes

I know where to add the parentheses (line 298), but I'm having trouble figuring out how to pass $votes. Any help is greatly appreciated.

UPDATE 2:

The code above is far from perfect, as it produces minor error messages regarding the $microdata & $rating_count_microdata variables. Using the code from Jeroen, I was able to come up with better code that I posted as the final answer below.

share|improve this question
    
Hi, Jay! Consider marking one of the answers as the solution, such that your question is removed from the list of unanswered questions. You can check your own answer or mine. That makes it easier for future visitors to find a working solution. – Jeroen Jun 27 at 9:44
    
Sorry Jeroen, I thought I'd already done this. Anyway, visitors would most likely have to go through both answers to get everything working perfectly, so I checked mine as the final answer. But really, your answer (and one of your comments) is part 1 & mine is part 2. :D – Jay Lee Jun 28 at 22:02
    
Sure, no problem. I have given your question an extra upvote. – Jeroen Jun 28 at 22:53

The output for average votes is set in the fivestar.theme.inc file, which is located at fivestar/includes. You have to overwrite the function theme_fivestar_summary on line 248 (version 7.x-2.1). In order to do this, simply copy the whole function to your theme's template.php file and make the necessary adjustments. I've already done that for you in the code underneath:

function YOURTHEME_fivestar_summary($variables) {
  $microdata = $variables['microdata'];
  extract($variables, EXTR_SKIP);
  $output = '';
  $div_class = '';
  $average_rating_microdata = '';
  $rating_count_microdata = '';
  if (isset($user_rating)) {
    $div_class = isset($votes) ? 'user-count' : 'user';
    $user_stars = round(($user_rating * $stars) / 100, 1);
    $output .= '<span class="user-rating">' . t('Your rating: <span>!stars</span>', array('!stars' => $user_rating ? $user_stars : t('None'))) . '</span>';
  }
  if (isset($user_rating) && isset($average_rating)) {
    $output .= ' ';
  }
  if (isset($average_rating)) {
    if (isset($user_rating)) {
      $div_class = 'combo';
    }
    else {
      $div_class = isset($votes) ? 'average-count' : 'average';
    }

    $average_stars = round(($average_rating * $stars) / 100, 1);
    if (!empty($microdata['average_rating']['#attributes'])) {
      $average_rating_microdata = drupal_attributes($microdata['average_rating']['#attributes']);
    }
    $output .= '<span class="average-rating">' . t('!stars',
      array('!stars' => "<span $average_rating_microdata>$average_stars/5</span>")) . '</span>';
  }

  if (isset($votes)) {
    if (!isset($user_rating) && !isset($average_rating)) {
      $div_class = 'count';
    }
    if ($votes === 0) {
      $output = '<span class="empty">'. t('No votes yet') .'</span>';
    }
    else {
      if (!empty($microdata['rating_count']['#attributes'])) {
        $rating_count_microdata = drupal_attributes($microdata['rating_count']['#attributes']);
      }
      // We don't directly substitute $votes (i.e. use '@count') in format_plural,
      // because it has a span around it which is not translatable.
      $votes_str = format_plural($votes, '!cnt vote', '!cnt votes', array(
        '!cnt' => '<span ' . $rating_count_microdata . '>' . intval($votes) . '</span>'));
      if (isset($user_rating) || isset($average_rating)) {
        $output .= ' <span class="total-votes">(' . $votes_str . ')</span>';
      }
      else {
        $output .= ' <span class="total-votes">' . $votes_str . '</span>';
      }
    }
  }


  $output = '<div class="fivestar-summary fivestar-summary-' . $div_class . '">' . $output . '</div>';
  return $output;
}
share|improve this answer
    
Jeroen, thanks for your answer. But what it does is the following for the "Stars" option (which is not what I want, but did find to be a good starting point): Average: 4.1 (235 votes) -> 4.1/5 (235 votes) What I want is the following for the "Rating" option: 4.1/5 -> 4.1/5 (235 votes) I'll edit my original question with some updates shortly. – Jay Lee Jan 26 at 19:07
    
@Jay Lee: You can debug $variables with Devel and then you'll see that you can get the total amount of votes with $variables['element']['#item']['count']. Use this to adapt the function in your theme template and you're good to go. – Jeroen Jan 26 at 20:47
    
Jeroen, thank you so much. I eventually customized the module to almost exactly how I always wanted it, and even wrote a blog post, the link of which is included in the final answer that I just posted here based on your code. Thanks again. – Jay Lee Jan 30 at 23:59
    
@JayLee: Great, I'm glad it worked out well! – Jeroen Jan 31 at 15:28
up vote 0 down vote accepted

Using the code from Jeroen, I came up with the following code that works 100% without errors in the template.php file:

function YOURTHEMENAME_fivestar_formatter_rating($variables) {
  $element = $variables['element'];
  $votes = $variables['element']['#item']['count'];
  $rating_count_microdata = NULL;

  if (empty($element['#item']['average'])) {
    $element['#item']['average'] = 0;
  }
  // Get number of stars.
  $stars = (empty($element['#instance_settings']['stars'])) ? 5 : $element['#instance_settings']['stars'];
  $average = $element['#item']['average'];
  // Rating is X out of Y stars.
  $rating = round(($average/100) * $stars, 1);
  $output = $rating . '/' . $stars;

  if (isset($votes)) {
    if (!isset($user_rating) && !isset($average_rating)) {
      $div_class = 'count';
    }
    if ($votes === 0) {
      $output = '<span class="empty">'. t('No votes yet') .'</span>';
    }
    else {
      // We don't directly substitute $votes (i.e. use '@count') in format_plural,
      // because it has a span around it which is not translatable.
      $votes_str = format_plural($votes, '!cnt vote', '!cnt votes', array(
        '!cnt' => '<span ' . $rating_count_microdata . '>' . intval($votes) . '</span>'));
      $output .= ' <span class="total-votes">(' . $votes_str . ')</span>';
    }
  }

  return $output;
}

I also decided to write a blog post with more details and explanations, including examples of some more simple customizations. I hope this helps some newbies having trouble customizing this awesome module.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.