Could it be possible to display the number of positive votes as well as the negative ones instead of displaying the total sum of votes? If not, it would be interesting to know the number of votes a node has received.

Thanks

Comments

pfoucher’s picture

I am actually trying to achieve the same thing. ( thumbs up, thumbs down kind of thing)

I think that one way to do it would be to rate negative votes as "0 point" whereas positive votes are equal to "1 point".

Then, the negative votes count could be the difference between total votes count and sum of points.
Your positive votes count will be the sum of points.

To do this, I had a look at votingapi in order to hook before inserting the vote in database and modify the value of negative vote from "-1" to "0".
The only thing is that the hook_insert happens after the insert in database.

One other way to do it would be to alter vote up/down module so that you can choose the points value for each positive or negative vote.

Anyway, i am still testing, will let you know if i have any success.

:)

poloparis’s picture

Hey lafouch

for what it's worth, i've kind of dabbled with that module and voting_api to write a small module to promote nodes to front page based on voting results of the vote_up_down module and i have used the following hook to do so, on line 397 of the votingapi.module :

// Give other modules a chance to act on the results of the vote totaling.
module_invoke_all('votingapi_results', $cached, $content_type, $content_id);

and found out the following to use in my module :

$cached[0]['value'] returns the total number of votes

$cached[1]['value'] returns the average result, bet 0 & 1 (or if you want , in percentage, the sum of + & - votes div by total votes)

$cached[2]['value'] returns the sum of + and - votes

hope that helps

jefftrnr’s picture

Hi lafouch,

I have had success with the following theme override. Just paste it into the template.php file in your theme's folder.

poloparis shows you can get three different results from the results array, but actually, the key was to switch the votingapi function to select_votes rather than select_result_value. I then used php to tally up the votes for either 1 or -1 values. Anyway, the code below should be close to what you're looking for.

function phptemplate_vote_up_down_points($cid, $type, $tag = NULL, $nodelink = FALSE) {
  $tag = $tag ? $tag : variable_get('vote_up_down_tag', 'vote');
  $criteria = array('content_type' => $type, 'content_id' => $cid, 'value_type' => 'points', 'tag' => $tag //, 'function' => 'sum'
  );
  $votes = votingapi_select_votes($criteria);

  $items = array(); $results_upvote = $results_downvote = 0;
  foreach ($votes as $vote) {
    if ($vote['value']>0) $results_upvote += $vote['value'];
    elseif ($vote['value']<0) $results_downvote += $vote['value'];
  }

  $items[] = array('class'=>'upvote','data'=>'<strong>'. $results_upvote .'</strong> <span>up</span>');
  $items[] = array('class'=>'downvote','data'=>'<strong>'. $results_downvote .'</strong> <span>down</span>');

  if ($nodelink) {
    foreach($items as $item) $title .= '<span class="'.$item['class'].'">'.$item['data'].'</span>';
    $output = array(
      'title' => $title,
      'html' => TRUE
    );
  }
  else {
    $output = theme('item_list',$items,null,'ul',array('id'=>'vote_points_'. $cid,'class'=>'vote-points'));
  }

  return $output;
}
pfoucher’s picture

Thanks to both of you,

i finally used the hook_votingapi_results_alter in the following way to get :
- negative votes, positive votes and percentage of positive votes among all votes

function thumbs_votingapi_results_alter(&$cache, $content_type, $content_id){
  
  $sql  = "SELECT count(*) as positive_count ";
  $sql .= "FROM {votingapi_vote} v ";
  $sql .= "WHERE v.content_type = '%s' AND v.content_id = %d ";
  $sql .= "AND v.value_type = 'points' AND v.value = 1";
  
  $results = db_query($sql, $content_type, $content_id);
  
  while ($result = db_fetch_array($results)) {
    $cache['thumb']['points']['positive'] = $result['positive_count'];
  } 
  
  $cache['thumb']['points']['negative']=$cache['vote']['points']['sum']-$cache['thumb']['points']['positive'];
  $cache['thumb']['percent']['average_success']=($cache['thumb']['points']['positive']/$cache['vote']['points']['sum'])*100; 
}

then the values are available with the votingapi_select_results($criteria);

tommytom’s picture

Can somebody help me with one function.
I want to implement hook_voingapi_results_alter() in vote up down module.

I have this code for votingapi version 1.x , I'm trying to change it to version 2.x .
I don't know how to check the current vote value : if ($vote->value == -1) -this doesn't work in votingapi 2.x
please help.

