5

On my website, users can rate each other's nodes via a Fivestar field called Stars in a comment. I'd now like to calculate the overall average score of a user. That means, I'd like to display the user's average score for all his/her nodes.

For example. Let's say a user created 2 nodes: Node 1 and Node 2. Some people rated his content:

  • Scores of Node 1: 4/5, 5/5, 3/5
  • Scores of Node 2: 4/5, 4/5

The overall average would then be (4+5+3+4+4)/5=4.

Preferably, this result should also be displayed as stars.

How can I do that?


Edit 1: Working with the Computed Field module seems to be a general idea to solve this matter. It looks fine to me and I think it's best to store the users' average score in a user field, in order to make it easily accessable. (Working with a view is also fine.) I'm planning to display the average score on their profile page, but perhaps I'm going to use it elsewhere on the website in the future too.

Can you please help me with (a scetch) of the code I'm supposed to use?


Edit 2: I created a user field called Gemiddelde and pasted @Thomas4019's code in my custom module hiderating (the module's title refers to an earlier question), but it gave me the following error:

  • Warning: Missing argument 5 for computed_field_field_gemiddelde_display(), called in C:\wamp\www\mysite\sites\all\modules\computed_field\computed_field.module on line 341 and defined in computed_field_field_gemiddelde_display()(line 24 of
    C:\wamp\www\mysite\sites\all\modules\hiderating\hiderating.module).
  • Notice: Undefined variable: entity in computed_field_field_gemiddelde_display() (line 30 of C:\wamp\www\mysite\sites\all\modules\hiderating\hiderating.module).
  • Notice: Trying to get property of non-object in computed_field_field_gemiddelde_display() (line 30 of C:\wamp\www\mysite\sites\all\modules\hiderating\hiderating.module).

The Gemiddelde field in the view on my profile page has the following value:

<div class="fivestar-basic"><div class="fivestar-widget-static fivestar-widget-static-vote fivestar-widget-static-5 clearfix"><div class="star star-1 star-odd star-first"><span class="off">0</span></div><div class="star star-2 star-even"><span class="off"></span></div><div class="star star-3 star-odd"><span class="off"></span></div><div class="star star-4 star-even"><span class="off"></span></div><div class="star star-5 star-odd star-last"><span class="off"></span></div></div></div><div class="fivestar-summary fivestar-summary-average-count"><span class="empty">No votes yet</span></div> 

Edit 3: After reinstalling the Computed Field module and clearing caches, the error messages are gone, but the Gemiddelde field in my view still displays the following CSS code:

<div class="fivestar-basic"><div class="fivestar-widget-static fivestar-widget-static-vote fivestar-widget-static-5 clearfix"><div class="star star-1 star-odd star-first"><span class="on">3</span></div><div class="star star-2 star-even"><span class="on"></span></div><div class="star star-3 star-odd"><span class="on"></span></div><div class="star star-4 star-even"><span class="off"></span></div><div class="star star-5 star-odd star-last"><span class="off"></span></div></div></div><div class="fivestar-summary fivestar-summary-average-count"><span class="average-rating">Average: <span >3</span></span> <span class="total-votes">(<span>1</span> vote)</span></div>

What went wrong?

  • How strange! Could you post the line 341 from C:\wamp\www\mysite\sites\all\modules\computed_field\computed_field.module? I imagine your using computer field version 7.x-1.0 right? – Thomas4019 Dec 5 '13 at 22:35
  • @Thomas4019: Yes, that's the version I'm using. Line 341 is the default one, I didn't change the code in the files. $display_output = $display_func($field, $entity_field_item, $entity_lang, $langcode); The bounty is yours if you can fix this. – Jeroen Dec 6 '13 at 23:07
  • Line 341 for me is $display_output = $display_func($field, $entity_field_item, $entity_lang, $langcode, $entity); I have no idea why they would be different. Maybe try redownloading computed field? – Thomas4019 Dec 6 '13 at 23:21
  • @Thomas4019: I redownloaded the module and now the $entityis there again! Very odd... After clearing caches, the Gemiddelde field in my view still displays CSS code. You can find the code in Edit 3. Did you test your code? It would be quite strange if it worked on your website and not on mine... – Jeroen Dec 6 '13 at 23:49
  • Usually what is documented in Fivestar 7.x: Creating a User Comment/Rating and Average Rating for a Content type, should be all you need. It provides detailed instructions about: 1. Setting Up the Content Type (node-type) 2. Setting Up the Comments/Ratings – Marko Blazekovic Jun 14 '15 at 8:59
9
+50

I know that something like this can be done with computed field. It will require some PHP code though. See some discussion here

