Newer
Older
// $Id$
/**
* @file
* Enables your site to capture votes on different topics in the form of multiple
* choice questions.
*/
Dries Buytaert
committed
/**
* Implementation of hook_help().
*/
Gábor Hojtsy
committed
function poll_help($path, $arg) {
switch ($path) {
Gábor Hojtsy
committed
$output = '<p>'. t('The poll module can be used to create simple polls for site users. A poll is a simple, multiple choice questionnaire which displays the cumulative results of the answers to the poll. Having polls on the site is a good way to receive feedback from community members.') .'</p>';
$output .= '<p>'. t('When creating a poll, enter the question being posed, as well as the potential choices (and beginning vote counts for each choice). The status and duration (length of time the poll remains active for new votes) can also be specified. Use the <a href="@poll">poll</a> menu item to view all current polls. To vote in or view the results of a specific poll, click on the poll itself.', array('@poll' => url('poll'))) .'</p>';
Gábor Hojtsy
committed
$output .= '<p>'. t('For more information, see the online handbook entry for <a href="@poll">Poll module</a>.', array('@poll' => 'http://drupal.org/handbook/modules/poll/')) .'</p>';
Dries Buytaert
committed
return $output;
Dries Buytaert
committed
/**
* Implementation of hook_init().
*/
function poll_init() {
drupal_add_css(drupal_get_path('module', 'poll') .'/poll.css');
}
Dries Buytaert
committed
/**
* Implementation of hook_theme()
*/
function poll_theme() {
return array(
Dries Buytaert
committed
'poll_vote' => array(
'template' => 'poll-vote',
Dries Buytaert
committed
'arguments' => array('form' => NULL),
),
'poll_choices' => array(
'arguments' => array('form' => NULL),
),
Dries Buytaert
committed
'poll_results' => array(
'template' => 'poll-results',
Dries Buytaert
committed
'arguments' => array('raw_title' => NULL, 'results' => NULL, 'votes' => NULL, 'raw_links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL),
Dries Buytaert
committed
),
'poll_bar' => array(
'template' => 'poll-bar',
Dries Buytaert
committed
'arguments' => array('title' => NULL, 'votes' => NULL, 'total_votes' => NULL, 'vote' => NULL, 'block' => NULL),
Dries Buytaert
committed
),
);
}
Dries Buytaert
committed
/**
* Implementation of hook_perm().
*/
function poll_perm() {
$perms = node_list_permissions('poll');
$perms += array(
'vote on polls' => t('Cast votes on polls.'),
'cancel own vote' => t('Retract and optionally change own votes.'),
'inspect all votes' => t('View voting results.'),
);
return $perms;
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Implementation of hook_access().
*/
function poll_access($op, $node, $account) {
switch ($op) {
case 'create':
Gábor Hojtsy
committed
return user_access('create poll content', $account);
case 'update':
Gábor Hojtsy
committed
return user_access('edit any poll content', $account) || (user_access('edit own poll content', $account) && ($node->uid == $account->uid));
Gábor Hojtsy
committed
case 'delete':
return user_access('delete any poll content', $account) || (user_access('delete own poll content', $account) && ($node->uid == $account->uid));
Dries Buytaert
committed
/**
* Implementation of hook_menu().
*/
function poll_menu() {
$items['poll'] = array(
'title' => 'Polls',
'page callback' => 'poll_page',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
'file' => 'poll.pages.inc',
Dries Buytaert
committed
);
$items['node/%node/votes'] = array(
'title' => 'Votes',
'page callback' => 'poll_votes',
'page arguments' => array(1),
'access callback' => '_poll_menu_access',
'access arguments' => array(1, 'inspect all votes', FALSE),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
'file' => 'poll.pages.inc',
Dries Buytaert
committed
);
$items['node/%node/results'] = array(
'title' => 'Results',
'page callback' => 'poll_results',
'page arguments' => array(1),
'access callback' => '_poll_menu_access',
'access arguments' => array(1, 'access content', TRUE),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
'file' => 'poll.pages.inc',
Dries Buytaert
committed
);
$items['poll/js'] = array(
'title' => 'Javascript Choice Form',
'page callback' => 'poll_choice_js',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
Dries Buytaert
committed
return $items;
}
/**
* Callback function to see if a node is acceptable for poll menu items.
*/
function _poll_menu_access($node, $perm, $inspect_allowvotes) {
return user_access($perm) && ($node->type == 'poll') && ($node->allowvotes || !$inspect_allowvotes);
}
Dries Buytaert
committed
/**
* Implementation of hook_block().
*
* Generates a block containing the latest poll.
*/
Dries Buytaert
committed
function poll_block($op = 'list', $delta = '') {
if (user_access('access content')) {
if ($op == 'list') {
Dries Buytaert
committed
$blocks['recent']['info'] = t('Most recent poll');
else if ($op == 'view') {
Dries Buytaert
committed
// Retrieve the latest poll.
Dries Buytaert
committed
$sql = db_rewrite_sql("SELECT MAX(n.created) FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1");
Dries Buytaert
committed
$poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'status' => 1));
Dries Buytaert
committed
$poll = poll_view($poll, TRUE, FALSE, TRUE);
Dries Buytaert
committed
$block['content'] = drupal_render($poll->content);
Dries Buytaert
committed
/**
* Implementation of hook_cron().
*
* Closes polls that have exceeded their allowed runtime.
*/
$result = db_query('SELECT p.nid FROM {poll} p INNER JOIN {node} n ON p.nid = n.nid WHERE (n.created + p.runtime) < '. time() .' AND p.active = 1 AND p.runtime != 0');
db_query("UPDATE {poll} SET active = 0 WHERE nid = %d", $poll->nid);
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implementation of hook_node_info().
Dries Buytaert
committed
*/
Dries Buytaert
committed
function poll_node_info() {
return array(
'poll' => array(
'name' => t('Poll'),
'module' => 'poll',
'description' => t('A <em>poll</em> is a question with a set of possible responses. A <em>poll</em>, once created, automatically provides a simple running count of the number of votes received for each response.'),
Dries Buytaert
committed
'title_label' => t('Question'),
'has_body' => FALSE,
)
);
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Implementation of hook_form().
*/
Dries Buytaert
committed
function poll_form(&$node, $form_state) {
global $user;
$admin = user_access('administer nodes') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid);
Neil Drumm
committed
$type = node_get_types('type', $node);
$form = array(
'#cache' => TRUE,
);
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#weight' => -5,
);
Dries Buytaert
committed
if (isset($form_state['choice_count'])) {
$choice_count = $form_state['choice_count'];
}
else {
$choice_count = max(2, empty($node->choice) ? 2 : count($node->choice));
// Add a wrapper for the choices and more button.
$form['choice_wrapper'] = array(
'#tree' => FALSE,
Gábor Hojtsy
committed
'#weight' => -4,
'#prefix' => '<div class="clear-block" id="poll-choice-wrapper">',
'#suffix' => '</div>',
);
// Container for just the poll choices.
$form['choice_wrapper']['choice'] = array(
'#prefix' => '<div id="poll-choices">',
'#suffix' => '</div>',
'#theme' => 'poll_choices',
);
// Add the current choices to the form.
for ($delta = 0; $delta < $choice_count; $delta++) {
$text = isset($node->choice[$delta]['chtext']) ? $node->choice[$delta]['chtext'] : '';
$votes = isset($node->choice[$delta]['chvotes']) ? $node->choice[$delta]['chvotes'] : 0;
$form['choice_wrapper']['choice'][$delta] = _poll_choice_form($delta, $text, $votes);
}
// We name our button 'poll_more' to avoid conflicts with other modules using
// AHAH-enabled buttons with the id 'more'.
$form['choice_wrapper']['poll_more'] = array(
'#type' => 'submit',
'#value' => t('More choices'),
'#description' => t("If the amount of boxes above isn't enough, click here to add more choices."),
'#weight' => 1,
'#submit' => array('poll_more_choices_submit'), // If no javascript action.
'#ahah' => array(
'path' => 'poll/js',
'wrapper' => 'poll-choices',
'method' => 'replace',
'effect' => 'fade',
),
);
Steven Wittens
committed
$_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval");
$_active = array(0 => t('Closed'), 1 => t('Active'));
$form['settings'] = array(
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#title' => t('Poll settings'),
Gábor Hojtsy
committed
'#weight' => -3,
);
$form['settings']['active'] = array(
'#type' => 'radios',
'#title' => t('Poll status'),
'#default_value' => isset($node->active) ? $node->active : 1,
'#options' => $_active,
'#description' => t('When a poll is closed, visitors can no longer vote for it.')
);
$form['settings']['runtime'] = array(
'#type' => 'select',
'#title' => t('Poll duration'),
Steven Wittens
committed
'#default_value' => isset($node->runtime) ? $node->runtime : 0,
'#options' => $_duration,
'#description' => t('After this period, the poll will be closed automatically.'),
);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/**
* Submit handler to add more choices to a poll form. This handler is used when
* javascript is not available. It makes changes to the form state and the
* entire form is rebuilt during the page reload.
*/
function poll_more_choices_submit($form, &$form_state) {
// Set the form to rebuild and run submit handlers.
node_form_submit_build_node($form, $form_state);
// Make the changes we want to the form state.
if ($form_state['values']['poll_more']) {
$form_state['choice_count'] = count($form_state['values']['choice']) + 5;
}
}
function _poll_choice_form($delta, $value = '', $votes = 0) {
$admin = user_access('administer nodes');
$form = array(
'#tree' => TRUE,
);
// We'll manually set the #parents property of these fields so that
// their values appear in the $form_state['values']['choice'] array.
$form['chtext'] = array(
'#type' => 'textfield',
'#title' => t('Choice @n', array('@n' => ($delta + 1))),
'#default_value' => $value,
Gábor Hojtsy
committed
'#parents' => array('choice', $delta, 'chtext'),
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
);
if ($admin) {
$form['chvotes'] = array(
'#type' => 'textfield',
'#title' => t('Votes for choice @n', array('@n' => ($delta + 1))),
'#default_value' => $votes,
'#size' => 5,
'#maxlength' => 7,
'#parents' => array('choice', $delta, 'chvotes'),
);
}
return $form;
}
/**
* Menu callback for AHAH additions.
*/
function poll_choice_js() {
$delta = count($_POST['choice']);
// Build our new form element.
$form_element = _poll_choice_form($delta);
drupal_alter('form', $form_element, array(), 'poll_choice_js');
// Build the new form.
$form_state = array('submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
// Add the new element to the stored form. Without adding the element to the
// form, Drupal is not aware of this new elements existence and will not
// process it. We retreive the cached form, add the element, and resave.
$form = form_get_cache($form_build_id, $form_state);
$form['choice_wrapper']['choice'][$delta] = $form_element;
form_set_cache($form_build_id, $form, $form_state);
$form += array(
'#post' => $_POST,
'#programmed' => FALSE,
);
// Rebuild the form.
$form = form_builder('poll_node_form', $form, $form_state);
// Render the new output.
$choice_form = $form['choice_wrapper']['choice'];
unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers.
$choice_form[$delta]['#attributes']['class'] = empty($choice_form[$delta]['#attributes']['class']) ? 'ahah-new-content' : $choice_form[$delta]['#attributes']['class'] .' ahah-new-content';
$choice_form[$delta]['chvotes']['#value'] = 0;
$output = theme('status_messages') . drupal_render($choice_form);
drupal_json(array('status' => TRUE, 'data' => $output));
}
Dries Buytaert
committed
/**
* Implementation of hook_submit().
*/
function poll_node_form_submit(&$form, &$form_state) {
// Renumber fields
$form_state['values']['choice'] = array_values($form_state['values']['choice']);
$form_state['values']['teaser'] = poll_teaser((object)$form_state['values']);
Dries Buytaert
committed
* Implementation of hook_validate().
Dries Buytaert
committed
function poll_validate($node) {
if (isset($node->title)) {
// Check for at least two options and validate amount of votes:
$realchoices = 0;
// Renumber fields
$node->choice = array_values($node->choice);
foreach ($node->choice as $i => $choice) {
if ($choice['chtext'] != '') {
$realchoices++;
}
if (isset($choice['chvotes']) && $choice['chvotes'] < 0) {
Dries Buytaert
committed
form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
}
}
Dries Buytaert
committed
if ($realchoices < 2) {
form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
}
}
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Implementation of hook_load().
*/
global $user;
$poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid));
Gábor Hojtsy
committed
// Load the appropriate choices into the $poll object.
$result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid = %d ORDER BY chorder", $node->nid);
while ($choice = db_fetch_array($result)) {
$poll->choice[$choice['chorder']] = $choice;
Gábor Hojtsy
committed
// Determine whether or not this user is allowed to vote.
$poll->allowvotes = FALSE;
if (user_access('vote on polls') && $poll->active) {
if ($user->uid) {
$result = db_fetch_object(db_query('SELECT chorder FROM {poll_votes} WHERE nid = %d AND uid = %d', $node->nid, $user->uid));
}
else {
$result = db_fetch_object(db_query("SELECT chorder FROM {poll_votes} WHERE nid = %d AND hostname = '%s'", $node->nid, ip_address()));
}
if (isset($result->chorder)) {
$poll->vote = $result->chorder;
}
else {
$poll->vote = -1;
$poll->allowvotes = TRUE;
}
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implementation of hook_insert().
Dries Buytaert
committed
*/
Dries Buytaert
committed
function poll_insert($node) {
if (!user_access('administer nodes')) {
// Make sure all votes are 0 initially
foreach ($node->choice as $i => $choice) {
$node->choice[$i]['chvotes'] = 0;
}
$node->active = 1;
}
db_query("INSERT INTO {poll} (nid, runtime, active) VALUES (%d, %d, %d)", $node->nid, $node->runtime, $node->active);
$i = 0;
foreach ($node->choice as $choice) {
if ($choice['chtext'] != '') {
db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $choice['chtext'], $choice['chvotes'], $i++);
}
}
}
/**
* Implementation of hook_update().
*/
function poll_update($node) {
Gábor Hojtsy
committed
// Update poll settings.
Dries Buytaert
committed
db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
Gábor Hojtsy
committed
// Clean poll choices.
Dries Buytaert
committed
db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
Gábor Hojtsy
committed
// Poll choices come in the same order with the same numbers as they are in
// the database, but some might have an empty title, which signifies that
// they should be removed. We remove all votes to the removed options, so
// people who voted on them can vote again.
$new_chorder = 0;
foreach ($node->choice as $old_chorder => $choice) {
$chvotes = isset($choice['chvotes']) ? (int)$choice['chvotes'] : 0;
Dries Buytaert
committed
$chtext = $choice['chtext'];
Gábor Hojtsy
committed
if (!empty($chtext)) {
db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $new_chorder);
if ($new_chorder != $old_chorder) {
// We can only remove items in the middle, not add, so
// new_chorder is always <= old_chorder, making this safe.
db_query("UPDATE {poll_votes} SET chorder = %d WHERE nid = %d AND chorder = %d", $new_chorder, $node->nid, $old_chorder);
}
$new_chorder++;
}
else {
db_query("DELETE FROM {poll_votes} WHERE nid = %d AND chorder = %d", $node->nid, $old_chorder);
Dries Buytaert
committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
}
}
}
/**
* Implementation of hook_delete().
*/
function poll_delete($node) {
db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {poll_votes} WHERE nid = %d", $node->nid);
}
/**
* Implementation of hook_view().
*
* @param $block
* An extra parameter that adapts the hook to display a block-ready
* rendering of the poll.
*/
function poll_view($node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
global $user;
$output = '';
// Special display for side-block
if ($block) {
// No 'read more' link
$node->readmore = FALSE;
$links = module_invoke_all('link', 'node', $node, 1);
$links[] = array('title' => t('Older polls'), 'href' => 'poll', 'attributes' => array('title' => t('View the list of polls on this site.')));
if ($node->allowvotes && $block) {
$links[] = array('title' => t('Results'), 'href' => 'node/'. $node->nid .'/results', 'attributes' => array('title' => t('View the current poll results.')));
}
$node->links = $links;
}
if (!empty($node->allowvotes) && ($block || empty($node->show_results))) {
$node->content['body'] = array(
'#value' => drupal_get_form('poll_view_voting', $node, $block),
);
}
else {
$node->content['body'] = array(
'#value' => poll_view_results($node, $teaser, $page, $block),
);
}
return $node;
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Creates a simple teaser that lists all the choices.
Dries Buytaert
committed
*
* This is primarily used for RSS.
Dries Buytaert
committed
*/
$teaser = NULL;
if ($choice['chtext'] != '') {
$teaser .= '* '. check_plain($choice['chtext']) ."\n";
}
}
}
return $teaser;
}
Dries Buytaert
committed
* Generates the voting form for a poll.
Dries Buytaert
committed
*
* @ingroup forms
* @see poll_vote()
* @see phptemplate_preprocess_poll_vote()
Dries Buytaert
committed
function poll_view_voting(&$form_state, $node, $block) {
$list = array();
foreach ($node->choice as $i => $choice) {
$list[$i] = check_plain($choice['chtext']);
$form['choice'] = array(
'#type' => 'radios',
'#default_value' => -1,
'#options' => $list,
);
Dries Buytaert
committed
Dries Buytaert
committed
$form['vote'] = array(
Dries Buytaert
committed
'#type' => 'submit',
Dries Buytaert
committed
'#value' => t('Vote'),
'#submit' => array('poll_vote'),
);
// Store the node so we can get to it in submit functions.
$form['#node'] = $node;
$form['#block'] = $block;
// Set form caching because we could have multiple of these forms on
// the same page, and we want to ensure the right one gets picked.
$form['#cache'] = TRUE;
// Provide a more cleanly named voting form theme.
$form['#theme'] = 'poll_vote';
Dries Buytaert
committed
return $form;
/**
* Validation function for processing votes
*/
function poll_view_voting_validate($form, &$form_state) {
if ($form_state['values']['choice'] == -1) {
form_set_error( 'choice', t('Your vote could not be recorded because you did not select any of the choices.'));
}
}
Dries Buytaert
committed
/**
* Submit handler for processing a vote
*/
function poll_vote($form, &$form_state) {
$node = $form['#node'];
$choice = $form_state['values']['choice'];
global $user;
if ($user->uid) {
db_query('INSERT INTO {poll_votes} (nid, chorder, uid) VALUES (%d, %d, %d)', $node->nid, $choice, $user->uid);
}
else {
db_query("INSERT INTO {poll_votes} (nid, chorder, hostname) VALUES (%d, %d, '%s')", $node->nid, $choice, ip_address());
}
// Add one to the votes.
db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
cache_clear_all();
drupal_set_message(t('Your vote was recorded.'));
// Return the user to whatever page they voted from.
}
/**
* Themes the voting form for a poll.
Dries Buytaert
committed
*
* Inputs: $form
Dries Buytaert
committed
function template_preprocess_poll_vote(&$variables) {
$form = $variables['form'];
$variables['choice'] = drupal_render($form['choice']);
$variables['title'] = check_plain($form['#node']->title);
$variables['vote'] = drupal_render($form['vote']);
$variables['rest'] = drupal_render($form);
$variables['block'] = $form['#block'];
// If this is a block, allow a different tpl.php to be used.
if ($variables['block']) {
$variables['template_files'][] = 'poll-vote-block';
}
Dries Buytaert
committed
/**
* Generates a graphical representation of the results of a poll.
*/
function poll_view_results(&$node, $teaser, $page, $block) {
Steven Wittens
committed
$total_votes = 0;
$max_votes = 0;
if (isset($choice['chvotes'])) {
$total_votes += $choice['chvotes'];
$max_votes = max($max_votes, $choice['chvotes']);
}
Steven Wittens
committed
$poll_results = '';
if (!empty($choice['chtext'])) {
Gábor Hojtsy
committed
$chvotes = isset($choice['chvotes']) ? $choice['chvotes'] : NULL;
$poll_results .= theme('poll_bar', $choice['chtext'], $chvotes, $total_votes, isset($node->vote) && $node->vote == $i, $block);
Dries Buytaert
committed
}
Dries Buytaert
committed
return theme('poll_results', $node->title, $poll_results, $total_votes, isset($node->links) ? $node->links : array(), $block, $node->nid, isset($node->vote) ? $node->vote : NULL);
/**
* Theme the admin poll form for choices.
Gábor Hojtsy
committed
*
* @ingroup themeable
*/
function theme_poll_choices($form) {
Gábor Hojtsy
committed
// Change the button title to reflect the behavior when using JavaScript.
drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $("#edit-poll-more").val("'. t('Add another choice') .'"); }); }', 'inline');
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
$rows = array();
$headers = array(
t('Choice'),
t('Vote count'),
);
foreach (element_children($form) as $key) {
// No need to print the field title every time.
unset($form[$key]['chtext']['#title'], $form[$key]['chvotes']['#title']);
// Build the table row.
$row = array(
'data' => array(
array('data' => drupal_render($form[$key]['chtext']), 'class' => 'poll-chtext'),
array('data' => drupal_render($form[$key]['chvotes']), 'class' => 'poll-chvotes'),
),
);
// Add additional attributes to the row, such as a class for this row.
if (isset($form[$key]['#attributes'])) {
$row = array_merge($row, $form[$key]['#attributes']);
}
$rows[] = $row;
}
$output = theme('table', $headers, $rows);
$output .= drupal_render($form);
return $output;
}
Dries Buytaert
committed
* Preprocess the poll_results theme hook.
*
* Inputs: $raw_title, $results, $votes, $raw_links, $block, $nid, $vote. The
* $raw_* inputs to this are naturally unsafe; often safe versions are
* made to simply overwrite the raw version, but in this case it seems likely
* that the title and the links may be overridden by the theme layer, so they
* are left in with a different name for that purpose.
*
* @see poll-results.tpl.php
* @see poll-results-block.tpl.php
* @see theme_poll_results()
Dries Buytaert
committed
function template_preprocess_poll_results(&$variables) {
$variables['links'] = theme('links', $variables['raw_links']);
if (isset($variables['vote']) && $variables['vote'] > -1 && user_access('cancel own vote')) {
$variables['cancel_form'] = drupal_get_form('poll_cancel_form', $variables['nid']);
Dries Buytaert
committed
$variables['title'] = check_plain($variables['raw_title']);
// If this is a block, allow a different tpl.php to be used.
if ($variables['block']) {
$variables['template_files'][] = 'poll-results-block';
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Preprocess the poll_bar theme hook.
*
* Inputs: $title, $votes, $total_votes, $voted, $block
*
* @see poll-bar.tpl.php
* @see poll-bar-block.tpl.php
* @see theme_poll_bar()
Dries Buytaert
committed
*/
Dries Buytaert
committed
function template_preprocess_poll_bar(&$variables) {
if ($variables['block']) {
$variables['template_files'][] = 'poll-bar-block';
Dries Buytaert
committed
}
Dries Buytaert
committed
$variables['title'] = check_plain($variables['title']);
$variables['percentage'] = round($variables['votes'] * 100 / max($variables['total_votes'], 1));
Dries Buytaert
committed
}
Dries Buytaert
committed
* Builds the cancel form for a poll.
*
* @ingroup forms
* @see poll_cancel()
Dries Buytaert
committed
function poll_cancel_form(&$form_state, $nid) {
// Store the nid so we can get to it in submit functions.
$form['#nid'] = $nid;
Dries Buytaert
committed
$form['submit'] = array(
Dries Buytaert
committed
'#type' => 'submit',
Dries Buytaert
committed
'#value' => t('Cancel your vote'),
'#submit' => array('poll_cancel')
);
Dries Buytaert
committed
$form['#cache'] = TRUE;
Dries Buytaert
committed
Dries Buytaert
committed
return $form;
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Submit callback for poll_cancel_form
Dries Buytaert
committed
*/
Dries Buytaert
committed
function poll_cancel($form, &$form_state) {
$node = node_load($form['#nid']);
Dries Buytaert
committed
global $user;
Dries Buytaert
committed
if ($user->uid) {
db_query('DELETE FROM {poll_votes} WHERE nid = %d and uid = %d', $node->nid, $user->uid);
Dries Buytaert
committed
db_query("DELETE FROM {poll_votes} WHERE nid = %d and hostname = '%s'", $node->nid, ip_address());
Dries Buytaert
committed
// Subtract from the votes.
db_query("UPDATE {poll_choices} SET chvotes = chvotes - 1 WHERE nid = %d AND chorder = %d", $node->nid, $node->vote);
Gerhard Killesreiter
committed
/**
* Implementation of hook_user().
*/
function poll_user($op, &$edit, &$user) {
if ($op == 'delete') {
db_query('UPDATE {poll_votes} SET uid = 0 WHERE uid = %d', $user->uid);
}
}