advpoll_voteapi.inc in Advanced Poll 7.3
Same filename and directory in other branches
Advanced Poll Vote API Include.
Handles function calls related to voting and selection of votes.
File
includes/advpoll_voteapi.incView source
<?php
/**
* @file
* Advanced Poll Vote API Include.
*
* Handles function calls related to voting and selection of votes.
*/
/**
* Get all votes related to a node by content type and node id.
*
* @param $nid
* Node ID of an advanced poll.
* @param $data
* Data from the node formatted by one of the helper functions in the
* advpoll_helper.inc document.
*
* @return array
* An array containing the keys:
* - choices: The index of each choice with its tallied votes.
* - total: The total of all votes.
*/
function advpoll_get_votes($nid, $data) {
$criteria = array();
$criteria['entity_id'] = $nid;
$criteria['entity_type'] = 'node';
$tags = array();
foreach ($data->choices as $choice) {
$tags[$choice['choice_id']] = $choice['choice_id'];
}
$criteria['tag'] = $tags;
$results = votingapi_select_votes($criteria);
if ($data->behavior === 'approval') {
$tabulated = advpoll_approval_vote($results);
}
elseif ($data->behavior === 'pool') {
$tabulated = advpoll_pooled_vote($results);
}
else {
$tabulated = advpoll_default_vote($results);
}
return $tabulated;
}
/**
* Tally votes by approval method.
*
* For approval voting, multiple choices cast by a single user count as one
* vote.
*
* @param array $results
* Results returned from voting api.
*
* @return array
* Associative array containing vote choices in descending order and total
* votes.
* $choices contains:
* - index: The index of the choice.
* - percentage: Percentage of votes choice received.
* - votes: The number of votes received.
*/
function advpoll_approval_vote($results) {
$tallied = array();
$source = array();
foreach ($results as $result) {
if (isset($tallied[$result['tag']])) {
$tallied[$result['tag']]++;
}
else {
$tallied[$result['tag']] = 1;
}
$source[$result['timestamp']] = 1;
}
$total = count($source);
$tabulated = advpoll_calculate_percentage($tallied, $total);
return array(
'choices' => $tabulated,
'total' => $total,
);
}
/**
* Tally votes by pooling them.
*
* All votes, whether cast by single or multichoice bear the same weight.
*
* @param array $results
* Results returned from voting api.
*
* @return array
* Associative array containing vote choices in descending order and total
* votes.
* Contains:
* - index: The index of the choice.
* - percentage: Percentage of votes choice received.
* - votes: The number of votes received.
*
*/
function advpoll_pooled_vote($results) {
$tallied = array();
$total = 0;
foreach ($results as $result) {
if (isset($tallied[$result['tag']])) {
$tallied[$result['tag']]++;
}
else {
$tallied[$result['tag']] = 1;
}
$total++;
}
$tabulated = advpoll_calculate_percentage($tallied, $total);
return array(
'choices' => $tabulated,
'total' => $total,
);
}
/**
* Default voting count.
*
* Uses the 'value' field returned by the voting API to tally votes and arrive
* at percentages.
*
* @param array $results
* Results returned from voting api.
*
* @return array
* Associative array containing vote choices in descending order and total
* votes.
* $choices contains:
* - index: The index of the choice.
* - percentage: Percentage of votes choice received.
* - votes: The number of votes received.
*/
function advpoll_default_vote($results) {
$tallied = array();
$total = 0;
$total_points = 0;
foreach ($results as $result) {
$points = (int) $result['value'];
if (isset($tallied[$result['tag']])) {
$tallied[$result['tag']] += $points;
}
else {
$tallied[$result['tag']] = $points;
}
$total_points += $points;
$total++;
}
$tabulated = advpoll_calculate_percentage($tallied, $total_points);
return array(
'choices' => $tabulated,
'total' => $total,
);
}
/**
* Return keyed array with percentages for each index.
*
* @param $tallied
* Array containing totals per choice index.
* @param $total
* Total number of votes.
*
* @return array
* An associative array containing:
* - index: The index of the choice.
* - percentage: The percentage of votes.
* - votes: The number of votes received.
*/
function advpoll_calculate_percentage($tallied, $total) {
$tabulated = array();
$precision = intval(variable_get('advpoll_percentage_precision', 0));
$pow = pow(10, $precision);
foreach ($tallied as $key => $value) {
$percentage = (int) $value / (int) $total * 100;
$percentage = number_format(advpoll_round($percentage * $pow) / $pow, $precision);
$tabulated[] = array(
'index' => $key,
'percentage' => $percentage,
'votes' => $value,
);
}
usort($tabulated, "advpoll_compare");
$tabulated = array_reverse($tabulated);
return $tabulated;
}
/**
* Callback for usort to order items by percentage.
*/
function advpoll_compare($a, $b) {
if ($a['percentage'] > $b['percentage']) {
return 1;
}
elseif ($a['percentage'] < $b['percentage']) {
return -1;
}
else {
return 0;
}
}
/**
* Checks for user's eligibility to vote on a given poll.
*
* Provides a series of fall-through tests to determine user's ability to vote.
*
* @param $node
* The poll node.
*
* @return bool
* TRUE or FALSE.
*/
function advpoll_user_eligibility($node) {
if (!user_access('vote on polls')) {
return FALSE;
}
global $user;
$data = advpoll_get_data($node);
if ($data->write_in && !user_access('add write-ins')) {
return FALSE;
}
if ($data->electoral) {
if (!advpoll_check_electoral_list($user->uid, $node->nid)) {
return FALSE;
}
}
if ($data->state !== 'open') {
return FALSE;
}
// It is possible for a user to not set a start or end date.
if ($data->start_date && $data->end_date) {
if ($data->start_date > time() || $data->end_date < time()) {
return FALSE;
}
}
if ($data->mode === 'cookie' && isset($_COOKIE[$node->type . $node->nid])) {
return FALSE;
}
if ($data->mode === 'normal') {
$criteria = array();
$criteria['entity_id'] = $node->nid;
$criteria['entity_type'] = 'node';
$criteria['value_type'] = 'percent';
$criteria['uid'] = $user->uid;
if (!$user->uid) {
$criteria['vote_source'] = ip_address();
}
$results = votingapi_select_votes($criteria);
if ($results) {
return FALSE;
}
}
$access = TRUE;
$context = array(
'node' => $node,
'data' => $data,
);
drupal_alter('advpoll_user_eligibility_post', $access, $context);
return $access;
}
/**
* Checks user against electoral list.
*
* @param $uid
* User's ID.
* @param $nid
* Node ID of the poll.
*
* @return bool
* TRUE or FALSE
*/
function advpoll_check_electoral_list($uid, $nid) {
$result = db_query("\n SELECT uid\n FROM {advpoll_electoral_list}\n WHERE uid = :uid AND nid = :nid\n ", array(
':uid' => $uid,
':nid' => $nid,
))
->fetchField();
if ($result) {
return TRUE;
}
return FALSE;
}
/**
* Add votes for a given poll.
*
* @param array $vote
* An associative array that is used to determine the method in which the vote
* will be tracked and what values will be passed to votingapi. It contains:
* - type: The content type - either advpoll or advpoll_ranking.
* - tag: Tag corresponds to the index of the selected choice.
* - nid: The node ID of poll being voted on.
* - mode: normal, cookie, or unlimited.
* - duration: duration is minutes that the cookie will last if one is set.
*/
function advpoll_add_votes($vote) {
/* Normal voting uses the votingapi to record user id or ip based on
* authentication.
*/
if ($vote['mode'] === 'normal') {
$votes = array(
'entity_type' => $vote['type'],
'entity_id' => $vote['nid'],
'value' => $vote['value'],
'tag' => $vote['tag'],
);
}
else {
/* Unlimited and cookie voting simply add values to the votingapi and bypass
* user id and ip as source. Time stamp instead of ip will prevent a unique
* id from being tied to these voters.
*/
if ($vote['mode'] === 'cookie') {
/* Necessary to pass Drupal's $cookie_domain to get this to stick.
* Raw cookies are safe in this case as we're only passing a static value
* to mark that this user voted on their machine.
*/
global $cookie_domain;
//Check if duration is 0 (IE Session) and set duration based on this.
if ($vote['duration'] == 0) {
$duration = 0;
}
else {
$duration = time() + 60 * $vote['duration'];
}
setrawcookie($vote['nodetype'] . $vote['nid'], 'vote', $duration, '/', $cookie_domain);
}
$votes = array(
'entity_type' => $vote['type'],
'entity_id' => $vote['nid'],
'value' => $vote['value'],
'tag' => $vote['tag'],
'uid' => '',
'vote_source' => time(),
);
}
votingapi_set_votes($votes);
}
/**
* Processes votes cast via checkboxes.
*
* Checkbox values returned by form_state have a different structure
* than radio buttons. We need an array of indexes representing
* items selected from list of choices.
*
* @param array $choices
* An array containing available choices in the poll.
* @param array $votes
* Text of choices selected from the form_state. Need to match them up with
* choices saved in the node.
*
* @return array
* The the unique IDs of the choices selected by the user.
*
*/
function advpoll_checkbox_selected($choices, $votes) {
$selected = array();
$count = count($choices);
for ($i = 0; $i < $count; $i++) {
$choice = strip_tags($choices[$i]['choice_id']);
if (isset($votes[$choice]) && ctype_xdigit($votes[$choice]) && !empty($votes[$choice])) {
$selected[] = $choices[$i]['choice_id'];
}
}
return $selected;
}
/**
* Processes votes cast via radio buttons.
*
* Radio buttons returns a string rather than an array.
*
* @param array $choices
* An array containing available choices in the poll.
* @param array $vote
* Text of choice selected from the form_state. Need to match it up with
* choices saved in the node.
*
* @return array
* The unique ID of the choice selected by the user.
*/
function advpoll_radio_selected($choices, $vote) {
$selected = array();
$count = count($choices);
for ($i = 0; $i < $count; $i++) {
$choice = strip_tags($choices[$i]['choice_id']);
if ($choice == strip_tags($vote)) {
$selected[] = $choices[$i]['choice_id'];
}
}
return $selected;
}
/**
* Returns unique choice ids for a given node id and user id.
*
* @param $nid
* The node ID of the poll to be examined for the current user.
*
* @return array
* Unique choice IDs selected by the user.
*/
function advpoll_get_user_votes($nid) {
global $user;
$votes = array();
$criteria = array();
$criteria['entity_id'] = $nid;
$criteria['entity_type'] = 'node';
$criteria['value_type'] = 'percent';
$criteria['uid'] = $user->uid;
if (!$user->uid) {
$criteria['vote_source'] = ip_address();
}
$results = votingapi_select_votes($criteria);
if ($results) {
foreach ($results as $result) {
$votes[] = $result['tag'];
}
}
return $votes;
}
Functions
Name | Description |
---|---|
advpoll_add_votes | Add votes for a given poll. |
advpoll_approval_vote | Tally votes by approval method. |
advpoll_calculate_percentage | Return keyed array with percentages for each index. |
advpoll_checkbox_selected | Processes votes cast via checkboxes. |
advpoll_check_electoral_list | Checks user against electoral list. |
advpoll_compare | Callback for usort to order items by percentage. |
advpoll_default_vote | Default voting count. |
advpoll_get_user_votes | Returns unique choice ids for a given node id and user id. |
advpoll_get_votes | Get all votes related to a node by content type and node id. |
advpoll_pooled_vote | Tally votes by pooling them. |
advpoll_radio_selected | Processes votes cast via radio buttons. |
advpoll_user_eligibility | Checks for user's eligibility to vote on a given poll. |