Once a vote has been cast, you cannot tell if the user has previous voted, and/or what was the value of their previous vote.

For me, I need to do a comparison on the previous value. I want to do this with Voting Rules.

Case:
User has a currency of 10 votes. They can spend them on any votes of a specific node type. They can vote up to 5 times on an entity, using Vote Up/Down (and this patch #1869790: Allow multiple votes).

Solution:
Add a field to the users (decimal/float type) with a default value of 10.
Add the patch below to VotingAPI module
Install Vote Up/Down module
Add Default Up/Down widget to specific node type.
Add #1869790: Allow multiple votes patch to Vote Up/Down
Setup a rules for when the user casts a vote on specific node type
- Calculate the difference between the current and previous vote
- Add/Subtract value from the user field

This works for other solutions
- Display the previous vote in a view
- Tell if the user has voted before (previous vote will be NULL if they haven't)
- For modules like Rate, using Voting Rules, if the user voted Red before, they cannot vote Green, only Blue.
- For modules like fivestar and Voting Rules, you can tell the user change the "5/5" to "1/5" and the they have decrease their rating by 80 percent.

Comments

istryker’s picture

Status: Active » Needs review
StatusFileSize
new3.83 KB

Attached it the patch.

Patch includes:
- Database upgrade hook
- Views integration

Minor Side-effect (with no solution):
After updating the database, all previous vote values are NULL. Its as if no one has voted twice or more before.

istryker’s picture

StatusFileSize
new3.27 KB

Looks like I added additional code to the patch. New patch removes this

istryker’s picture

Assigned: istryker » Unassigned
StatusFileSize
new3.65 KB

With patch #18 from #1269614: Add pre-save or pre-set hook before data is store to database you can add the previous value to be evaluated by implementing hook_votingapi_preset_votes_alter().

When you pass it by reference and set the previous value, Patch #2 breaks. You cannot select the correct vote to delete from the database, as the previous value now set. Attached is a patch that fixes this.

Simple example

function mymodule_votingapi_preset_votes_alter(&$votes) {
  foreach ($votes as &$vote) {
      $tmp = $user_info;
      $tmp += $vote;
      if (isset($vote['value'])) {
        // have to unset the value to be able to select the correct record
        // in the database to delete.
        unset($tmp['value']);
      }
      $vote['previous_value'] = votingapi_select_single_vote_value($tmp);
      ...
      // do whatever you want
      ...
   }  
}

Example that I am using in Voting Rules #1880550: Need: Pre vote or Pre cast Event

/**
 * Implements hook_votingapi_preset_votes_alter().
 */
function voting_rules_votingapi_preset_votes_alter(&$votes) {
  // for pass by reference
  $objVote = new EntityMetadataArrayObject($votes);
  for ($delta = 0; $delta < $objVote->count(); $delta++) {
    // Majority of the time you will need the previous value for comparision in a
    // rule. Voteapi module does not add before this function is called.
    $vote = $objVote->offsetGet($delta);
    if (!isset($vote['previous_value'])) {
      $tmp = votingapi_current_user_identifier();
      $tmp += $vote;
      if (isset($tmp['value'])) {
        unset($tmp['value']);
      }
      $vote['previous_value'] = votingapi_select_single_vote_value($tmp);
      $objVote->offsetSet($delta, $vote);
    }
  }
  ...
  // additional code
  ...
}
melissavdh’s picture

I have used the patch in #3 and it successfully defines a new column in the votingapi_vote table and populates it as expected. In order to expose the new previous_value field to Rules I added it to hook_rules_data_type_info() in voting_rules.module. Now I have defined a rule that says "IF vote:previous_value field is empty then award userpoints" (i.e. award the points if the user has not voted on that node before already).

Patch attached.

istryker’s picture

Status: Needs review » Reviewed & tested by the community

@melissavdh I have created the identical patch already in the Voting Rules issue queue. I should have referenced it before. #1882086: Add Rule for Previous vote value

Thank you for you comment and explanation though. It does have its place here. I believe its safe to change the status to rtbc

adamtong’s picture

will this patch in #4 committed in the module?

torotil’s picture

Status: Reviewed & tested by the community » Closed (won't fix)

I'm not in favour of adding a previous_value column to the schema. I think there are better ways to approach your use-cases. As mentioned in #3 there is already a patch that might do what you want without the additional column.

istryker’s picture

I have rethought this. If we do an additional query in the set function, before the preset hook, and grab the "current" vote and add it to the $vote variable, then we should be good.

I will create a new issue.

FYI - The 3 patches I have for Voting Rules will have to be rewritten too.

Leaving this issue closed (won't fix).

socialnicheguru’s picture

this issue is a little confusing.
the patch in #3 is the one to be applied to votingapi
the patch in https://www.drupal.org/node/1882086 should be applied to voting_rules to take advantage of #3

the patch in #4 is superceded by the patch here at https://www.drupal.org/node/1882086 as stated in 5

but why is this won't fix?