VotingAPI 2.0 under development

Events happening in the community are now at Drupal community events on www.drupal.org.
eaton's picture

With the Drupal 6 code freeze, it's time to crack down on some of the existing VotingAPI bugs and put together the battle plan for something that's been a long time coming: VotingAPI 2.0, for Drupal 6.

What will VotingAPI 2.0 offer? Nothing that can't already be done with some elbow-grease. The goal is not to dramatically expand what it does, but to streamline the APIs and make things work a bit smoother.

  • Support anonymous voting with settings. Fivestar already uses a simple version of this: if anonymous users have permission to vote, they are restricted to one vote per IP address per hour. The plan is to offer several configurable settings for how anon users are identified, including timespans, optional setting of cookies, and so on.
  • Streamlining a number of the support/helper functions. Right now, there's a rat's nest of querying and updating functions to be used in different scenerios. I'd like to get these trimmed down to just two or three, for individual votes and cached votes.
  • Simplify the use of votingapi_set_vote(). Right now, it's possible to pass in an int, an object, or an array of objects to this function -- it will do different things in each scenerio. I'd like to simplify that to just 'object' and 'array of objects.' Each object can be as simple as 'content id/value', and defaults will be used for all other values like tag, value_type, etc... but it will greatly simplify some of the processing. This will change the function signature a bit for folks who are casting simple numerical votes, but it shouldn't be too different.
  • Provide a handful of new hooks for cleaner views integration
  • Provide a new field for each vote: module. This isn't essential, but for modules doing VERY tweaky things, it would make it possible to query up JUST the votes that should be altered.

Any thoughts? Suggestions?

Comments

Plugins?

gerd riesselmann's picture

Hi Eaton, glad to hear VotingAPI 2 is on the way!

Here's something I am thinking about for a couple of weeks: VotingAPI Plugins.

One of the most wanted features for Userreview Module I am maintaining is voting on independent factors like already supported by the node review module. If I port the according code of the node review module, however, this would end up in code duplication. Same holds if a user wants the 5-Star-Voting UI rather than the UI provided by userreview itself.

This leads me to the concept of plugins or "module-modules": If we separate the processing of votes, the voting UI, and the rights management into different units that are independently combinable we allow much more flexibility.

What does that mean?

  • Processing: This means the backend that contains the voting logic. I think of specialized modules/plugins for multiple axis voting, or percentage voting, or 1 to 10 or whatever.
  • UI: If I have for example a 1 to 10 voting backend, I can have a five star UI, or a slider, or a dropdown, or 10 different funny pictures that play a sound when the mouse hovers over them. Having the UI seperated, this would allow development of Voting User Interfaces without supplying any other kind of functionality.
  • Rights management: I think that what really distinct user review and node review is the question of when to display the voting UI to whom - and nothing more. Everything else is just ballast in the end. Having the right management separated would allow to really concentrate on this single feature and dramatically reduce complexity.

Having independent plugins, the user can combine the user review rights management with the mutiple axis backend logic and - say - one of 4 multiple axis UI modules. But she can also use the 5 star voting backend instead and combine it with the "funny pictures with sound" voting UI.

You get the idea?

Following this approach, Voting API itself would be split into 3 loosely coupled subunits that communicate via hooks only (the Drupal way of expressing an interface). This would require a major rewrite of all recent voting modules. However, I think we all would benefit from this step, and so would the the users.

What do you think? What do other think?

Cheers,

Gerd


Gerd Riesselmann
http://www.gerd-riesselmann.net

Thanks for the

eaton's picture

Thanks for the reply!

Actually, the approach that you describe is already the way things can be set up. VotingAPI provides the underlying workflow mechanism for voting, and a number of 'default' aggregate calculations for processing vote results. But any module can hook in and provide their own functions (like role-weighted vote averages, time-sliced averages, etc.) hook_votingapi_calculate() is the mechanism for that.

UI and rights management, at least for the moment, is handled completely by the modules that live 'on top' of VotingAPI. Early on, I experimented with a module I called custom_vote, which provided a plugin architecture for vote widgets, calculation types, etc. Eventually it became clear that the approach wasn't a good match: people with simple voting needs didn't want the complexity that the additional layer of plugins and configuration added. And people with highly specialized needs had to write custom code anyways, and were using VotingAPI themselves.