Here's what you need to do:

  1. Install Computed Field and Fivestar
  2. Go to admin/config/people/accounts/fields and create a computed field on the user entity type. In my case I named it "field_computed_rating". On the settings form for the field make sure the checkbox "Store value in the database" is unchecked.
  3. Click on "Manage Display" for the content type you created the field on. Then make sure the format for that field is set to "Unsanitized".
  4. (if you already have a custom module you can skip this step) In your code base within sites/all/modules, create a new folder titled fivestar_user_aggregate. Within that folder you will need to create fivestar_user_aggregate.info with the following contents.

    name = Fivestar User Aggregate
    description = Assign users an aggregate rating based on all their nodes
    core = 7.x
    package = Custom
    
  5. Add this custom php function to your module file or create fivestar_user_aggregate.module within fivestar_user_aggregate with the following contents. If you named your field differently then you will need to modify the function name accordingly.

    <?php
    
    function computed_field_field_computed_rating_display($field, $entity_field_item, $entity_lang, $langcode, $entity) {
        $result = db_query("SELECT n.uid, n.nid, vote1.value AS count, vote2.value AS average FROM {node} n
    INNER JOIN {votingapi_cache} vote1 ON n.nid = vote1.entity_id
    AND vote1.function =  'COUNT'
    INNER JOIN {votingapi_cache} vote2 ON n.nid = vote2.entity_id
    AND vote2.function =  'average'
    WHERE n.uid = :uid", array(':uid' => $entity->uid));
    
        $rating_count = 0;
        $rating_total = 0;
    
        $nodes = $result->fetchAll();
        foreach ($nodes as $node) {
            $rating_count += $node->count;
            $rating_total += $node->average * $node->count;
        }
    
        if ($rating_total == 0) {
            $weighted = 0;
        } else {
            $weighted = $rating_total / $rating_count;
        }
    
        $variables = array(
            "rating" => $weighted,
            "average_rating" => $weighted,
            "votes"  => $rating_count,
            "stars" => 5
        );
        $variables["widget"]["name"] = "basic";
        $variables["widget"]["css"] = "sites/all/modules/fivestar/widgets/basic/basic.css";  
        drupal_add_css(drupal_get_path('module', 'fivestar') .'/css/fivestar.css');
        return theme('fivestar_static', $variables) . theme('fivestar_summary', $variables);
    }
    
  6. Enjoy! You should now see a weighted average of all a user's node's ratings on their page.

  • Thanks for your answer, Thomas. The discussion you refer to only handles a solution for computing the average score for multiple votes on the same nodes. Just to make sure you've interpret my question correctly: I'd like to compute the average score of multiple node. Anyway, thank you for the link: it might come in handy in the future. – Jeroen Nov 29 '13 at 18:30
  • It's not a simple problem. You can see someone else's similar question. With computed field you can put in arbitrary PHP code so you can put in code that does the necessary SQL query to pull the ratings of all a users nodes and then calculates an average. – Thomas4019 Nov 30 '13 at 17:52
  • Your idea of working with Computed Field sounds doable. Can you perhaps help me a bit with the PHP code? – Jeroen Dec 4 '13 at 16:00
  • First of all, thanks a lot for working this out for me! Your update looked very promising, but unfortunately, it doesn't work yet. I pasted the error messages I get in an Edit 2. – Jeroen Dec 5 '13 at 22:10
  • GREAT NEWS! I found the solution! There's nothing wrong with your code, but the Gemiddelde field's formatter in my view was incorrect. It was switched on Plain text instead of Unsanitized. You really deserved my bounty: THANKS A LOT! – Jeroen Dec 6 '13 at 23:54
2

Jeroen,

Firstly, where do you want this info to show up? If this is a user page, go ahead with Computed Field, else, if this is something like a listing page, or a view, then you can use Views PHP. In both cases, you will have to code to fetch the results. You will have to fetch the nodes of the user, sum up all the ratings on all the nodes, and then take an average. This would be your result.

  • I've updated my question in order to give you some more information. – Jeroen Dec 4 '13 at 8:55
0

Did you try Views Aggregation ? I think with a little work it can do what you need.

  • Can you be a little bit more specific? The screencast in the link you mention doesn't handle calculating average results, neither do any of the related videos about aggregation. – Jeroen Dec 3 '13 at 20:07
  • In a view with your field, gather all values and activate aggregation and set 'average'. – Gregory Kapustin Dec 4 '13 at 16:01
0

Yet another approach, as per the "Working with a view is also fine" in the question:

  1. Create some view that contains the relevant data, filters, sorting, etc.

  2. Use the Views_calc module to have the average displayed below the views result.

Here is a typical screenprint of such table:

Views Calc screenprint

Refer to my answer to the question about "How can I show average votes of fivestar nodes?" for more details on this.

Disclosure: I'm a co-maintainer of this module,
I hope this does not violate the site's policy on self-promotion.

0

I have recently stumbled upon this problem again and I solved it with Views Aggregation myself in a couple of minutes without thinking about this old question. I would like to add my solution as an alternative answer for people who are not (yet) into programming. The View is set as follows:

  • Create a new unsorted View that displays comments.
  • Check that there is already a relation to the content, i.e. the node that received the comment, in the advanced settings.
  • Add a contextual filter to the author uid of the content. In my case, I display the View on the user pages, so I set the default value to the uid in the URL.
  • Next, enable Aggregation in the Other section of the advanced settings.
  • Add the field Stars, display the value as stars and change the aggregation settings to average (type) and rating (group).
  • Add additional filters if necessary. For example, I filtered on approved comments with a non-zero vote on published nodes of a specific type.

Done! If you are reading this as a Drupal beginner, you can interpret this story as a kind of reassurance: don't give up and you will make enormous progressions, even if you don't believe it yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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