/**
* Implementation of hook_votingapi_calculate().
*
* @param $cache
* an array of {votingapi_cache} records. Here you put your stuff in there. It is keyed by $tag, $type, $function
*
*/
function vote_up_down_votingapi_calculate(&$cache, $votes, $content_type, $content_id) {
  foreach ($votes as $vote) {
    if ($vote->value == -1) {
      $cache[$vote->tag][$vote->content_type]['thumbs_down']++;
    }
    else if ($vote->value == 1) {
      $cache[$vote->tag][$vote->content_type]['thumbs_up']++;
    }
  }
}

In version 2.x it doesn't get the $vote->value .

This hook_votingapi_calculate(&$cache, $votes, $content_type, $content_id) has changed to hook_votingapi_results_alter(&$cache, $content_type, $content_id) .
What happen with the $votes array ? How can I get the current vote value ?

totaldrupal’s picture

did you get this to work?

tommytom’s picture

yes but not with this hook. I had some problems with the implementation so I modified the voting api module.
I added this 3 lines to votingapi:

function _votingapi_get_standard_results($content_type, $content_id)
...
    $votesdown = (  $result['value_count']  -  $result['value_sum']  ) / 2 ;
    $cache[$result['tag']][$result['value_type']]['votes_down'] = $votesdown;
    $cache[$result['tag']][$result['value_type']]['votes_up'] =  $result['value_count'] - $votesdown ;
...

and it works fine for me. However, it's not a good idea to do it this way. It should be done with this hook:
hook_voingapi_results_alter() in vote up down module !!!!!!!!!!!!!!!!!

Now it calculates the values everytime somebody votes.

To see the result you have to add this to the theme function of vote up down module:

function template_preprocess_vote_up_down_points(&$variables) {
...
         $criteria1 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_down'
  );

    $criteria2 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_up'
  );

  $vote_result_downs = (int)votingapi_select_single_result_value($criteria1);
  $vote_result_ups = (int)votingapi_select_single_result_value($criteria2);
  $variables['points_down_labelled'] = format_plural($vote_result_downs, '1 down ', '@count down ');
  $variables['points_up_labelled'] = format_plural($vote_result_ups, '1 up, ', '@count up, ');
...

and you have to edit this file: vote_up_down_points.tpl.php
The up point are stored now in $points_up_labelled.
For example you can add this 2 lines to the tpl file:

<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_up_labelled; ?></span></span>
<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_down_labelled; ?></span></span>

You also may want to edit the css file.

tommytom’s picture

if you have the voting counts and sum, you can calculate the ups and downs :
downpoints = (count - sum) /2
uppoints = count - downpoints

socialnicheguru’s picture

subscribing

totaldrupal’s picture

Tried to get this to work but I'm not a programmer and good with code so I'm sure I screwed it up. Do you only add the code or do you need to modify the existing code? Maybe you could dumb it down for me so I can get this working. Thanks.

mcload’s picture

subscribing

aac’s picture

Plus vote = Number of Plus votes
Minus vote = Number of Minus votes

count = Plus vote + Minus vote
sum = Plus vote - Minus vote

Solving these equations give the following results for Plus and Minus votes-

Plus vote = (count + sum)/2
Minus vote = (count - sum)/2

Now these can be used in the vote up down module to get the desired results. I think it does not require to alter votingapi module.

socialnicheguru’s picture

subscribing

davedg629’s picture

I got this to work with one small problem. When I view a node that his this voting enabled, the results say 0 up 0 down. Then when I vote "up" I see 1 up 0 down 0 down. The extra "0 down" is the problem. If I switch the order of the results it does the same thing. Obviously the second result that is being shown is not getting cleared. When I print only the up results or only the down results everything works fine. So there must be some place in the code where you have to tell it to clear both values instead of just one.

Dave

davedg629’s picture

Here is where I put the code in the votingapi.module file:

function _votingapi_get_standard_results($content_type, $content_id) {
  $cache = array();

  $sql  = "SELECT v.value_type, v.tag, ";
  $sql .= "COUNT(v.value) as value_count, SUM(v.value) as value_sum  ";
  $sql .= "FROM {votingapi_vote} v ";
  $sql .= "WHERE v.content_type = '%s' AND v.content_id = %d AND v.value_type IN ('points', 'percent') ";
  $sql .= "GROUP BY v.value_type, v.tag";
  $results = db_query($sql, $content_type, $content_id);

  while ($result = db_fetch_array($results)) {
    $cache[$result['tag']][$result['value_type']]['count'] = $result['value_count'];
    $cache[$result['tag']][$result['value_type']]['average'] = $result['value_sum'] / $result['value_count'];

    //INSERT CODE HERE
    $votesdown = (  $result['value_count']  -  $result['value_sum']  ) / 2 ;
    $cache[$result['tag']][$result['value_type']]['votes_down'] = $votesdown;
    $cache[$result['tag']][$result['value_type']]['votes_up'] =  $result['value_count'] - $votesdown ;
    //END OF INSERTED CODE

  if ($result['value_type'] == 'points') {
      $cache[$result['tag']][$result['value_type']]['sum'] = $result['value_sum'];
    }
  }

Here is where I put the code in vote_up_down.module:

function template_preprocess_vote_up_down_points(&$variables) {
  $tag = isset($variables['tag']) ? $variables['tag'] : variable_get('vote_up_down_tag', 'vote');

//INSERT CODE HERE
$criteria1 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_down'
  );

    $criteria2 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_up'
  );

  $vote_result_downs = (int)votingapi_select_single_result_value($criteria1);
  $vote_result_ups = (int)votingapi_select_single_result_value($criteria2);
  $variables['points_down_labelled'] = format_plural($vote_result_downs, '1 down ', '@count down ');
  $variables['points_up_labelled'] = format_plural($vote_result_ups, '1 up, ', '@count up, ');
  //END OF CODE INSERT

Then just modify vote_up_down_points.tpl.php the way tommy said so. Just a little clarification for those who don't know exactly where to put this code.

davedg629’s picture

StatusFileSize
new14.65 KB
new14.73 KB

I am still having trouble with the results not being cleared after a new vote is cast.

I've attached two images that show what is going on.

The first image shows a node for Derek Jeter where one person has voted "up". As you can see it is working correctly - showing 1 up vote, and 0 down votes.

The second image shows what happens after I change this vote to "down". As you can see here, there is an extra "0 down" appended to the end of the results.

It should also be noted that the same thing occurs if I click the "up arrow" after I have already cast a vote. The results aren't effected (so its not like I am voting again), it just displays the "0 down" to the right a second time.

davedg629’s picture

I think some of the ajax code needs to be changed to get rid of this problem.

davedg629’s picture

Version: 6.x-1.0-beta4 » 6.x-1.0-beta6

o yea, changing this to beta6

khanz’s picture

Title: sepparated number of votes instead of total sum » separated number of votes instead of total sum

Is there any way of doing, without hacking the core mod. i am not a programmer so plz be easy on the step of doing it.

davedg629’s picture

Okay, fixed my problem detailed in #16.

Changes need to be made to the code in the vote_up_down.module file and the vote_up_down_points.tpl.php.

Here is the correct code for the vote_up_down.module file:

/**
 * Preprocess function for the points in the normal display style.
 */
function template_preprocess_vote_up_down_points(&$variables) {
  $tag = isset($variables['tag']) ? $variables['tag'] : variable_get('vote_up_down_tag', 'vote');

$criteria1 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_down'
  );

    $criteria2 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_up'
  );

  $vote_result_downs = (int)votingapi_select_single_result_value($criteria1);
  $vote_result_ups = (int)votingapi_select_single_result_value($criteria2);
  
  //Here is the change from the code I used in comment #15 (see above)
  $variables['points_labelled'] = format_plural($vote_result_downs, '1 down ', '@count down ') . format_plural($vote_result_ups, '1 up ', '@count up ');

With this change to the variables['points_labelled'], the tpl file must be changed to this:

<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_labelled; ?></span></span>

But like khan said, a solution needs to be outlined where hacking the module is not needed. Don't know much about overriding functions, but if someone does help is appreciated. Until then I'm just gonna go with this hack.

aac’s picture

I would like to know, how can i write a module to promote the nodes on the front page based on number of votes.
Thanks for your any help.

john.kenney’s picture

I'd really like to get this to work, but have tried a few times and not getting it. Or maybe I am getting it, but I don't know how to print the result?

I have tried to follow the directions above - largely #7, #15, and #20 as follows:

1. Modify votingapi.module with code inserted as shown here:


function _votingapi_get_standard_results($content_type, $content_id) {
  $cache = array();

  $sql  = "SELECT v.value_type, v.tag, ";
  $sql .= "COUNT(v.value) as value_count, SUM(v.value) as value_sum  ";
  $sql .= "FROM {votingapi_vote} v ";
  $sql .= "WHERE v.content_type = '%s' AND v.content_id = %d AND v.value_type IN ('points', 'percent') ";
  $sql .= "GROUP BY v.value_type, v.tag";
  $results = db_query($sql, $content_type, $content_id);

  while ($result = db_fetch_array($results)) {
    $cache[$result['tag']][$result['value_type']]['count'] = $result['value_count'];
    $cache[$result['tag']][$result['value_type']]['average'] = $result['value_sum'] / $result['value_count'];

    //INSERT CODE HERE
    $votesdown = (  $result['value_count']  -  $result['value_sum']  ) / 2 ;
    $cache[$result['tag']][$result['value_type']]['votes_down'] = $votesdown;
    $cache[$result['tag']][$result['value_type']]['votes_up'] =  $result['value_count'] - $votesdown ;
    //END OF INSERTED CODE

  if ($result['value_type'] == 'points') {
      $cache[$result['tag']][$result['value_type']]['sum'] = $result['value_sum'];
    }
  }

2. Modify vote_up_down.module as shown here:


/**
* Preprocess function for the points in the normal display style.
*/
function template_preprocess_vote_up_down_points(&$variables) {
  $tag = isset($variables['tag']) ? $variables['tag'] : variable_get('vote_up_down_tag', 'vote');

  // begin inserted code
    $criteria1 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_down'
  );

    $criteria2 = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'votes_up'
  );

  $vote_result_downs = (int)votingapi_select_single_result_value($criteria1);
  $vote_result_ups = (int)votingapi_select_single_result_value($criteria2);
  $variables['points_labelled'] = format_plural($vote_result_downs, '1 down ', '@count down ') . format_plural($vote_result_ups, '1 up ', '@count up ');
  //end inserted code

  $criteria = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'sum'
  );

3. Modify vote_up_down_points.tpl.php as shown here:


<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_labelled; ?></span></span>
  // begin inserted code
<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_up_labelled; ?></span></span>
<span id="vote_points_<?php print $cid; ?>" class="vote-points"><span class="<?php print $class; ?>"><?php print $points_down_labelled; ?></span></span>
  //end inserted code

davedg629 or others, can you confirm this code is correct? I've put it all in place - but not getting a result. Not getting any errors, either, so if it is working, I guess next question is how do I get at the data? What variables do I use to print them to my pages?

I am using on a page with CCK variables. From Contemplate, I got this for printing the widget:

<?php print $node->content['vote_up_down']['#value'];?>

This works fine - votes are being recorded, but there are no variables shown in Contemplate to display the up / down results - perhaps that is because the above bits aren't working or perhaps because they are to be found elsewhere. I tried various things, but nothing worked - which isn't surprisingly cause I haven't got a clue what I'm doing.

Can someone offer advice how to get this working?

Thank you!

HunterElliott’s picture

This may not be what you want since it uses an external 3rd party system, but the easiest way I've found to implement this is to use the Nero Rating System from polldaddy.com. You will need to sign up for an account there, but you can do this with the basic/free account.

Just log in to your acct at polldaddy.com. Under the Account tab, there will be an item called "Ratings" (at this point in time, it has a 'beta' label on it). Click on Ratings and then click on the button that says Create New Rating. Choose a "Nero" style for thumbs up/down. Give the rating a name that you'll remember - you do NOT need to create a separate rating for everything on your site, you only need to create one, really.

Once you create a rating, it will give you some embed code for your site. Copy this code and put it in your relevant .tpl file. The DIV in the code will have an ID in it - keep the ID, but you may want to give it a CLASS for your own styling. The only line you *really* need to change here is the line that has the Unique ID; here I just plopped in the Node ID for it, but you can put something else text-wise at the front/end/both of it to make sure: "unique_id" : " (use the php tags around the following) $node->nid; "

If you want different images for the thumbs, polldaddy.com gives you the option list an image of your own (you'll need to host the image on your site).

(and no, I am in no way affiliated with polldaddy - just letting people know about it as so many people want to use this kind of thing)

HunterElliott’s picture

After playing around with the polldaddy code, which BTW did NOT work as "published" from their site, I did find out what was needed to change.

If you do use said code, this is what you need to do to get it to work if you're displaying say a list of 10 items from a blog post via a query...

The code they give you needs to be modified as follows:

< div id="pd_rating_holder_Number_identifyingText(nodeID)" >< / div>
< script language=" javascript" > //remove the "text=" value that is in the PD generated code
PDRTJS_settings_Number_identifyingText(nodeID) = ({ //IMPORTANT - make sure to add a "(" before the brace
"id" : "Number",
"unique_id" : "value", // here I used a value of the userID, a comma, and then the nodeID - this *cannot* be the same as the item_id
"title" : "", // if you use a value here, like the node Title, make sure that it is NOT linked to the node - create another Title value in your query and make sure it's not linked
"permalink" : "",
"item_id" : "_identifyingText(nodeID)"
}); // IMPORTANT - make sure to add a ")" after the brace -- the parentheses are not in the PD generated code

I hope this helps someone - it was a PITA to figure out since the info from PollDaddy was not correct. FWIW, PD says they're planning on releasing a Drupal module for their rating system sometime this year.

Gabriel R.’s picture

StatusFileSize
new32.54 KB

I am looking for a clean solution that only involves Views.

I have a a hunch that the answer could be in the Other option for Aggregation function. See the attached image. Is there any documentation I could use for it?

trevorleenc’s picture

will any of this work with 2.x-dev ?

szadok’s picture

I have used jefftrnr (#3) solution with version 1.0 and it worked for me perfectly, thanks a lot !

gausarts’s picture

Subscribing. Thanks

kscheirer’s picture

I think you guys are making this way harder than it needs to be - the solution aac posted in #12 is correct.

Vote Up/Down normally just tells you the Count (total number of votes) and Sum (# positive votes - # negative votes). Based on only those 2 values, you can get the total number of up votes and total number of down votes. So it just requires a little extra logic in the template preprocess function which is easily overridable, and should not need any changes to the module or votingapi.module.

The total number of down votes is (Count - Sum) / 2. Once you know that, the total number of up votes is (Count - # of down votes).

I'll post the theme override function I used. Honestly I think this should be the core way of displaying vote totals. Or possibly provide these values to the theme functions by default, and make it easier for folks to display what they want.

kscheirer’s picture

This is the override function. Really I just added the lines in the middle - the rest are standard from the modulel.

/**
 * Override Vote Up/Down theme function
 *
 * Preprocess function for the points in the normal display style.
 */
function exampletheme_preprocess_vote_up_down_points(&$variables) {
  $tag = isset($variables['tag']) ? $variables['tag'] : variable_get('vote_up_down_tag', 'vote');

  $criteria = array(
    'content_type' => $variables['type'],
    'content_id' => $variables['cid'],
    'value_type' => 'points',
    'tag' => $tag,
    'function' => 'sum'
  );
  $vote_sum = (int)votingapi_select_single_result_value($criteria);

  // Added - get the voute count.
  $criteria['function'] = 'count';
  $vote_count = (int)votingapi_select_single_result_value($criteria);

  // Added - calculate number of up and down votes.
  $variables['down_votes'] = ($vote_count - $vote_sum) / 2;
  $variables['up_votes'] = $vote_count - $variables['down_votes'];

  if ($variables['type'] == 'node') {
    $node = node_load($variables['cid']);
    $variables['node_type'] = node_get_types('name', $node);
  }

  if ($vote_result > 0) {
    $variables['class'] = 'positive';
    $variables['points'] = '+'. $vote_result;
  }
  else {
    $variables['points'] = $vote_result;
    if ($vote_result < 0) {
      $variables['class'] = 'negative';
    }
    else {
      $variables['class'] = 'neutral';
    }
  }
  $variables['label'] = format_plural($vote_result, 'point', 'points');
  $variables['points_labelled'] = format_plural($vote_result, '1 point', '@count points');
  if (isset($variables['style'])) {
    $variables['template_files'][] = 'vote_up_down_points_'. $variables['style'];
  }
}

and then in my theme's vote_up_down_points.tpl.php

<span id="vote_points_<?php print $cid; ?>" class="vote-points">
  <span class="vote-points-like">Like this <?php print $node_type ?>: <strong><?php print $up_votes ?></strong></span>
  <span class="vote-points-dislike"> | Dislike this <?php print $node_type ?>: <strong><?php print $down_votes ?></strong></span>
</span>
kerberos’s picture

@ #30:

Very helpful, thanks!

-Daniel

sotiris’s picture

In which version do we have to apply the #30 code? I did with beta-6 but it does not work as well as expected. It counts every like vote for 0.5 point, and it doesn't count dislikes at all... (In the voting details tab, i have correct counting of votes +1 -1)

Update: I forgot to change $vote_result to $vote_sum, after this change your code worked as expected,

Thank you so much!

ccshannon’s picture

Subscribe from my iPhone so I can implement this when I get home.

ccshannon’s picture

And it worked beautifully.

Many thanks!

ckreutz’s picture

Does anybody has a solution for the same issue for the 6.x.2.x-dev version? It seems the module has changed a lot and the above version e.g. #30 cannot work.

AntiNSA’s picture

Subscribe

DomDoze’s picture

Subscribe

marvil07’s picture

just to mention that there are plans to include this on 6.x-2.x also ;-) #811694: New widget for splitting of votes in positives/negatives (5 voted up, 2 voted down)

marvil07’s picture

Version: 6.x-1.0-beta6 » 6.x-1.x-dev
Status: Active » Closed (won't fix)

No more features to 6.x-1.x, please take a look to the update on the project page.