Right now, the approach is as follows:

VotingAPI handles storing, retrieving, and calculating votes
Workflow modules like Voting Actions handle what should happen after votes are cast
Modules like Vote Up/Down, Fivestar, etc provide specific voting interfaces and permissions.

I'm open to the possibility of additional layers on top of VotingAPI, but I think they'd need to be thought out carefully. Do you have any ideas how this division of responsibility would work at an API level?

Artem's picture

Hi Eaton

Great to see that you are looking for suggestions! Everything you listed sounds reasonable. However, I cannot quite find a [plug-in] place for the functionality I'd like to use.

I am currently into creating Digg-like sites. What I'd like to have is some kind of automated tuning of the voting conditions. For example, instead of saying that node needs 5 votes to be promoted to the front page, I'd like to say that only one node that got most votes during the day should be promoted. Or maybe I'd also like to take into account only nodes submitted only during the last week.

Certainly with some amount of PHP-coding could be implemented even with the current Voting API, however, it is not fun and is quite a lot of coding. What I see missing from the Voting API is:
1. The concept of "now" (to consider only lately published nodes)
2. An easy way to consider only "lately casted" votes.
3. A way to work with some aggregation of votes over many nodes. There are indeed ways to act when a "sum" or "count" of votes for a particular node, but I don't see an easy way to fire action when some node group condition is satisfied.

To put one more example, I could imagine some action to be fired when the nodes in a particular category get many votes. The action could be to decrease the value of the "inflated category"

I not quite sure how to implement such requests. However, it is what I would consider useful for myself and I believe for many other site admins.

hook_votingapi_calculate

eaton's picture

Great to see that you are looking for suggestions! Everything you listed sounds reasonable. However, I cannot quite find a [plug-in] place for the functionality I'd like to use.

Any module that implements hook_votingapi_calculate() can intercept the calculation of vote results from individual votes -- discarding data from votes older than a week, mixing in a multiplier based on the category the content is in, adding additional functions (like 'velocity') beyond the standard average and sum, etc.

The API is bad at remixing vote results based purely on time, when no additional votes have been cast. It would be possible to query nodes whose last result summation is older than N, and call votingapi_recalculate_results('node', $nid) to re-weight the results based on the current timestamp...

I realize that it is

Artem's picture

I realize that it is possible. In fact I even wrote a similar module for myself (though went for a simpler solution later). My point is in that at the moment it is a bit too complex and requires a bit too much programming. In my opinion Voting API could/should provide a little bit more possibilities for plugging the formulas in exactly when it comes to acting on many votes.

Example
Let me bring a concrete example where I felt quite limited by the Voting API
I wanted to make a self-tuning Digg-like site that every day would promote one and only one node to the front page basing on both how many votes are casted and on when they've been casted - old votes are valued less.

I don't know any direct way to implement the idea above with the current API.
- What I found "almost working" was to create a function called timedPriority that essentially was "Sum" decayed by time.
- Then on every vote I had to go over 10 most lately published non-promoted nodes, recalculating timedPriority (with the special protection against recursive hook_votingapi_calculate!).
- Then basing on timed priority and time since the last automated promotion I was calculating function shouldBePromotedToFrontPageNow function that was always 1 or 0.

As you've told it is indeed possible to do a lot using the votingapi_calculate hook. However, in this case I felt like bypassing the VotingAPI and reinventing the [hard-coded] wheel instead of focusing on the rules or business logic if you like.

What would have helped me and is either missing or I failed to figure it out
I believe the real custom things that the custom module should have had provided were:
1. The rule on how to choose the nodes that should be taken into account - the 10 latest non-promoted in my case
2. The formula to figure out the node(s) upon which the actions should be fired
3. Possibly the cron hook to fire recalculation of the time-dependent formulas. Though clever caching might also solve it
Unfortunately, at the moment it is quite difficult to consider only a subset of nodes and to fire action NOT on the node with the latest vote casted.


That said I indeed find VotingAPI very useful. It is just so that at the moment some things while possible are a bit too difficult to implement.

a use case: Votes by my

moshe weitzman's picture

a use case:

Votes by my buddies should count twice as much as votes by non buddies. This has repurcussions for cache table and views especially. each user sees a personalized score.

Voting Systems

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: