votingapi.module in Voting API 7.2
Same filename and directory in other branches
A generalized voting API for Drupal.
Maintains and provides an interface for a shared bin of vote and rating data. Modules can cast votes with arbitrary properties and VotingAPI will total them automatically. Support for basic anonymous voting by IP address hash, multi-criteria voting, arbitrary aggregation functions, etc.
Implementation of hook_help().
File
votingapi.moduleView source
<?php
/**
* @file
* A generalized voting API for Drupal.
*
* Maintains and provides an interface for a shared bin of vote and rating
* data. Modules can cast votes with arbitrary properties and VotingAPI will
* total them automatically. Support for basic anonymous voting by
* IP address hash, multi-criteria voting, arbitrary aggregation functions, etc.
*
* /**
* Implementation of hook_help().
*/
function votingapi_help($path, $arg) {
switch ($path) {
case 'admin/help#votingapi':
$output = '';
$text = 'module helps developers who want to use a standardized API';
$text .= ' and schema for storing, retrieving, and tabulating votes for';
$text .= ' Drupal content. Note that this module does NOT directly';
$text .= ' expose any voting mechanisms to end users. It is a framework';
$text .= ' designed to make life easier for other developers, and to';
$text .= ' standardize voting data for consumption by other modules';
$text .= ' (like Views). For more information, see the online';
$text .= ' documentation for the ';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The <a href="@votingapi">VotingAPI</a> ' . $text . ' <a href="@doco">VotingAPI module</a>.', array(
'@votingapi' => 'http://drupal.org/project/votingapi',
'@doco' => 'https://www.drupal.org/node/68851',
)) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('General') . '</dt>';
$output .= '<dd>' . t('VotingAPI is used to allow module developers to focus on their ideas (say, providing a "rate this thread" widget at the bottom of each forum post) without worrying about the grunt work of storing votes, preventing ballot-stuffing, calculating the results, and so on.') . '</dd>';
$output .= '<dt>' . t('Basic Concepts and Features ') . '</dt>';
$output .= '<dd>' . t('VotingAPI does four key jobs for module developers: ') . '</dd>';
$output .= '<dd>' . t('1. CRUD: Create/Retrieve/Update/Delete operations for voting data. ') . '</dd>';
$output .= '<dd>' . t('2. Calculation: Every time a user casts a vote, VotingAPI calculates the results and caches them for you. ') . '</dd>';
$output .= '<dd>' . t('3. Workflow: By integrating with Actions.module, VotingAPI can trigger workflow steps (like promoting a node to the front page, hiding a comment thathas been flagged as spam, or emailing an administrator) when votes are cast and results are tallied. ') . '</dd>';
$output .= '<dd>' . t('4. Display: VotingAPI integrates with Views.module, allowing you to slice and dice the content of your site based on user consensus. ') . '</dd>';
return $output;
}
}
/**
* Implements of hook_menu().
*/
function votingapi_menu() {
$items = array();
$items['admin/config/search/votingapi'] = array(
'title' => 'Voting API',
'description' => 'Configure sitewide settings for user-generated ratings and votes.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'votingapi_settings_form',
),
'access callback' => 'user_access',
'access arguments' => array(
'administer voting api',
),
'file' => 'votingapi.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
if (module_exists('devel_generate')) {
$items['admin/config/development/generate/votingapi'] = array(
'title' => 'Generate votes',
'description' => 'Generate a given number of votes on site content. Optionally delete existing votes.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'votingapi_generate_votes_form',
),
'access arguments' => array(
'administer voting api',
),
'file' => 'votingapi.admin.inc',
);
}
$items['admin/config/search/votingapi/general'] = array(
'title' => 'General Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/config/search/votingapi/rebuild'] = array(
'title' => t('Rebuild voting results'),
'description' => t('Allows rebuilding of voting results cache'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'votingapi_rebuild_form',
),
'access callback' => 'user_access',
'access arguments' => array(
'administer voting api',
),
'file' => 'votingapi.admin.inc',
'type' => MENU_LOCAL_TASK,
);
return $items;
}
/**
* Implements hook_permission().
*/
function votingapi_permission() {
return array(
'administer voting api' => array(
'title' => t('Administer Voting API'),
),
);
}
/**
* Implements of hook_views_api().
*/
function votingapi_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'votingapi') . '/views',
);
}
/**
* Implements of hook_cron().
*
* Allows db-intensive recalculations to be deferred until cron-time.
*/
function votingapi_cron() {
if (variable_get('votingapi_calculation_schedule', 'immediate') == 'cron') {
$time = REQUEST_TIME;
$last_cron = variable_get('votingapi_last_cron', 0);
$result = db_query('SELECT DISTINCT entity_type, entity_id FROM {votingapi_vote} WHERE timestamp > :timestamp', array(
':timestamp' => $last_cron,
));
foreach ($result as $content) {
votingapi_recalculate_results($content->entity_type, $content->entity_id, TRUE);
}
variable_set('votingapi_last_cron', $time);
}
_votingapi_cron_delete_orphaned();
}
/**
* Cast a vote on a particular piece of content.
*
* This function does most of the heavy lifting needed by third-party modules
* based on VotingAPI. Handles clearing out old votes for a given piece of
* content, saving the incoming votes, and re-tallying the results given the
* new data.
*
* Modules that need more explicit control can call votingapi_add_votes() and
* manage the deletion/recalculation tasks manually.
*
* @param array $votes
* An array of votes, each with the following structure:
* $vote['entity_type'] (Optional, defaults to 'node')
* $vote['entity_id'] (Required)
* $vote['value_type'] (Optional, defaults to 'percent')
* $vote['value'] (Required)
* $vote['tag'] (Optional, defaults to 'vote')
* $vote['uid'] (Optional, defaults to current user)
* $vote['vote_source'] (Optional, defaults to current IP)
* $vote['timestamp'] (Optional, defaults to REQUEST_TIME)
* @param array $criteria
* A keyed array used to determine what votes will be deleted when the current
* vote is cast. If no value is specified, all votes for the current content
* by the current user will be reset. If an empty array is passed in, no votes
* will be reset and all incoming votes will be saved IN ADDITION to existing
* ones.
* $criteria['vote_id'] (If this is set, all other keys are skipped)
* $criteria['entity_type']
* $criteria['entity_id']
* $criteria['value_type']
* $criteria['tag']
* $criteria['uid']
* $criteria['vote_source']
* $criteria['timestamp'] (If this is set, records with timestamps
* GREATER THAN the set value will be selected.)
*
* @return array
* An array of vote result records affected by the vote. The values are
* contained in a nested array keyed thusly:
* $value = $results[$entity_type][$entity_id][$tag][$value_type][$function]
*
* @see votingapi_add_votes()
* @see votingapi_recalculate_results()
*/
function votingapi_set_votes(&$votes, $criteria = NULL) {
$touched = array();
if (!empty($votes['entity_id'])) {
$votes = array(
$votes,
);
}
// Allow other modules to modify or unset/remove votes.
// module_invoke_all does not allow passing variables by reference
// http://api.drupal.org/api/drupal/includes%21module.inc/function/module_invoke_all/7#comment-35778
drupal_alter(array(
'votingapi_preset_votes',
), $votes);
// Handle clearing out old votes if they exist.
if (!isset($criteria)) {
// If the calling function didn't explicitly set criteria for vote deletion,
// build up the delete queries here.
foreach ($votes as $vote) {
$identifier_info = votingapi_current_user_identifier();
// Make sure we're dealing with an array to avoid errors.
if (is_array($vote) && is_array($identifier_info)) {
$tmp = $vote + $identifier_info;
}
if (isset($tmp['value'])) {
unset($tmp['value']);
}
votingapi_delete_votes(votingapi_select_votes($tmp));
}
}
elseif (is_array($criteria)) {
// The calling function passed in an explicit set of delete filters.
if (!empty($criteria['entity_id'])) {
$criteria = array(
$criteria,
);
}
foreach ($criteria as $c) {
votingapi_delete_votes(votingapi_select_votes($c));
}
}
foreach ($votes as $key => $vote) {
_votingapi_prep_vote($vote);
$votes[$key] = $vote;
// Is this needed? Check to see how PHP4 handles refs.
}
// Cast the actual votes, inserting them into the table.
votingapi_add_votes($votes);
foreach ($votes as $vote) {
$touched[$vote['entity_type']][$vote['entity_id']] = TRUE;
}
if (variable_get('votingapi_calculation_schedule', 'immediate') != 'cron') {
foreach ($touched as $type => $ids) {
foreach ($ids as $id => $bool) {
$touched[$type][$id] = votingapi_recalculate_results($type, $id);
}
}
}
return $touched;
}
/**
* Generate a proper identifier for the current user: if they have an account,
* return their UID. Otherwise, return their IP address hash.
*/
function votingapi_current_user_identifier() {
global $user;
$criteria = array(
'uid' => $user->uid,
);
if (!$user->uid) {
$criteria['vote_source'] = hash('sha256', serialize(ip_address()));
}
return $criteria;
}
/**
* Implements of hook_votingapi_storage_add_vote().
*/
function votingapi_votingapi_storage_add_vote(&$vote) {
drupal_write_record('votingapi_vote', $vote);
}
/**
* Implements of hook_votingapi_storage_delete_votes().
*/
function votingapi_votingapi_storage_delete_votes($votes, $vids) {
db_delete('votingapi_vote')
->condition('vote_id', $vids, 'IN')
->execute();
}
/**
* Implements of hook_votingapi_storage_select_votes().
*/
function votingapi_votingapi_storage_select_votes($criteria, $limit) {
$query = db_select('votingapi_vote')
->fields('votingapi_vote');
foreach ($criteria as $key => $value) {
if ($key == 'timestamp') {
$query
->condition($key, $value, '>');
}
else {
$query
->condition($key, $value, is_array($value) ? 'IN' : '=');
}
}
if (!empty($limit)) {
$query
->range(0, $limit);
}
return $query
->execute()
->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Save a collection of votes to the database.
*
* This function does most of the heavy lifting for VotingAPI the main
* votingapi_set_votes() function, but does NOT automatically triger
* re-tallying
* of results. As such, it's useful for modules that must insert their votes in
* separate batches without triggering unecessary recalculation.
*
* Remember that any module calling this function implicitly assumes
* responsibility for calling votingapi_recalculate_results() when all votes
* have been inserted.
*
* @param array $votes
* A vote or array of votes, each with the following structure:
* $vote['entity_type'] (Optional, defaults to 'node')
* $vote['entity_id'] (Required)
* $vote['value_type'] (Optional, defaults to 'percent')
* $vote['value'] (Required)
* $vote['tag'] (Optional, defaults to 'vote')
* $vote['uid'] (Optional, defaults to current user)
* $vote['vote_source'] (Optional, defaults to current IP)
* $vote['timestamp'] (Optional, defaults to REQUEST_TIME)
*
* @return array
* The same votes, with vote_id keys populated.
*
* @see votingapi_set_votes()
* @see votingapi_recalculate_results()
*/
function votingapi_add_votes(&$votes) {
if (!empty($votes['entity_id'])) {
$votes = array(
$votes,
);
}
$function = variable_get('votingapi_storage_module', 'votingapi') . '_votingapi_storage_add_vote';
foreach ($votes as $key => $vote) {
_votingapi_prep_vote($vote);
$function($vote);
$votes[$key] = $vote;
}
module_invoke_all('votingapi_insert', $votes);
return $votes;
}
/**
* Save a bundle of vote results to the database.
*
* This function is called by votingapi_recalculate_results() after tallying
* the values of all cast votes on a piece of content. This function will be of
* little use for most third-party modules, unless they manually insert their
* own result data.
*
* @param array vote_results
* An array of vote results, each with the following properties:
* $vote_result['entity_type']
* $vote_result['entity_id']
* $vote_result['value_type']
* $vote_result['value']
* $vote_result['tag']
* $vote_result['function']
* $vote_result['timestamp'] (Optional, defaults to REQUEST_TIME)
*/
function votingapi_add_results($vote_results = array()) {
if (!empty($vote_results['entity_id'])) {
$vote_results = array(
$vote_results,
);
}
foreach ($vote_results as $vote_result) {
$vote_result['timestamp'] = REQUEST_TIME;
drupal_write_record('votingapi_cache', $vote_result);
}
}
/**
* Delete votes from the database.
*
* @param $votes
* An array of votes to delete. Minimally, each vote must have the 'vote_id'
* key set.
*/
function votingapi_delete_votes($votes = array()) {
if (!empty($votes)) {
module_invoke_all('votingapi_delete', $votes);
$vids = array();
foreach ($votes as $vote) {
$vids[] = $vote['vote_id'];
}
$function = variable_get('votingapi_storage_module', 'votingapi') . '_votingapi_storage_delete_votes';
$function($votes, $vids);
}
}
/**
* Delete cached vote results from the database.
*
* @param $vote_results
* An array of vote results to delete. Minimally, each vote result must have
* the 'vote_cache_id' key set.
*/
function votingapi_delete_results($vote_results = array()) {
if (!empty($vote_results)) {
$vids = array();
foreach ($vote_results as $vote) {
$vids[] = $vote['vote_cache_id'];
}
db_delete('votingapi_cache')
->condition('vote_cache_id', $vids, 'IN')
->execute();
}
}
/**
* Select individual votes from the database.
*
* @param $criteria
* A keyed array used to build the select query. Keys can contain
* a single value or an array of values to be matched.
* $criteria['vote_id'] (If this is set, all other keys are skipped)
* $criteria['entity_id']
* $criteria['entity_type']
* $criteria['value_type']
* $criteria['tag']
* $criteria['uid']
* $criteria['vote_source']
* $criteria['timestamp'] (If this is set, records with timestamps
* GREATER THAN the set value will be selected.)
* @param $limit
* An optional integer specifying the maximum number of votes to return.
*
* @return
* An array of votes matching the criteria.
*/
function votingapi_select_votes($criteria = array(), $limit = 0) {
$window = -1;
if (empty($criteria['uid']) || $criteria['uid'] == 0) {
if (!empty($criteria['vote_source'])) {
$window = variable_get('votingapi_anonymous_window', 86400);
}
}
else {
$window = variable_get('votingapi_user_window', -1);
}
if ($window >= 0) {
$criteria['timestamp'] = REQUEST_TIME - $window;
}
$function = variable_get('votingapi_storage_module', 'votingapi') . '_votingapi_storage_select_votes';
return $function($criteria, $limit);
}
/**
* Select cached vote results from the database.
*
* @param $criteria
* A keyed array used to build the select query. Keys can contain
* a single value or an array of values to be matched.
* $criteria['vote_cache_id'] (If this is set, all other keys are skipped)
* $criteria['entity_id']
* $criteria['entity_type']
* $criteria['value']
* $criteria['value_type']
* $criteria['tag']
* $criteria['function']
* $criteria['timestamp'] (If this is set, records with timestamps
* GREATER THAN the set value will be selected.)
* @param $limit
* An optional integer specifying the maximum number of votes to return.
*
* @return
* An array of vote results matching the criteria.
*/
function votingapi_select_results($criteria = array(), $limit = 0) {
$query = db_select('votingapi_cache')
->fields('votingapi_cache');
foreach ($criteria as $key => $value) {
$query
->condition($key, $value, is_array($value) ? 'IN' : '=');
}
if (!empty($limit)) {
$query
->range(0, $limit);
}
return $query
->execute()
->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Recalculates the aggregate results of all votes for a piece of content.
*
* Loads all votes for a given piece of content, then calculates and caches the
* aggregate vote results. This is only intended for modules that have assumed
* responsibility for the full voting cycle: the votingapi_set_vote() function
* recalculates automatically.
*
* @param string $entity_type
* A string identifying the type of content being rated. Node, comment,
* aggregator item, etc.
* @param string $entity_id
* The key ID of the content being rated.
* @param bool $force_calculation
*
* @return array
* An array of the resulting votingapi_cache records, structured thusly:
* $value = $results[$ag][$value_type][$function]
*
* @see votingapi_set_votes()
*/
function votingapi_recalculate_results($entity_type, $entity_id, $force_calculation = FALSE) {
// if we're operating in cron mode, and the 'force recalculation' flag is NOT set,
// bail out. The cron run will pick up the results.
if (variable_get('votingapi_calculation_schedule', 'immediate') != 'cron' || $force_calculation == TRUE) {
$query = db_delete('votingapi_cache')
->condition('entity_type', $entity_type)
->condition('entity_id', $entity_id)
->execute();
$function = variable_get('votingapi_storage_module', 'votingapi') . '_votingapi_storage_standard_results';
// Bulk query to pull the majority of the results we care about.
$cache = $function($entity_type, $entity_id);
// Give other modules a chance to alter the collection of votes.
drupal_alter('votingapi_results', $cache, $entity_type, $entity_id);
// Now, do the caching. Woo.
$cached = array();
foreach ($cache as $tag => $types) {
foreach ($types as $type => $functions) {
foreach ($functions as $function => $value) {
$cached[] = array(
'entity_type' => $entity_type,
'entity_id' => $entity_id,
'value_type' => $type,
'value' => $value,
'tag' => $tag,
'function' => $function,
);
}
}
}
votingapi_add_results($cached);
// Give other modules a chance to act on the results of the vote totaling.
module_invoke_all('votingapi_results', $cached, $entity_type, $entity_id);
return $cached;
}
}
/**
* Returns metadata about tags, value_types, and results defined by vote
* modules.
*
* If your module needs to determine what existing tags, value_types, etc., are
* being supplied by other modules, call this function. Querying the votingapi
* tables for this information directly is discouraged, as values may not
* appear
* consistently. (For example, 'average' does not appear in the cache table
* until votes have actually been cast in the cache table.)
*
* Three major bins of data are stored: tags, value_types, and functions. Each
* entry in these bins is keyed by the value stored in the actual VotingAPI
* tables, and contains an array with (minimally) 'name' and 'description'
* keys.
* Modules can add extra keys to their entries if desired.
*
* This metadata can be modified or expanded using
* hook_votingapi_metadata_alter().
*
* @param bool $reset
* A reset status.
*
* @return array
* An array of metadata defined by VotingAPI and altered by vote modules.
*
* @see hook_votingapi_metadata_alter()
*/
function votingapi_metadata($reset = FALSE) {
static $data;
if ($reset || !isset($data)) {
$data = array(
'tags' => array(
'vote' => array(
'name' => t('Normal vote'),
'description' => t('The default tag for votes on content. If multiple votes with different tags are being cast on a piece of content, consider casting a "summary" vote with this tag as well.'),
),
),
'value_types' => array(
'percent' => array(
'name' => t('Percent'),
'description' => t('Votes in a specific range. Values are stored in a 1-100 range, but can be represented as any scale when shown to the user.'),
),
'points' => array(
'name' => t('Points'),
'description' => t('Votes that contribute points/tokens/karma towards a total. May be positive or negative.'),
),
),
'functions' => array(
'count' => array(
'name' => t('Number of votes'),
'description' => t('The number of votes cast for a given piece of content.'),
),
'average' => array(
'name' => t('Average vote'),
'description' => t('The average vote cast on a given piece of content.'),
),
'sum' => array(
'name' => t('Total score'),
'description' => t('The sum of all votes for a given piece of content.'),
'value_types' => array(
'points',
),
),
),
);
drupal_alter('votingapi_metadata', $data);
}
return $data;
}
/**
* Builds the default VotingAPI results for the three supported voting styles.
*/
function votingapi_votingapi_storage_standard_results($entity_type, $entity_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.entity_type = :type AND v.entity_id = :id AND v.value_type IN ('points', 'percent') ";
$sql .= "GROUP BY v.value_type, v.tag";
$results = db_query($sql, array(
':type' => $entity_type,
':id' => $entity_id,
));
foreach ($results as $result) {
$cache[$result->tag][$result->value_type]['count'] = $result->value_count;
$cache[$result->tag][$result->value_type]['average'] = $result->value_sum / $result->value_count;
if ($result->value_type == 'points') {
$cache[$result->tag][$result->value_type]['sum'] = $result->value_sum;
}
}
$sql = "SELECT v.tag, v.value, v.value_type, COUNT(1) AS score ";
$sql .= "FROM {votingapi_vote} v ";
$sql .= "WHERE v.entity_type = :type AND v.entity_id = :id AND v.value_type = 'option' ";
$sql .= "GROUP BY v.value, v.tag, v.value_type";
$results = db_query($sql, array(
':type' => $entity_type,
':id' => $entity_id,
));
foreach ($results as $result) {
$cache[$result->tag][$result->value_type]['option-' . $result->value] = $result->score;
}
return $cache;
}
/**
* Retrieve the value of the first vote matching the criteria passed in.
*/
function votingapi_select_single_vote_value($criteria = array()) {
if ($results = votingapi_select_votes($criteria, 1)) {
return $results[0]['value'];
}
}
/**
* Retrieve the value of the first result matching the criteria passed in.
*/
function votingapi_select_single_result_value($criteria = array()) {
if ($results = votingapi_select_results($criteria, 1)) {
return $results[0]['value'];
}
}
/**
* Populate the value of any unset vote properties.
*
* @param $vote
* A single vote.
*/
function _votingapi_prep_vote(&$vote) {
global $user;
if (is_array($vote) && empty($vote['prepped'])) {
$vote += array(
'entity_type' => 'node',
'value_type' => 'percent',
'tag' => 'vote',
'uid' => $user->uid,
'timestamp' => REQUEST_TIME,
'vote_source' => hash('sha256', serialize(ip_address())),
'prepped' => TRUE,
);
}
}
/**
* Implements hook_entity_delete().
*
* Delete all votes and cache entries for the deleted entities
*/
function votingapi_entity_delete($entity, $type) {
$ids = entity_extract_ids($type, $entity);
// We will use "Primary/Revision ID of the entity" only.
if (count($ids) > 1) {
$id = array(
$ids[0],
$ids[1],
);
}
else {
$id = array(
$ids[0],
);
}
_votingapi_delete_cache_by_entity($id, $type);
_votingapi_delete_votes_by_entity($id, $type);
}
/**
* Helper function to delete all cache entries on given entities.
*
* @param array entity ids
* @param string entity type
*/
function _votingapi_delete_cache_by_entity($entity_ids, $type) {
$result = db_select('votingapi_cache', 'v')
->fields('v', array(
'vote_cache_id',
))
->condition('entity_type', $type)
->condition('entity_id', $entity_ids)
->execute();
$votes = array();
foreach ($result as $row) {
$votes[]['vote_cache_id'] = $row->vote_cache_id;
}
votingapi_delete_results($votes);
}
/**
* Helper function to delete all votes on given entities.
*
* @param array entity ids
* @param string entity type
*/
function _votingapi_delete_votes_by_entity($entity_ids, $type) {
$result = db_select('votingapi_vote', 'v')
->fields('v', array(
'vote_id',
'entity_type',
'entity_id',
))
->condition('entity_type', $type)
->condition('entity_id', $entity_ids)
->execute();
$votes = array();
foreach ($result as $row) {
$votes[] = (array) $row;
}
votingapi_delete_votes($votes);
}
/**
* Delete votes and cache entries for a number of entities in the queue.
*/
function _votingapi_cron_delete_orphaned() {
$queue = DrupalQueue::get('VotingAPIOrphaned');
$limit = variable_get('votingapi_cron_orphaned_max', 50);
$done = 0;
while (($item = $queue
->claimItem()) && $done++ < $limit) {
_votingapi_delete_cache_by_entity(array(
$item->data['entity_id'],
), $item->data['entity_type']);
_votingapi_delete_votes_by_entity(array(
$item->data['entity_id'],
), $item->data['entity_type']);
$queue
->deleteItem($item);
}
}
Functions
Name | Description |
---|---|
votingapi_add_results | Save a bundle of vote results to the database. |
votingapi_add_votes | Save a collection of votes to the database. |
votingapi_cron | Implements of hook_cron(). |
votingapi_current_user_identifier | Generate a proper identifier for the current user: if they have an account, return their UID. Otherwise, return their IP address hash. |
votingapi_delete_results | Delete cached vote results from the database. |
votingapi_delete_votes | Delete votes from the database. |
votingapi_entity_delete | Implements hook_entity_delete(). |
votingapi_help | @file A generalized voting API for Drupal. |
votingapi_menu | Implements of hook_menu(). |
votingapi_metadata | Returns metadata about tags, value_types, and results defined by vote modules. |
votingapi_permission | Implements hook_permission(). |
votingapi_recalculate_results | Recalculates the aggregate results of all votes for a piece of content. |
votingapi_select_results | Select cached vote results from the database. |
votingapi_select_single_result_value | Retrieve the value of the first result matching the criteria passed in. |
votingapi_select_single_vote_value | Retrieve the value of the first vote matching the criteria passed in. |
votingapi_select_votes | Select individual votes from the database. |
votingapi_set_votes | Cast a vote on a particular piece of content. |
votingapi_views_api | Implements of hook_views_api(). |
votingapi_votingapi_storage_add_vote | Implements of hook_votingapi_storage_add_vote(). |
votingapi_votingapi_storage_delete_votes | Implements of hook_votingapi_storage_delete_votes(). |
votingapi_votingapi_storage_select_votes | Implements of hook_votingapi_storage_select_votes(). |
votingapi_votingapi_storage_standard_results | Builds the default VotingAPI results for the three supported voting styles. |
_votingapi_cron_delete_orphaned | Delete votes and cache entries for a number of entities in the queue. |
_votingapi_delete_cache_by_entity | Helper function to delete all cache entries on given entities. |
_votingapi_delete_votes_by_entity | Helper function to delete all votes on given entities. |
_votingapi_prep_vote | Populate the value of any unset vote properties. |