Hi all,

I am using Views to pull up stories by rating, the rating being done with the Up/Down module that uses the Voting API. Because of the peculiarities of the Voting API, if one person votes a story up and another person votes it down, then the NET result is still '0', which the Views result mistakenly assumes means it is NULL and has not been voted on at all. Well, to worsen this situation, if you have three stories rated as follows...

3, 0, -3

Views will output these three stories in the following order.

3, -3, 0

When you turn off the showing of the '0's, which are interpreted as NULLs, you are left with a list of liked stories followed by a list of hated stories, with all the stories equally liked and hated being left out.

MY quick and dirty solution was to just add an arbitrary number (100 for instance) to every single vote result, ergo...

103, 100, 97

would be the three scores, meaning Views could order them as would be logical in real life.

My question is, how can I throw this simple addition calculation into the midst of Views, on the fly, while Views is doing its job?

I suppose I could create a CCK conditional field, throw it in somewhere and have it trigger each time someone votes, changing up and down by a point, then have Views pull from that field, but it seems like a lot of work that I would prefer to avoid if only there was some function inside Views or some simple module that might give Views this functionality.

Any answers appreciated.

Thanks,
Rob

Comments

rfiertek’s picture

Sorry, meant to say I would create a CCK CALCULATION FIELD...

Drave Robber’s picture

Can you post a screenshot of your view's edit screen somewhere? (provided it contains no trade secrets :)

rfiertek’s picture

Drave Robber’s picture

I made a couple of quick experiments meanwhile, managed to reproduce at least similar, if not the same, issue, and then corrected it.

This seems to be about configuring the relationship:
- by checking 'Require this relationship', we can exclude pieces of content that have no votes at all;
- by selecting 'Total score' as 'Aggregation function', we can ensure the rest are sorted properly.

Not 100% sure though as I have only 3 pieces of content in my view at the moment.

edit: with 5, it still works. :)

rfiertek’s picture

Actually, those were the settings I did have. The following two screenshots show the results with and without the "Require Relationship" setting...

with require

without require

It seems like it might be possible to do what I am seeking by using the "Aggregation Function/Other" option, but I am not well versed enough in what sort of code I would need to be able to insert in the resulting text box, nor whether this function would even do what I needed.

Rob

Drave Robber’s picture

screenshot

The sort criterion is still 'Value', not 'Function'.

rfiertek’s picture

OK, it works! MY BAD. Once I actually placed 1 vote up and 1 vote down vote into a story, this DID properly sort, and actually did place the true '0's at the bottom, while placing the "net 0 (1 up/1 down)" in the middle of the pack, between the +1 and the -1!

Thank you!
Rob

Drave Robber’s picture

Yep, and if the relationship is required, the nodes with no votes won't appear at all.

another screenshot – page display test

a piece of content with zero sum is placed correctly.

(please pay no attention to content – this is spam I use for testing plagiarism detector :D)

rfiertek’s picture

But actually, now that I think about it, the preferred method to sort would really be...

+1
0 (1 up and 1 down vote)
0 (not voted on yet)
-1

The idea being that a "new" story, that has not had any votes cast for it yet, ought not to be placed BEHIND stories which are disliked, as this gives these new stories a negative reputation that they do not necessarily deserve.

And really, a story that is equally liked and hated IS equivalent to a new story that may have had ten people look at it and none decided it was any better or worse than some average they have in their head.

Rolling in ALL the zeros, whether voted on or not, between the positives and the negatives, would be the ideal.

Or alternately, quick and cheap, I can just leave out the nonvoted zeros altogether, though I would prefer to include them into this list.

rfiertek’s picture

OR, if the negative voted stories are somehow able to be left off the list altogether, then it does not matter if the true zeros are at the bottom of the list, since the net zeros are right before it.

hence...

+1
0 (1 up, 1 down)
0 (no vote yet)

Drave Robber’s picture

Or alternately, quick and cheap, I can just leave out the nonvoted zeros altogether, though I would prefer to include them into this list.

This is achieved by making the relationship required;

other displays don't seem so easy, as any filter when introduced kicks non-voted content out, too.

I'll take a look at Voting API docs tomorrow, there should be a more or less hackish way to create votingapi_cache records for new content.

rfiertek’s picture

I was thinking that - creation of a new story, using rules, could automatically generate a listing under Voting API, even if it shows 0 votes, but at least it is in the data table, thus able to be pulled.

Drave Robber’s picture

I took a quick stroll through the documentation, and it seems that votingapi_recalculate_results() would not only not write anything for nodes having no votes, but would delete previously existing records, too. This, of course, generally makes sense (less crap in the db), but doesn't serve this case.

Are your users permitted to withdraw their votes?

rfiertek’s picture

Seems not to be the case. I can switch out the widget with something else, and I may end up doing that anyway.

Drave Robber’s picture

I wrote a micromodule to create Voting API cache entries for new nodes. Seems to do the job.

This won't quite work if votes can be withdrawn because the cache entry would get deleted if the node, after having some votes, returns to having zero votes again. (This was why I was asking about that)

(replace 'column' with the name of your content type in line 4)

dr_votingapidoctor.info:

name = "Voting API Doctor"
description = "Creates a cache entry for new nodes so that they would properly sort in Views"
core = 6.x
package = Voting
dependencies[] = votingapi

dr_votingapidoctor.module:


function dr_votingapidoctor_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  // A new 'column' node has just been inserted.
  if ($op == 'insert' && $node->type == 'column') {
    // Prepare a blanket Voting API cache entry.
    $entry = array();
    $entry['content_type'] = 'node';
    $entry['content_id'] = $node->nid;
    $entry['value_type'] = 'points';
    $entry['value'] = 0;
    // We don't need anything but sum so far.
    $entry['function'] = 'sum';
    // Retrieve the tag used by Vote Up/Down, for the unlikely case it's not the default one.
    $entry['tag'] = variable_get('vud_tag', 'userpoints_karma');
    // Write the prepared entry. The timestamp will be added automatically.
    votingapi_add_results($entry);
  }
}

(the closing ?> tag is here for highlighting only and should not be saved into the file)

rfiertek’s picture

Works like a CHARM! Thank You!! You're a Godsend.

Of course, just so it's clear, "$node->type == 'column'" is changed to whatever node type(s) you are having be voted on, in my case 'story'.

Being still somewhat newb, I am sure I could have worked out such a module, but it would have taken me a few days, but I have seen this issue brought up before by others, so I am sure it will help many out there.

Thanks again, (I hope to keep returning the favors to the Drupal community, as I have a few times myself with some custom workarounds)
Rob

Drave Robber’s picture

Nice to hear it works. :)

I also submitted a feature request to get this into Rules Bonus Pack:
#1202904: Action: create Voting API cache entry(-ies)
...so that people who have an allergy to custom code can take advantage of this.

Drave Robber’s picture

I've created a somewhat more advanced version of this, which lets one select which node types Voting API cache entries should be automatically created for, and also lets manually create entries for old nodes:

Micromodules: Voting API cache doctor

(this also creates all five 'functions', not just sum)

alexkessler’s picture

There is a new checkbox called "Treat missing votes as zeros" for views sorting.
Uses SQL COALESCE and seems to work fine.