Use Node Comment and Fivestar to Create Advanced Reviews
Note that at the time this was written, fivestar required nodecomments. Fivestar can now be used on regular comments as well.
What You Will Need
Latest stable versions of:
* Drupal 5.x
* Fivestar
* Voting API
* CCK
* Views
* Node Comments
This tutorial was specifically written using the following environment:
* Windows XP Pro
* XAMPP 1.6.2
* Drupal 5.7
* Fivestar 1.11
* Voting API 1.5
* CCK 1.6
* Views 1.6
* Node Comments 1.0
This should work for Drupal 6.x too in time, but not just yet. Too many of the required modules are still in alpha and beta states.
Node Comments, why you need it
The problem with comments in the Drupal core is they are not nodes. This means you cannot do any of the neat stuff you can do with nodes with comments. Unfortunately this includes (amongst many other things) rating them. But don't worry! Help is at hand in the form of the Node Comments module. It does what it says on the tin - replaces the core Comments module with a mechanism for commenting via normal content types, so your comments become nodes.
As a result we can use them with the Views module, rate them, give them TPL files, etc. etc.
YOU CANNOT CONTINUE WITH THIS TUTORIAL UNLESS YOU HAVE NODE COMMENTS INSTALLED, which means you cannot use the core Comments module and follow this approach to content rating.
One word of caution though. The implication of moving from Comments to Node Comments is some other modules you may require may not work. For example, the core Forum module does not work with Node Comments AFAIK (and at time of writing, obviously). Do your homework before you make the switch, and where Node Comments are not supported by a module, make sure you are happy the alternatives work.
Basic Reviews - One Rating Field per Node Comment
For the purposes of a demonstration, I will use Quicksketch's website for Good Charlotte as an example use case. It is a website for a rock band where you can listen to their album and then rate it with a comment. To achieve this we need:
* a content type which we expect to rate (call it "album")
* a content type for storing our ratings (call it "review")
So, you've installed all the modules listed above and you're all set.
Create content types
Create a new content type called "review" (admin/content/types) for the comments on our content we wish to rate. For now leave everything default and just save it. Then create a new content type called "album", again leaving defaults, but this time before saving your new content type, near the bottom you should see options called "Default comment setting". Make sure this is set to Read/Write. While you're here, the next option should be "Node type for comments" - pick your new "review" content type from the available list and save your "album" content type.
Reviewing what we just did, we should now have two new content types:
* review - Title and Body fields
* album - Title and Body fields and comments enabled with content type set to "review"
Enable Fivestar on the target
Now, edit the "album" content type. Towards the bottom of the edit page there should be a field group of items labeled Fivestar, possibly collapsed by default. (If so, expand it.) Check the "Enable Fivestar" box and under the "Direct ratings widget" field group set "Teaser display" and "Full node display" to Hidden. Then save.
We have now switched on Fivestar for our rateable "album" content type, but hidden the ability to rate directly on the node from our users (because we want to do this via our comments... the "reviews"... right?)
Add a Fivestar CCK field
Edit the "review" content type. Click the "Add field" tab, type in "Rating" as the field name and pick Fivestar Rating -> Stars as the type. Click the Create field button. You will be taken to the configuration page for your newly created Rating field (which will be the CCK field called field_rating).
Most of the options before you are about visual appearance at this point - the key one is "Target Node ID". This is how Fivestar knows which node your rating is intended for. Vital! There is a checkbox labeled "Use Node Comment Parent as Target", which you should check. Alternatively (and this is the approach I took) leave that box UNCHECKED and paste the following code (provided by Quicksketch) in to the "Target Node ID" text box:
<?php
if (arg(0) == 'node' && arg(1) == 'add' && is_numeric(arg(3))) {
return arg(3);
}
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'edit') {
$node = node_load(arg(1));
return $node->field_rating[0]['target'];
}
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
return arg(1);
}
drupal_set_message('An error occurred saving your review, no target was specified.', 'error');
return 0;
?>Save your field settings.
Displaying your Fivestar average score
Ok, so this is all well and good, but we haven't actually outputted our field to screen (remember, we hid the widget on the node, so right now there is no Fivestar widget or rating visible on our "album" nodes). We need to create a template for our new content type.
Browse to the directory where your theme lives (see PHPTemplate documentation for more information on theming if you are not familiar with how it works), copy your node.tpl.php file and name the copy node-album.tpl.php. Open it in your favourite SDK/text editor and add this code where you want the average rating from your "reviews" to appear:
<?php
$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print '<div><strong>Rating:</strong>';
print theme('fivestar_static', $current_rating->value);
print '</div>';
?>Save the template file. Note, if you read the documentation for the votingapi_get_voting_result() function there are other available options you may wish to use.
Create some actual content
First Create an Album. Just give it a title and some Body text. When you submit the new Album node then you should be taken to it. There should be an empty Fivestar widget shown on the page, where you placed it in your template file.
There should also be an "Add new review" link, provided by Node Comments, already underneath the Album node view. (Permissions permitting! - no link, check your permissions - does your role have permission to create "review" content?)
Click the link and you should have a Title, Body and Rating (in the form of a Fivestar widget). Fill in the Title and Body for your "review" and rate your content by using the Fivestar CCK Rating widget you set up. Then click Submit.
Don't forget to run cron!
Now you will need to run cron (because of the current Voting API bug - see the top of this howto) in order to see your vote working. You can do this by going to Admin -> Logs -> Status report (admin/logs/status) ... there is a "run cron manually" link there. After running cron, navigate back to your Album and you will see the vote from your comment appears.
IMPORTANT NOTE: if you create a new comment as the same user on the same album, your previous vote will be over-written, not added to. If you wish to test the 'average' function by creating more reviews, you must do so as different users. This behaviour is BY DESIGN. If you don't like it, create a patch and publish it back to the community. =)
Advanced Reviews - Multiple Voting Axis per Node Comment
If you've followed this far, you should have a working average rating on your "album" content type being provided by the comments underneath of type "review". But let's say we want another couple of possible star ratings on our "review" content type, which are still relevant to our "album". Consider the rating from the simple approach to be our "overall rating", but consider we want two additional rating fields, "singing" and "musicianship" (this is a harsh website we're building here!)
Create multiple Fivestar CCK fields with different axes
Edit your "review" content type and re-follow the steps for adding a Fivestar CCK field, this time naming the field "Singing". Before you save the field settings (after pasting the code in the "Target Node ID" box) this time you need to give it a "Voting Axis". Type 'singing' (without the quotes) in the "Voting Axis" field and save your settings.
Do the above again for a field called "Musicianship" with 'musicianship' as a "Voting Axis". Finally, change the label on your original CCK field, "Rating", to "Overall rating" so it makes more sense.
Create a new review
Now go back to your original Album node and "add new review" again. This time you should see all three Fivestar CCK widgets:
* Musicianship
* Overall rating
* Singing
Fill in your review fields (just Title and Body in our case), give votes for your three Fivestar fields and click Submit. Run cron again.
Showing our extra Fivestar fields in the template
We have registered some votes on different axes, but we're currently only actually displaying the "Overall rating" field. To display all three axes on our node, we need to replace the code we initially placed in our template file with this:
<?php
$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'singing', 'average');
print '<div><strong>Singing:</strong>';
print theme('fivestar_static', $current_rating->value);
print '</div>';
$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'musicianship', 'average');
print '<div><strong>Musicianship:</strong>';
print theme('fivestar_static', $current_rating->value);
print '</div>';
$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print '<div><strong>Overall:</strong>';
print theme('fivestar_static', $current_rating->value);
print '</div>';
?>Refresh your Album page and you should see all three average votes now. The key thing here is the fourth parameter being passed to the votingapi_get_voting_result() function. It is a string representing the axis you defined when you created your Fivestar field. By default (if you leave "Voting Axis" blank in your CCK config) it will be 'vote' (see Overall rating). To show votes from a different axis, simply call the votingapi_get_voting_result() function with the appropriate axis name as the fourth parameter (called 'tag' by the Voting API).
Advanced: Voting API - what's going on?
If you are interested, a quick look at the Voting API tables, votingapi_vote and votingapi_cache, is worth it. In essence, when you create your "review" and save it, Fivestar creates a vote in the votingapi_vote table for each CCK field. It differentiates between which field is which by putting the "Voting Axis" text in Voting API's 'tag' column.
Whenever cron runs, the Voting API module calculates the average (amongst other functions available) for each node and 'tag' combination and saves a row in the votingapi_cache table. The results can be retrieved from this table by using votingapi_get_voting_result() and telling it which node, function and 'tag' (AKA "Voting Axis") you wish to display.
Compatibility Notice: Issue with VotingAPI
At time of writing, due to a problem with VotingAPI (as far as I can tell) you need to set Voting API settings to "Tally when cron runs" for the voting cache to be set.
Written by Greg Harvey - http://www.drupaler.co.uk

Without nodecomment
You can actually rate with normal comments in more recent versions of fivestar. If you don't want to do anything with the reviews except show them on the node, that's an easier method. If you can't use nodecomment but want to have your reviews be nodes, I wrote a tutorial last October that may still be of use: http://shellmultimedia.com/tutorials/rate-and-review-2
Michelle
--------------------------------------
See my Drupal articles and tutorials or come check out life in the Coulee Region.
Cron work around/ custom node type
To avoid having to Tally on cron, add this line to your template:
<?php if (variable_get("votingapi_calculation_schedule", "immediate")=="immediate") { votingapi_recalculate_results('node', $node->nid, TRUE); } ?>To do this without NodeComment and use any arbitrary node type as your review type, create a required Node Reference field (called 'YourReference' below) to select the node to be rated, and set your "Target Node ID" as:
<?php return $_POST['field_YourReference']['nids']; ?>interested in your do this without nodecomment
Hi matt2000,
i am interested to know more about your method of creating advanced reviews without the use of nodecomment.
specifically, i have troubles displaying the link of the parent of review when viewing the review as a node by itself.
i am very new to drupal and know very little about php.
I have chosen to use the nodecomments way is because i want to have a easy "add new review link" below the body of the product node and same time be able to display a list of reviews below the product and use the fivestar module.
I hope you can advise me on your method so that it may help.
thanks
Drupal 6 - Displaying your fivestar average score
Everything here is working on Drupal 6.x, except I can't figure out how to calculate the average score. The provided code:
<?php$current_rating = votingapi_get_voting_result('node', $node->nid, 'percent', 'vote', 'average');
print '<div><strong>Rating:</strong>';
print theme('fivestar_static', $current_rating->value);
print '</div>';
?>
...will not work with voting_api in drupal 6. The function votingapi_get_voting_result is no longer a part of the module.
If anyone has figured out the d6 code, please post.
Allow user to clear value - breaks user editing reviews
After tinkering a bit i found that if you leave under Review Settings "Allow user to clear value" when creating a new field the user will not be able to update their ratings correctly when editing their comments.
It also appeared that the system will break down and no longer allow for the user to adjust their ratings when editing too.
If you're having problems take a look at this setting. :)
For D6
<?php$current_rating = votingapi_select_results(array('content_id' => $node->nid, 'function' => 'average'));
print '<div><strong>Rating:</strong>';
print theme('fivestar_static', $current_rating[0]['value'], '5'); //this is for 5 stars, enter 10 (or whatever) instead as appropriate
print '</div>';
?>
Advanced Web Design
How about D6 with multiple axes?
I can't find in the votingapi_select_results() documentation where the field name can be specified in the array.
me either - did you find it?
me either - did you find it? I can get average but don't know how to get multiple axis averages printing in drupal 6.
This may not be the most
This may not be the most efficient way but this is how I achieved it in Drupal 6
<?php$customer_service = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'customer_service', 'function' => 'average'));
$reliability = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'reliability', 'function' => 'average'));
$features = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'features', 'function' => 'average'));
$price = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'price', 'function' => 'average'));
$current_rating = ($customer_service[0]['value'] + $reliability[0]['value'] + $features[0]['value'] + $price[0]['value']) / 4;
print '<div class="fivestar-rating">'. theme('fivestar_static', $current_rating, '5') .'</div>';
?>
- Vivian
Hi, could anyone point out
Hi, could anyone point out where I'm going wrong! You'll probably notice in a second that I'm useless at PHP as I've hacked together this code using the example above:
<?php$design = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'design', 'function' => 'average'));
$performance = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'performance', 'function' => 'average'));
$value = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'value', 'function' => 'average'));
$current_rating = ($design[0]['value'] + $performance[0]['value'] + $value[0]['value']) / 3;
print '<div class="fivestar-rating">'. theme('fivestar_static', $current_rating, '10') .'</div>';
?>
Design
<?php
$design = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'design', 'function' => 'average'));
$design_current_rating = ($design[0]['value']);
print '<div class="fivestar-rating">'. theme('fivestar_static', $design_current_rating, '10') .'</div>';
?>
Performance
<?php
$performance = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'performance', 'function' => 'average'));
$performance_current_rating = ($performance[0]['value']);
print '<div class="fivestar-rating">'. theme('fivestar_static', $performance_current_rating, '10') .'</div>';
?>
Value
<?php
$value = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'value', 'function' => 'average'));
$value_current_rating = ($value[0]['value']);
print '<div class="fivestar-rating">'. theme('fivestar_static', $value_current_rating, '10') .'</div>';
?>
For testing purposes I have rated the "design", "performance" and "value" axis as 10 stars each, However, when printing out the average for each axis as well as the overall axis I'm a bit lost. The ratings are only displaying the rating of the the last submitted review and not the average of all reviews.
Can anyone point out what might be wrong?
P.s. I'm using the node relativity module, so the ratings are taken from a related node, but on the related node the ratings are displayed correctly, it's only on the parent node where I'm having problems displaying the average ratings.
Thanks to anyone that can help.
I cannot get the D6 code to
I cannot get the D6 code to work either. I am trying to do multiple axis ratings of "Node A" which is being referenced by "Node B". "Node B" is the node in which the fivestar field rating is being performed. When I visit "Node A", I just see a blank widget (I have submitted a few "Node B's" so the average should be displayed). Here is the code I used:
<?php$high_rating = votingapi_select_results(array('content_id' => $node->nid, 'tag' =>'high', 'function' => 'average'));
print '<div><strong>Average High Rating:</strong>';
print theme('fivestar_static', $high_rating[0]['value'], '5');
print '</div>';
?>
"high" is the axis I used for the "High Rating".
Dave
www.DrugCritics.com
What about multiple axis on the default comment module?
Is there a way to put multiple voting axis on the default comment module. That would seem to be ideal.
multiple axis on a comment would indeed rock -or just for a node
It'd be great to have multiple axis for a comment or a node, so that the users wouldn't need to comment/create a node just to leave a multiple rating.
Thanks.
What about voting api filter?
First,thank you for so excellent solution for nodecomment with fivestar!
It works very well in my site,except when I try to add views filter 'voting api percent vote value'.
I can make list of title of nodecomment(in above example,'review') with username who added it with views.But when I add 'voting api percent vote value' field and filter,the result comes to empty.
I want to know vote value of each user...is this a kind of bug?
What should I do?
It works for D6, but now.....
I have setup and advanced review and rating system using this tutorial. (check this issue: http://drupal.org/node/430170). But how to display this using views?? Any ideas??
the 'this' link doesnt work
the 'this' link doesnt work for me
Drupaling along...
feed me deals
I am trying to do the exact
I am trying to do the exact same type of thing (in Drupal 6), but with a few extras. It looks like the tutorial you linked will help, as I am trying to set up a review site for users to perform multi-axial reviews. My stipulations are:
1) I am going to have users be able to add a product (which I should be able easily do with permission settings). However, if they add a product, I would like them to have a review for it on the same screen, or as a required Step 2. Otherwise, I feel having them do two separate unlinked processes (part 1= click to create add a product, part 2 = click on a separate menu to review it), fewer people will do the first anyway. So it is almost like saying when somebody accesses the "product" node, I want the "review" node to actually integrate into it seamlessly.
2) It actually isn't a product I am reviewing, but a worksite, with a geographic location. As part of the product entry, I would like users to be able to put in at least a city and state, and optionally an address. What I would then like to do is have a searchable index, where users can search by geographic location (ie, within 50 miles of this zip code) to find a worksite. Therefore, any worksites entered by users, with reviews already, should come up with that search. Also, I would like to have a general directory, ie, by state, which I assume I could do with tagging, but would imagine there would be an easier way. I believe using the gmap module is part of that, but am not sure how to integrate that information with my "product" and search for "reviews."
Any ideas for either of these, or better places to post them (since it is related to the original question, but also goes off on a tangent?)
Good Question
Did you figure anything out? As I'm trying to figure out where to start when building a site where members rate agencies... and like your way of thinking... (STEP 1)
Ideas
Hola, everyone.
Im kind of new to Drupal and i've tried every single solution i found at drupal.org to have a multi-axes fivestar-like widget but totally unsuccessful. However, i came up with this idea:
- we have fivestar source code
- we can duplicate this code naming 'fivestar2' to all references to 'fivestar' on the code when needed
- we can create a module named fivestar2 so we have 2 fivestar blocks.
- Then, we can create multiple fivestar blocks provided that we know what to change so that we have a fivestar2, 3 or 4
Maybe this idea is totally pointless but, having no vast knowledge on PHP, i thought it could be fine.
The thing is that i dont know how to do it right now but im just a beginner, someone else may be able to.
Allow Multiple Ratings
Is there a way to allow users to have multiple ratings without having the original rating being replaced by the new one. For example let says users are rating multiple instances of Product A. Product A can exist in different colors. The first time a user rated Product A was when he had it in color Blue (user inputs "Blue" in one of the fields created by CCK). The next time the user rates the same Product A, but he wants to do it for color "Green." This time, the user inputs "Green" in one of the fields created by CCK. So when the user is raiting for a different color of Product A, the original raiting shouldn't be override.
Rating as Sort Criteria under Views Module
I followed this tutorial on Multiple Voting Axis with my D6 site and everything was okay before I tried to add the rating result as Sort Criteria. I added "field_rate_reliability" and set it to "Descending", but the nodes (which are to be rated) aren't in order of the values. I also tried adding a relationship but the axis tag (like "reliability") didn't appear in the "Vote tag" list.
Does anyone know how to figure it out?