View source
<?php
define('ADVPOLL_MAX_CHOICES', 0);
define('ADVPOLL_RUNTIME', 0);
define('ADVPOLL_ELECTORAL_LIST', 0);
define('ADVPOLL_SHOW_VOTES', 1);
define('ADVPOLL_WRITEINS', 0);
define('ADVPOLL_SHOW_WRITEINS', 0);
define('ADVPOLL_INITIAL_CHOICES', 5);
define('ADVPOLL_USE_QUESTION', 0);
define('ADVPOLL_CHOICE_MAX_LENGTH', 2048);
define('ADVPOLL_VIEW_RESULTS', 'aftervote');
function advpoll_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('A sophisticated polling module for voting, elections, and group decision-making.');
break;
}
}
function advpoll_perm() {
return array(
'create polls',
'edit polls',
'edit own polls',
'vote on polls',
'cancel own vote',
'administer polls',
'inspect all votes',
'access electoral list',
'add write-ins',
);
}
function advpoll_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('create polls');
}
if ($op == 'update') {
if (user_access('edit polls') || $node->uid == $user->uid && user_access('edit own polls')) {
return TRUE;
}
}
}
function advpoll_node_info() {
$modes = _advpoll_list_modes();
$info = array();
foreach ($modes as $mode) {
$info['advpoll_' . $mode['name']] = array(
'name' => t('@name poll', array(
'@name' => $mode['name_label'],
)),
'module' => 'advpoll',
'description' => $mode['description'],
'title_label' => t('@name question', array(
'@name' => $mode['name_label'],
)),
'body_label' => t('Description'),
);
}
return $info;
}
function advpoll_menu($may_cache) {
global $user;
$modes = _advpoll_list_modes();
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'advpoll/cancel',
'title' => t('Cancel'),
'callback' => 'advpoll_cancel',
'access' => user_access('cancel own vote'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'polls',
'title' => t('Advanced Polls'),
'callback' => 'advpoll_page',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM,
);
}
else {
drupal_add_css(drupal_get_path('module', 'poll') . '/poll.css');
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load($nid);
if (strstr($node->type, 'advpoll_') == 0) {
if (_advpoll_is_active($node) && !$node->voted && _advpoll_can_view_results($node)) {
$items[] = array(
'path' => 'node/' . $nid . '/results',
'title' => t('Results'),
'callback' => 'advpoll_results',
'access' => user_access('access content'),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
}
if ($node->show_votes) {
$items[] = array(
'path' => 'node/' . $nid . '/votes',
'title' => t('Votes'),
'callback' => 'advpoll_votes_page',
'access' => user_access('inspect all votes'),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
}
if ($node->use_list) {
$items[] = array(
'path' => 'node/' . $nid . '/electoral_list',
'title' => t('Electoral list'),
'callback' => 'advpoll_electoral_list_page',
'access' => user_access('access electoral list'),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'node/' . $nid . '/remove',
'callback' => 'advpoll_remove_voter',
'access' => user_access('administer polls'),
'weight' => 3,
'type' => MENU_CALLBACK,
);
}
$items[] = array(
'path' => 'node/' . $nid . '/reset',
'callback' => 'drupal_get_form',
'callback arguments' => 'advpoll_reset_confirm',
'access' => user_access('administer polls'),
'weight' => 3,
'type' => MENU_CALLBACK,
);
if ($node->writeins) {
$has_writeins = FALSE;
foreach ($node->choice as $choice) {
if ($choice['writein']) {
$has_writeins = TRUE;
break;
}
}
if ($has_writeins) {
$items[] = array(
'path' => 'node/' . $nid . '/writeins',
'title' => t('Write-ins'),
'callback' => 'advpoll_writeins_page',
'access' => user_access('administer polls'),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
}
}
}
}
}
return $items;
}
function advpoll_init() {
if (module_exists('views')) {
require_once drupal_get_path('module', 'advpoll') . '/advpoll_views.inc';
}
}
function advpoll_block($op = 'list') {
switch ($op) {
case 'list':
$blocks['latest_poll']['info'] = t('Latest poll');
return $blocks;
case 'view':
$block['subject'] = t('Latest poll');
$block['content'] = theme('advpoll_block_latest_poll');
return $block;
}
}
function theme_advpoll_block_latest_poll() {
$node = advpoll_latest_poll();
$output = '';
if ($node) {
$output .= '<h3>' . check_plain($node->title) . '</h3>';
$output .= drupal_render($node->content);
if ($node->voted) {
$output .= '<p>' . l(t('Older polls'), 'polls', array(
'class' => 'old-polls',
'title' => t('View the list of polls on this site.'),
)) . '</p>';
}
}
return $output;
}
function advpoll_latest_poll() {
$result = db_query('SELECT MAX(n.nid) AS nid FROM {node} n INNER JOIN {advpoll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1');
$poll = db_fetch_object($result);
if ($poll->nid) {
$node = advpoll_view(node_load($poll->nid), FALSE, FALSE);
}
return $node;
}
function advpoll_form($node, $form_values = NULL) {
$mode = _advpoll_get_mode($node->type);
$type = node_get_types('type', $node);
$editing = isset($node->nid);
$form = array();
static $add_js;
if (!$add_js) {
drupal_add_js(array(
'advPoll' => array(
'remove' => t('Remove'),
'addChoice' => t('Add choice'),
'noLimit' => t('No limit'),
),
), 'setting');
drupal_add_js(drupal_get_path('module', 'advpoll') . '/advpoll-form.js', 'module');
drupal_add_css(drupal_get_path('module', 'advpoll') . '/advpoll.css', 'module');
$add_js = TRUE;
}
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
);
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#title' => check_plain($type->body_label),
'#required' => FALSE,
'#default_value' => $node->body,
);
$form['body_filter']['format'] = filter_form($node->format);
if (isset($form_values)) {
$choices = $form_values['choices'];
if ($form_values['more_choices']) {
$choices *= 2;
}
}
else {
$choices = max(2, count($node->choice) ? count($node->choice) : ADVPOLL_INITIAL_CHOICES);
}
if (variable_get('advpoll_use_question_' . $type->type, ADVPOLL_USE_QUESTION) || isset($node->question) && $node->question !== '') {
$form['question'] = array(
'#type' => 'textfield',
'#title' => t('Question'),
'#default_value' => $node->question,
'#maxlength' => 255,
);
}
$form['choices'] = array(
'#type' => 'hidden',
'#value' => $choices,
);
$form['choice'] = array(
'#type' => 'fieldset',
'#title' => t('Poll choices'),
'#collapsible' => TRUE,
'#prefix' => '<div class="poll-form">',
'#suffix' => '</div>',
'#tree' => TRUE,
'#weight' => 1,
);
if ($editing) {
$form['choice']['choice_note'] = array(
'#value' => '<div id="edit-settings-choice-note" class="description">' . t('Note: adding or removing choices after voting has begun is not recommended.') . '</div>',
);
}
$default_choices = variable_get('advpoll_choices_' . $type->type, '');
if (!$editing) {
$form['choice']['choice_area'] = array(
'#type' => 'textarea',
'#title' => t('Choices'),
'#parents' => array(
'choice_area',
),
'#description' => t('Enter one choice per line.'),
'#default_value' => $default_choices,
);
}
else {
$form['choice']['more_choices'] = array(
'#type' => 'checkbox',
'#title' => t('Need more choices'),
'#value' => 0,
'#parents' => array(
'more_choices',
),
'#prefix' => '<div id="more-choices">',
'#suffix' => '</div>',
'#description' => t("If the number of choices above isn't enough, check this box and click the Preview button below to double the number of choices."),
'#weight' => 1,
);
$current_choices = 0;
if (isset($node->choice)) {
foreach ($node->choice as $index => $choice) {
$form['choice'][$index]['label'] = array(
'#type' => 'textfield',
'#title' => t('Choice %n', array(
'%n' => $current_choices + 1,
)) . ($choice['writein'] ? ' ' . t('(write-in)') : ''),
'#default_value' => $choice['label'],
'#attributes' => array(
'class' => 'choices',
),
'#maxlength' => variable_get('advpoll_choice_max_length', ADVPOLL_CHOICE_MAX_LENGTH),
);
$current_choices++;
$next_index = $index + 1;
}
}
elseif ($default_choices != '') {
$default_choices = explode("\n", $default_choices);
foreach ($default_choices as $index => $label) {
$form['choice'][$index]['label'] = array(
'#type' => 'textfield',
'#title' => t('Choice %n', array(
'%n' => $current_choices + 1,
)),
'#default_value' => $label,
'#attributes' => array(
'class' => 'choices',
),
);
$current_choices++;
$next_index = $index + 1;
}
}
else {
$next_index = 1;
}
if ($current_choices < $choices) {
for ($index = $next_index; $current_choices < $choices; $index++, $current_choices++) {
$form['choice'][$index]['label'] = array(
'#type' => 'textfield',
'#title' => t('Choice %n', array(
'%n' => $current_choices + 1,
)),
'#attributes' => array(
'class' => 'choices',
),
'#maxlength' => variable_get('advpoll_choice_max_length', ADVPOLL_CHOICE_MAX_LENGTH),
);
}
}
}
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Poll settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 2,
'#tree' => TRUE,
);
$max_choice_list = array();
for ($i = 0; $i <= $choices; $i++) {
$max_choice_list[$i] = $i == 0 ? t('No limit') : $i;
}
$form['settings']['max_choices'] = array(
'#type' => 'select',
'#title' => t('Maximum choices'),
'#default_value' => isset($node->max_choices) ? $node->max_choices : variable_get('advpoll_max_choices_' . $type->type, ADVPOLL_MAX_CHOICES),
'#options' => $max_choice_list,
'#DANGEROUS_SKIP_CHECK' => TRUE,
'#description' => t('Limits the total number of choices voters may select.'),
);
$voting_algorithms = advpoll_algorithms($mode);
if (count($voting_algorithms) > 1) {
$form['settings']['algorithm'] = array(
'#type' => 'select',
'#title' => t('Algorithm'),
'#options' => $voting_algorithms,
'#default_value' => isset($node->algorithm) ? $node->algorithm : variable_get('advpoll_algorithm_' . $type->type, key($voting_algorithms)),
'#description' => t('Voting algorithm to use to calculate the winner.'),
);
}
else {
$form['settings']['algorithm'] = array(
'#type' => 'value',
'#value' => key($voting_algorithms),
);
}
$form['settings']['close'] = array(
'#type' => 'checkbox',
'#title' => t('Close poll'),
'#description' => t('When a poll is closed users may no longer vote on it.'),
'#default_value' => isset($node->active) ? !$node->active : 0,
);
$default_start_date = '';
$default_end_date = '';
$time = format_date(time(), 'custom', 'Y-m-d H:i:s O');
if (variable_get('advpoll_runtime_' . $type->type, FALSE) && !$editing) {
$default_start_date = $time;
$default_end_date = format_date(time() + variable_get('advpoll_runtime_' . $type->type, ''), 'custom', 'Y-m-d H:i:s O');
}
$form['settings']['start_date'] = array(
'#type' => 'textfield',
'#title' => t('Starting date'),
'#description' => t('The date that the poll opens. Format: %time. Leave blank if you want the poll to open now.', array(
'%time' => $time,
)),
'#size' => 25,
'#maxlength' => 25,
'#default_value' => !empty($node->start_date) ? format_date($node->start_date, 'custom', 'Y-m-d H:i:s O') : $default_start_date,
);
$form['settings']['end_date'] = array(
'#type' => 'textfield',
'#title' => t('Ending date'),
'#description' => t('The date that the poll closes. Format: %time. Leave blank if you do not want the poll to close automatically.', array(
'%time' => $time,
)),
'#size' => 25,
'#maxlength' => 25,
'#default_value' => !empty($node->end_date) ? format_date($node->end_date, 'custom', 'Y-m-d H:i:s O') : $default_end_date,
);
$default_use_list = isset($node->use_list) ? $node->use_list : variable_get('advpoll_electoral_list_' . $type->type, ADVPOLL_ELECTORAL_LIST);
$default_show_votes = isset($node->show_votes) ? $node->show_votes : variable_get('advpoll_show_votes_' . $type->type, ADVPOLL_SHOW_VOTES);
$default_writeins = isset($node->writeins) ? $node->writeins : variable_get('advpoll_writeins_' . $type->type, ADVPOLL_WRITEINS);
$default_show_writeins = isset($node->show_writeins) ? $node->show_writeins : variable_get('advpoll_show_writeins_' . $type->type, ADVPOLL_SHOW_WRITEINS);
if (user_access('administer polls')) {
$form['settings']['admin_note'] = array(
'#value' => '<div id="edit-settings-admin-note" class="description">' . t('The settings below are only available for users with the <em>administer polls</em> permission.') . '</div>',
);
$form['settings']['writeins'] = array(
'#type' => 'checkbox',
'#title' => t('Allow users to cast a write-in vote'),
'#default_value' => $default_writeins,
'#description' => t('Allow voters with the "add write-ins" permission to write-in up to one choice each.'),
'#attributes' => array(
'class' => 'settings-writeins',
),
);
$form['settings']['show_writeins'] = array(
'#type' => 'checkbox',
'#title' => t('Display write-in votes as choices for future voters'),
'#default_value' => $default_show_writeins,
'#description' => t('Allow voters to see and choose from previously submitted write-in votes.'),
'#prefix' => '<div class="edit-settings-show-writeins">',
'#suffix' => '</div>',
);
$form['settings']['use_list'] = array(
'#type' => 'checkbox',
'#title' => t('Restrict voting to electoral list'),
'#description' => t('If enabled, a list of eligible voters will be created and only that group will be able to vote in the poll.'),
'#default_value' => $default_use_list,
);
$form['settings']['show_votes'] = array(
'#type' => 'checkbox',
'#title' => t('Show individual votes'),
'#description' => t('Users with the appropriate permissions will be able to see how each person voted.'),
'#default_value' => $default_show_votes,
);
if ($editing) {
$form['settings']['reset'] = array(
'#type' => 'button',
'#value' => t('Reset votes'),
);
}
}
else {
$defaults = array(
'use_list' => $default_use_list,
'show_votes' => $default_show_votes,
'writeins' => $default_writeins,
'show_writeins' => $default_show_writeins,
);
foreach ($defaults as $name => $value) {
$form['settings'][$name] = array(
'#type' => 'value',
'#value' => $value,
);
}
}
$form['#multistep'] = TRUE;
return $form;
}
function advpoll_form_alter($form_id, &$form) {
if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
$node_type = $form['old_type']['#value'];
if ($form['module']['#value'] == 'advpoll') {
drupal_add_js(drupal_get_path('module', 'advpoll') . '/advpoll-form.js', 'module');
drupal_add_css(drupal_get_path('module', 'advpoll') . '/advpoll.css', 'module');
$form['advpoll'] = array(
'#type' => 'fieldset',
'#title' => t('Poll settings'),
'#collapsible' => TRUE,
);
$form['advpoll']['advpoll_choices'] = array(
'#type' => 'textarea',
'#title' => t('Default choices'),
'#default_value' => variable_get('advpoll_choices_' . $node_type, ''),
'#description' => t('Add one choice per row. This setting can be overridden on the poll edit page.'),
);
$form['advpoll']['advpoll_max_choices'] = array(
'#type' => 'select',
'#title' => t('Default maximum choices'),
'#options' => array(
0 => t('No limit'),
) + drupal_map_assoc(array(
1,
2,
3,
4,
5,
)),
'#default_value' => variable_get('advpoll_max_choices_' . $node_type, ADVPOLL_MAX_CHOICES),
'#description' => t('The default number of maximum choices for new polls. This setting can be overridden on the poll edit page.'),
);
$mode = _advpoll_get_mode($node_type);
$voting_algorithms = advpoll_algorithms($mode);
if (count($voting_algorithms) > 1) {
$form['advpoll']['advpoll_algorithm'] = array(
'#type' => 'select',
'#title' => t('Default algorithm'),
'#options' => $voting_algorithms,
'#default_value' => variable_get('advpoll_algorithm_' . $node_type, key($voting_algorithms)),
'#description' => t('Default voting algorithm for calculating the winner.'),
);
}
$form['advpoll']['advpoll_runtime'] = array(
'#type' => 'select',
'#title' => t('Default duration'),
'#default_value' => variable_get('advpoll_runtime_' . $node_type, ADVPOLL_RUNTIME),
'#options' => array(
0 => t('Unlimited'),
) + drupal_map_assoc(array(
86400,
172800,
345600,
604800,
1209600,
1814400,
2419200,
4838400,
9676800,
31536000,
), 'format_interval'),
'#description' => t('The date the poll was created is used as start date for the default duration. This setting can be overridden on the poll edit page.'),
);
$form['advpoll']['advpoll_writeins'] = array(
'#type' => 'checkbox',
'#title' => t('Allow users to cast a write-in vote by default'),
'#default_value' => variable_get('advpoll_writeins_' . $node_type, ADVPOLL_WRITEINS),
'#description' => t('Allow voters with the "add write-ins" permission to write-in up to one choice each. Users with the <em>administer polls</em> permission will be able to override this setting.'),
'#attributes' => array(
'class' => 'settings-writeins',
),
);
$form['advpoll']['advpoll_show_writeins'] = array(
'#type' => 'checkbox',
'#title' => t('Display write-in votes as choices for future voters by default'),
'#default_value' => variable_get('advpoll_show_writeins_' . $node_type, ADVPOLL_SHOW_WRITEINS),
'#description' => t("Allow voters to see and choose from previous voters' write-in votes. Users with the <em>administer polls</em> permission will be able to override this setting."),
'#prefix' => '<div class="edit-settings-show-writeins">',
'#suffix' => '</div>',
);
$form['advpoll']['advpoll_electoral_list'] = array(
'#type' => 'checkbox',
'#title' => t('Use electoral list by default'),
'#description' => t('Use an electoral list by default for new polls. Users with the <em>administer polls</em> permission will be able to override this setting.'),
'#default_value' => variable_get('advpoll_electoral_list_' . $node_type, ADVPOLL_ELECTORAL_LIST),
);
$form['advpoll']['advpoll_show_votes'] = array(
'#type' => 'checkbox',
'#title' => t('Show individual votes by default'),
'#description' => t('Let users with appropriate permissions see how each person voted by default for new polls. Users with the <em>administer polls</em> permission will be able to override this setting.'),
'#default_value' => variable_get('advpoll_show_votes_' . $node_type, ADVPOLL_SHOW_VOTES),
);
$view_results = array(
'always' => t('Always'),
'aftervote' => t('After user has voted'),
'afterclose' => t('After voting has closed'),
);
$form['advpoll']['advpoll_view_results'] = array(
'#type' => 'radios',
'#title' => t('Display results'),
'#description' => t('Determines when users may view the results of the poll.'),
'#default_value' => variable_get('advpoll_view_results_' . $node_type, ADVPOLL_VIEW_RESULTS),
'#options' => $view_results,
);
$form['advpoll']['advpoll_use_question'] = array(
'#type' => 'checkbox',
'#title' => t('Use question field'),
'#description' => t('Use a dedicated question field instead of a combined question and title field. It is recommended to rename <em>Title field label</em> above to "Title" if this is checked.'),
'#default_value' => variable_get('advpoll_use_question_' . $node_type, ADVPOLL_USE_QUESTION),
);
}
}
}
function advpoll_load($node) {
global $user;
$poll = db_fetch_object(db_query('SELECT * FROM {advpoll} WHERE nid = %d', $node->nid));
$result = db_query('SELECT cid, weight, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY weight', $node->nid);
while ($choice = db_fetch_array($result)) {
$poll->choice[$choice['cid']] = $choice;
}
$poll->choices = count($poll->choice);
$result = db_query("SELECT value FROM {votingapi_cache} WHERE content_type = 'advpoll' AND content_id = %d AND tag = '_advpoll' AND function = 'total_votes'", $node->nid);
if (db_num_rows($result) > 0) {
$cache = db_fetch_object($result);
$poll->votes = $cache->value;
}
else {
$poll->votes = 0;
}
list($poll->voted, $poll->cancel_vote) = _advpoll_user_voted($node->nid);
return $poll;
}
function advpoll_validate($node, &$form) {
global $form_values;
if ($form_values['op'] == t('Reset votes')) {
drupal_goto('node/' . $node->nid . '/reset');
}
else {
if (isset($node->choice_area)) {
$real_choices = count(explode("\n", $node->choice_area));
}
else {
$node->choice = array_values($node->choice);
array_unshift($node->choice, '');
unset($node->choice[0]);
$real_choices = 0;
foreach ($_POST['choice'] as $i => $choice) {
if ($choice['label'] != '') {
$real_choices++;
}
}
}
if ($real_choices < 2) {
form_set_error("choice][{$real_choices}][label", t('You must fill in at least two choices.'));
}
if ($node->settings['max_choices'] < 0) {
form_set_error('settings][max_choices]', t('Maximum choices must be a non-negative integer.'));
}
if ($node->settings['max_choices'] > $real_choices) {
form_set_error('settings][max_choices]', t('Maximum choices cannot be larger than the number of choices submitted.'));
}
if (!empty($node->settings['start_date']) && strtotime($node->settings['start_date']) <= 0) {
form_set_error('settings][start_date', t('You have to specify a valid starting date.'));
}
if (!empty($node->settings['end_date']) && strtotime($node->settings['end_date']) <= 0) {
form_set_error('settings][end_date', t('You have to specify a valid ending date.'));
}
if (!empty($node->settings['end_date']) && $node->settings['end_date'] < $node->settings['start_date']) {
form_set_error('settings][end_date', t('Ending date cannot be before the starting date.'));
}
}
}
function advpoll_insert($node) {
$mode = _advpoll_get_mode($node->type);
db_query("INSERT INTO {advpoll} (nid, mode, use_list, active, max_choices, algorithm, show_votes, start_date, end_date, writeins, show_writeins, question) VALUES (%d, '%s', %d, %d, %d, '%s', %d, '%s', '%s', %d, %d, '%s')", $node->nid, $mode, $node->settings['use_list'], !$node->settings['close'], $node->settings['max_choices'], $node->settings['algorithm'], $node->settings['show_votes'], $node->settings['start_date'] ? strtotime($node->settings['start_date']) : 0, $node->settings['end_date'] ? strtotime($node->settings['end_date']) : 0, $node->settings['writeins'], $node->settings['show_writeins'], $node->question);
$raw_choices = explode("\n", $_POST['choice_area']);
$choices = array();
foreach ($raw_choices as $choice_line) {
$choices[] = array(
'label' => $choice_line,
);
}
_advpoll_insert_choices($node->nid, $choices);
}
function advpoll_update($node) {
db_query("UPDATE {advpoll} SET active = %d, max_choices = %d, algorithm = '%s', use_list = %d, show_votes = %d, start_date = '%s', end_date = '%s', writeins = %d, show_writeins = %d, question = '%s' WHERE nid = %d", !$node->settings['close'], $node->settings['max_choices'], $node->settings['algorithm'], $node->settings['use_list'], $node->settings['show_votes'], $node->settings['start_date'] ? strtotime($node->settings['start_date']) : 0, $node->settings['end_date'] ? strtotime($node->settings['end_date']) : 0, $node->settings['writeins'], $node->settings['show_writeins'], $node->question, $node->nid);
_advpoll_insert_choices($node->nid, $_POST['choice']);
votingapi_recalculate_results('advpoll', $node->nid);
}
function advpoll_view($node, $teaser = FALSE, $page = FALSE) {
drupal_add_css(drupal_get_path('module', 'advpoll') . '/advpoll.css', 'module');
$status = _advpoll_is_active($node, TRUE);
if ($node->question !== '') {
$node->content['question'] = array(
'#weight' => 1,
'#value' => theme('advpoll_question', check_plain($node->question)),
);
}
if ($node->in_preview) {
$poll = drupal_get_form('advpoll_voting_' . _advpoll_get_mode($node->type) . '_form', $node, $teaser, $page, $status);
}
else {
if (!$node->voted && arg(2) != 'results' && ($status == 'open' || $status == 'pending') || $_POST['op'] == 'Vote') {
$poll = drupal_get_form('advpoll_voting_' . $node->mode . '_form', $node, $teaser, $page, $status);
static $add_js = TRUE;
if ($add_js) {
drupal_add_js(drupal_get_path('module', 'advpoll') . '/advpoll-vote.js', 'module');
drupal_add_js(drupal_get_path('module', 'advpoll') . '/jquery.form.js', 'module');
$add_js = FALSE;
}
}
else {
$poll = advpoll_view_results($node, $teaser, $page);
}
}
$node->content['poll'] = array(
'#weight' => 2,
'#value' => $poll,
);
return node_prepare($node, $teaser);
}
function advpoll_delete($node) {
db_query('DELETE FROM {advpoll} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {advpoll_choices} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {advpoll_electoral_list} WHERE nid = %d', $node->nid);
db_query("DELETE FROM {votingapi_vote} WHERE content_id = %d AND content_type = 'advpoll'", $node->nid);
db_query("DELETE FROM {votingapi_cache} WHERE content_id = %d AND content_type = 'advpoll'", $node->nid);
}
function advpoll_page() {
$sql = "SELECT n.nid, n.title, p.active, n.created, c.value AS votes FROM {node} n INNER JOIN {advpoll} p ON n.nid = p.nid INNER JOIN {votingapi_cache} c ON n.nid = c.content_id WHERE n.status = 1 AND c.tag = '_advpoll' AND c.function = 'total_votes' AND c.content_type = 'advpoll' GROUP BY n.nid, n.title, p.active, n.created, c.value ORDER BY n.created DESC";
$sql = db_rewrite_sql($sql);
$result = pager_query($sql, 15);
$output = '<ul>';
while ($node = db_fetch_object($result)) {
$output .= '<li>' . l($node->title, 'node/' . $node->nid) . ' - ' . format_plural($node->votes, '1 vote', '@count votes') . ' - ' . (_advpoll_is_active($node) ? t('open') : t('closed')) . '</li>';
}
$output .= '</ul>';
$output .= theme('pager', NULL, 15);
return $output;
}
function advpoll_votingapi_calculate(&$results, $votes, $content_type, $content_id) {
if ($content_type == 'advpoll') {
$node = node_load($content_id, NULL, TRUE);
$mode = _advpoll_get_mode($node->type);
$function = 'advpoll_calculate_results_' . $mode;
if (function_exists($function)) {
$function($results, $votes, $node);
}
cache_clear_all();
}
}
function _advpoll_user_voted($nid) {
global $user;
$voted = FALSE;
$cancel_vote = FALSE;
if ($user->uid) {
$voted = count(votingapi_get_user_votes('advpoll', $nid)) > 0;
if ($voted) {
$cancel_vote = TRUE;
}
}
else {
$host = $_SERVER['REMOTE_ADDR'] . ($_SERVER['HTTP_X_FORWARDED_FOR'] ? '-' . $_SERVER['HTTP_X_FORWARDED_FOR'] : '');
$result = db_query("SELECT value FROM {votingapi_vote} WHERE content_id = %d AND content_type = 'advpoll' AND hostname = '%s' AND uid = 0", $nid, $host);
if (db_num_rows($result) > 0) {
$voted = TRUE;
$cancel_vote = TRUE;
}
}
return array(
$voted,
$cancel_vote,
);
}
function advpoll_electoral_list_page() {
if ($node = node_load(arg(1))) {
if (!$node->use_list) {
drupal_not_found();
return;
}
drupal_set_title(check_plain($node->title));
if (user_access('administer polls')) {
$output .= drupal_get_form('advpoll_electoral_list_form', $node->nid);
}
$output .= '<p>' . t('This table lists all the eligible voters for this poll.') . '</p>';
$header[] = array(
'data' => t('Voter'),
'field' => 'u.name',
);
$result = pager_query("SELECT u.uid, u.name FROM {advpoll_electoral_list} el LEFT JOIN {users} u ON el.uid = u.uid WHERE el.nid = %d" . tablesort_sql($header), 20, 0, NULL, $node->nid);
$table_rows = array();
while ($voter = db_fetch_object($result)) {
$row = array(
theme('username', $voter),
);
if (user_access('administer polls')) {
$row[] = l(t('remove'), 'node/' . $node->nid . '/remove/' . $voter->uid);
}
$table_rows[] = $row;
}
$output .= theme('table', $header, $table_rows);
$output .= theme('pager', NULL, 20, 0);
print theme('page', $output);
}
else {
drupal_not_found();
}
}
function advpoll_electoral_list_form($nid) {
$form['electoral_list'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Administer electoral list'),
'#collapsible' => TRUE,
'#weight' => 2,
);
$form['electoral_list']['add_user'] = array(
'#type' => 'textfield',
'#title' => t('Add user'),
'#size' => 40,
'#description' => t('Add an individual user to the electoral list.'),
);
if (user_access('access user profiles')) {
$form['electoral_list']['add_user']['#autocomplete_path'] = 'user/autocomplete';
}
$result = db_query("SELECT r.name, r.rid FROM {role} r LEFT JOIN {permission} p ON p.rid = r.rid WHERE p.perm LIKE '%vote on polls%' AND r.rid != 1 ORDER BY r.name");
$role_options = array(
0 => t('(Select a role)'),
);
while ($role = db_fetch_object($result)) {
$role_options[$role->rid] = $role->name;
}
$form['electoral_list']['add_role'] = array(
'#type' => 'select',
'#title' => t('Add users by role'),
'#description' => t('Only roles that have the "vote on polls" permission are listed.'),
'#options' => $role_options,
);
$form['electoral_list']['submit'] = array(
'#type' => 'submit',
'#value' => t('Add to electoral list'),
);
$form['electoral_list']['reset'] = array(
'#type' => 'button',
'#value' => t('Clear electoral list'),
);
$form['nid'] = array(
'#type' => 'hidden',
'#value' => $nid,
);
return $form;
}
function advpoll_remove_voter() {
$nid = arg(1);
$uid = arg(3);
if ($uid && ($node = node_load($nid))) {
$result = db_query('SELECT name FROM {users} WHERE uid = %d', $uid);
if (db_num_rows($result) > 0) {
$user = db_fetch_object($result);
db_query('DELETE FROM {advpoll_electoral_list} WHERE nid = %d AND uid = %d', $nid, $uid);
drupal_set_message(t('%user removed from the electoral list.', array(
'%user' => $user->name,
)));
}
else {
drupal_set_message(t('No user found with a uid of %uid.', array(
'%uid' => $uid,
)));
}
}
drupal_goto('node/' . $node->nid . '/electoral_list');
}
function advpoll_electoral_list_form_validate($form_id, $form_values) {
if ($form_values['op'] == t('Clear electoral list')) {
if (user_access('administer polls')) {
db_query('DELETE FROM {advpoll_electoral_list} WHERE nid = %d', $form_values['nid']);
drupal_set_message(t('Electoral list cleared.'));
return;
}
}
$add_user = $form_values['electoral_list']['add_user'];
if ($add_user) {
$result = db_query("SELECT uid FROM {users} WHERE name = '%s'", $add_user);
if (db_num_rows($result) == 0) {
form_set_error('electoral_list][add_user', t('User %user does not exist.', array(
'%user' => $add_user,
)));
return FALSE;
}
}
}
function advpoll_electoral_list_form_submit($form_id, $form_values) {
$add_user = $form_values['electoral_list']['add_user'];
if ($add_user) {
db_query("REPLACE INTO {advpoll_electoral_list} (nid, uid) SELECT '%d', u.uid FROM {users} u WHERE u.name = '%s'", $form_values['nid'], $add_user);
drupal_set_message(t('%user added to electoral list.', array(
'%user' => $add_user,
)));
}
$add_role = $form_values['electoral_list']['add_role'];
if ($add_role) {
$result = db_query('SELECT uid FROM {advpoll_electoral_list} WHERE nid = %d', $form_values['nid']);
$current_list = array(
0,
);
while ($user = db_fetch_object($result)) {
$current_list[] = $user->uid;
}
$user_in_string = implode(',', $current_list);
$is_authenticated = db_result(db_query("SELECT COUNT(*) FROM {role} r WHERE r.name = 'authenticated user' AND r.rid = %d", $add_role));
if ($is_authenticated) {
$result = db_query("INSERT INTO {advpoll_electoral_list} (nid, uid) SELECT '%d', u.uid FROM {users} u WHERE u.uid NOT IN('%s')", $form_values['nid'], $user_in_string);
}
else {
$result = db_query("INSERT INTO {advpoll_electoral_list} (nid, uid) SELECT '%d', u.uid FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid WHERE ur.rid = %d AND u.uid NOT IN('%s')", $form_values['nid'], $add_role, $user_in_string);
}
drupal_set_message(format_plural(db_affected_rows($result), 'Added 1 user to the electoral list.', 'Added @count users to the electoral list.'));
}
}
function advpoll_votes_page() {
if ($node = node_load(arg(1))) {
if (!$node->show_votes) {
drupal_not_found();
return;
}
drupal_set_title(check_plain($node->title));
$output = t('This table lists all the recorded votes for this poll. If anonymous users are allowed to vote, they will be identified by the IP address of the computer they used when they voted.');
$header[] = array(
'data' => t('Visitor'),
'field' => 'u.name',
);
$header[] = array(
'data' => t('Vote'),
'',
);
$result = pager_query("SELECT v.uid, v.hostname, v.timestamp, u.name FROM {votingapi_vote} v LEFT JOIN {users} u ON v.uid = u.uid WHERE v.content_type = 'advpoll' AND v.content_id = %d GROUP BY v.uid, v.hostname, v.timestamp, u.name" . tablesort_sql($header), 20, 0, NULL, $node->nid);
$uids = array();
$hostnames = array();
$timestamp = array();
while ($vote = db_fetch_object($result)) {
$uids[$vote->uid] = $vote->uid;
$hostnames[$vote->hostname] = $vote->hostname;
$timestamps[$vote->timestamp] = $vote->timestamp;
}
$rows = array();
if (count($uids) > 0) {
$uid_placeholders = array_fill(0, count($uids), '%d');
$host_placeholders = array_fill(0, count($hostnames), "'%s'");
$time_placeholders = array_fill(0, count($timestamps), '%d');
$query = "SELECT v.vote_id, v.tag, v.uid, v.hostname, v.timestamp, v.value, u.name FROM {votingapi_vote} v LEFT JOIN {users} u ON v.uid = u.uid WHERE v.content_id = %d AND v.uid IN(" . implode(', ', $uid_placeholders) . ") AND v.hostname IN(" . implode(', ', $host_placeholders) . ") AND v.timestamp IN(" . implode(', ', $time_placeholders) . ")" . tablesort_sql($header);
$parameters = array_merge(array(
$query,
$node->nid,
), array_values($uids), array_values($hostnames), array_values($timestamps));
$result = call_user_func_array('db_query', $parameters);
while ($vote = db_fetch_object($result)) {
$key = $vote->uid ? $vote->uid : $vote->hostname . '-' . $vote->timestamp;
$rows[$key]['name'] = $vote->name ? theme('username', $vote) : check_plain($vote->hostname);
if ($node->type == 'advpoll_ranking') {
$rows[$key]['votes'][$vote->value][] = _advpoll_choice_markup($node->choice[$vote->tag]['label'], $node->format, FALSE);
}
else {
$rows[$key]['votes'][] = _advpoll_choice_markup($node->choice[$vote->tag]['label'], $node->format, FALSE);
}
}
}
$separators = array(
'advpoll_ranking' => ' > ',
'advpoll_binary' => ', ',
);
$results = array();
foreach ($rows as $key => $container) {
$ranking = $container['votes'];
asort($ranking);
$rankings = array();
if ($node->type == 'advpoll_ranking') {
foreach ($ranking as $vote => $choices) {
$rankings[$vote] = implode(' = ', $choices);
}
}
else {
$rankings = $ranking;
}
ksort($rankings);
$results[$key]['name'] = $rows[$key]['name'];
$results[$key]['vote'] = implode($separators[$node->type], $rankings);
}
$output .= theme('table', $header, $results);
$output .= theme('pager', NULL, 20, 0);
print theme('page', $output);
}
else {
drupal_not_found();
}
}
function _advpoll_can_view_results($node) {
$view_results = variable_get('advpoll_view_results_' . $node->type, ADVPOLL_VIEW_RESULTS);
return !_advpoll_is_active($node) || $node->voted && $view_results == 'aftervote' || $view_results == 'always';
}
function advpoll_cancel_form($nid) {
$form['#action'] = url('advpoll/cancel/' . $nid);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Cancel your vote'),
);
return $form;
}
function _advpoll_is_active($node, $return_status = FALSE) {
$active = TRUE;
$status = 'open';
$start_date = $node->start_date;
$end_date = $node->end_date;
if (!$node->active) {
$active = FALSE;
$status = 'closed';
}
if ($active && $start_date > 0) {
if (!($active = time() >= $start_date)) {
$status = 'pending';
}
}
if ($active && $end_date > 0) {
if (!($active = time() < $end_date)) {
$status = 'passed';
}
}
return $return_status ? $status : $active;
}
function _advpoll_insert_choices($nid, $choices) {
$node = node_load($nid);
$weight = 0;
$seen_ids = array();
foreach ($choices as $index => $choice) {
if ($choice['label'] != '') {
$seen_ids[$index] = 1;
if (!isset($node->choice[$index])) {
db_query("INSERT INTO {advpoll_choices} (nid, label, weight) VALUES (%d, '%s', %d)", $nid, $choice['label'], $weight);
}
else {
db_query("UPDATE {advpoll_choices} SET label = '%s', weight = %d WHERE cid = %d", $choice['label'], $weight, $index);
}
$weight++;
}
}
if (isset($node->choice)) {
foreach ($node->choice as $id => $choice) {
if (!isset($seen_ids[$id])) {
db_query('DELETE FROM {advpoll_choices} WHERE cid = %d', $id);
drupal_set_message(t('Deleted choice %label', array(
'%label' => $choice['label'],
)), 'status');
}
}
}
}
function _advpoll_get_mode($node_type) {
if ($node_type) {
$mode = explode('advpoll_', $node_type, 2);
return $mode[1];
}
else {
drupal_set_message(t('No mode specified for content type %type.', array(
'%type' => $node_type,
)), 'error');
return '';
}
}
function advpoll_reset_confirm() {
global $form_values;
$edit = $form_values['edit'];
$edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
$node = node_load($edit['nid']);
$form['nid'] = array(
'#type' => 'value',
'#value' => $node->nid,
);
$output = confirm_form($form, t('Are you sure you want to reset the votes for %title?', array(
'%title' => $node->title,
)), 'node/' . $node->nid, t('This action cannot be undone.'), t('Reset votes'), t('Cancel'));
return $output;
}
function advpoll_reset_confirm_submit($form_id, $form_values) {
if ($form_values['confirm']) {
$nid = arg(1);
if ($node = node_load($nid)) {
db_query("DELETE FROM {votingapi_vote} WHERE content_type = 'advpoll' AND content_id = %d", $node->nid);
db_query('DELETE FROM {advpoll_choices} WHERE writein = 1 AND nid = %d', $node->nid);
votingapi_recalculate_results('advpoll', $node->nid);
drupal_set_message(t('Votes have been reset.'));
drupal_goto('node/' . $node->nid);
}
}
return '';
}
function _advpoll_block_resultslink($node) {
return array(
'title' => t('Results'),
'href' => 'node/' . $node->nid . '/results',
'attributes' => array(
'title' => t('View the current poll results.'),
),
);
}
function theme_advpoll_question($question) {
return '<p class="poll-question">' . $question . '</p>';
}
function theme_advpoll_results($title, $results, $votes, $links, $nid, $voted, $cancel_vote) {
$output = '<div class="poll">';
if ($results) {
$output .= $results;
$output .= '<div class="total">' . t('Total voters: %votes', array(
'%votes' => $votes,
)) . '</div>';
}
else {
$output .= '<p class="message">' . t('No votes have been recorded for this poll.') . '</p>';
}
$output .= '</div>';
return $output;
}
function _advpoll_show_cancel_form($node) {
$output = '';
if ($node->voted && $node->cancel_vote && user_access('cancel own vote') && _advpoll_is_active($node)) {
$output .= drupal_get_form('advpoll_cancel_form', $node->nid);
}
return $output;
}
function theme_advpoll_bar($title, $percentage, $votes, $choice = NULL) {
$output = '<div class="text">' . $title . ($choice && $choice['writein'] ? ' ' . t('(write-in)') : '') . '</div>';
$output .= '<div class="bar"><div style="width: ' . $percentage . '%;" class="foreground"></div></div>';
$output .= '<div class="percent">' . $percentage . '% <span class="votes">(' . $votes . ')</span></div>';
return $output;
}
function advpoll_results() {
if ($node = node_load(arg(1))) {
drupal_set_title(check_plain($node->title));
return node_show($node, 0);
}
else {
drupal_not_found();
}
}
function _advpoll_vote_response($node, $form_values) {
$msg = t('Your vote was registered.');
if ($form_values['ajax']) {
unset($node->choice);
$result = db_query('SELECT cid, weight, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY weight', $node->nid);
while ($choice = db_fetch_array($result)) {
$node->choice[$choice['cid']] = $choice;
}
$node->choices = count($poll->choice);
$result = db_query("SELECT value FROM {votingapi_cache} WHERE content_type = 'advpoll' AND content_id = %d AND tag = '_advpoll' AND function = 'total_votes'", $node->nid);
if (db_num_rows($result) > 0) {
$cache = db_fetch_object($result);
$node->votes = $cache->value;
}
else {
$node->votes = 0;
}
list($node->voted, $node->cancel_vote) = _advpoll_user_voted($node->nid);
$ajax_output .= advpoll_view_results($node, NULL, NULL);
$ajax_output = str_replace("\n", '', $ajax_output);
drupal_set_header('Content-Type: text/plain; charset=utf-8');
print drupal_to_js(array(
'statusMsgs' => '<div class="messages status">' . $msg . '</div>',
'response' => $ajax_output,
));
exit;
}
else {
drupal_set_message($msg);
}
}
function advpoll_view_results(&$node, $teaser, $page) {
$mode = _advpoll_get_mode($node->type);
if (_advpoll_can_view_results($node)) {
if (function_exists('advpoll_view_results_' . $mode)) {
$results = call_user_func('advpoll_view_results_' . $mode, $node, $teaser, $page);
$output .= theme('advpoll_results', check_plain($node->title), $results['results'], $results['votes'], $node->links, $node->nid, $node->voted, $node->cancel_vote);
}
}
$output .= _advpoll_show_cancel_form($node);
return $output;
}
function advpoll_cancel($nid) {
global $user;
$nid = arg(2);
if ($nid && ($node = node_load(array(
'nid' => $nid,
)))) {
if (isset($node->type) && $node->voted && _advpoll_is_active($node)) {
if ($user->uid && count($user_vote = votingapi_get_user_votes('advpoll', $node->nid)) > 0) {
votingapi_unset_vote('advpoll', $node->nid, $user->uid);
}
else {
$host = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
db_query("DELETE FROM {votingapi_vote} WHERE content_id = %d and hostname = '%s' AND uid = 0", $node->nid, $host);
votingapi_recalculate_results('advpoll', $nid);
}
$mode = _advpoll_get_mode($node->type);
$function = 'advpoll_cancel_' . $mode;
if (function_exists($function)) {
$function($node, $user_vote);
}
drupal_set_message(t('Your vote was canceled.'));
}
else {
drupal_set_message(t('You are not allowed to cancel an invalid choice.'), 'error');
}
drupal_goto('node/' . $nid);
}
else {
drupal_not_found();
}
}
function advpoll_eligible($node, $uid = NULL) {
global $user;
if (!isset($uid)) {
$uid = $user->uid;
}
if ($node->use_list) {
$eligible = db_result(db_query('SELECT COUNT(*) FROM {advpoll_electoral_list} WHERE nid = %d AND uid = %d', $node->nid, $uid));
}
else {
$eligible = user_access('vote on polls');
}
return $eligible;
}
function advpoll_algorithms($mode) {
return call_user_func('advpoll_algorithms_' . $mode);
}
function _advpoll_list_modes() {
static $advpoll_modes;
if (!$advpoll_modes) {
$files = file_scan_directory(dirname(__FILE__) . '/modes/', '^([^\\.].*)\\.inc$', array(
'.',
'..',
'CVS',
), 0, FALSE);
foreach ($files as $file) {
require_once $file->filename;
$mode = $file->name;
if (function_exists('advpoll_info_' . $mode)) {
$advpoll_modes[$mode] = call_user_func('advpoll_info_' . $mode);
}
}
}
return $advpoll_modes;
}
function _advpoll_choice_markup($text, $format = FILTER_FORMAT_DEFAULT, $check = TRUE) {
$text = check_markup($text, $format, $check);
$text = str_replace(array(
'<p>',
'</p>',
), '', $text);
$text = trim($text);
return $text;
}
function _advpoll_form_set_error($name = NULL, $message = '', $ajax = FALSE) {
if ($ajax) {
drupal_set_header('Content-Type: text/plain; charset=utf-8');
print drupal_to_js(array(
'errors' => '<div class="messages error">' . $message . '</div>',
));
exit;
}
else {
return form_set_error('choice[', $message);
}
}
function _advpoll_writeins_voting_form_validate($node, $writein_option, $writein_text, $ajax) {
if ($node->writeins && user_access('add write-ins')) {
if ($writein_text) {
$writein_choice_lower = strtolower($writein_text);
foreach ($node->choice as $i => $value) {
if (strtolower($val['label']) == $writein_choice_lower && ($node->show_writeins || !$value['writein'])) {
_advpoll_form_set_error('writein_choice', t("A write-in vote can not be for an existing choice. Select the choice's option instead."), $ajax);
}
}
}
if ($writein_option && !$writein_text) {
_advpoll_form_set_error('writein_choice', t('If the "write-in" option is selected, a choice must be written in.'), $ajax);
}
if (!$writein_option && $writein_text) {
_advpoll_form_set_error('writein_choice', t('If a choice is written in, the "write-in" option must be selected.'), $ajax);
}
}
}
function _advpoll_writeins_voting_form_submit($node, $form_values, &$votes, $vote_value) {
if ($form_values['writein_choice']) {
$result = db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND LOWER(label) = LOWER('%s')", $node->nid, $form_values['writein_choice']);
if (db_num_rows($result) > 1) {
$result = db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND label = '%s'", $node->nid, $form_values['writein_choice']);
}
if (db_num_rows($result)) {
$obj = db_fetch_object($result);
$existing_choice = $obj->cid;
$vote = new stdClass();
$vote->value = $vote_value;
$vote->tag = $existing_choice;
$vote->value_type = 'option';
$votes[] = $vote;
}
else {
$highest_weight = db_result(db_query("SELECT MAX(weight) FROM {advpoll_choices} WHERE nid = %d", $node->nid));
$next_weight = $highest_weight ? $highest_weight + 1 : 1;
db_query("INSERT INTO {advpoll_choices} (nid, label, weight, writein) VALUES (%d, '%s', %d, 1)", $node->nid, check_plain($form_values['writein_choice']), $next_weight);
$next_cid = db_result(db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND label = '%s'", $node->nid, $form_values['writein_choice']));
$vote = new stdClass();
$vote->value = $vote_value;
$vote->tag = $next_cid;
$vote->value_type = 'option';
$votes[] = $vote;
}
}
}
function advpoll_writeins_page() {
$node = node_load(arg(1));
drupal_set_title(check_plain($node->title));
$output .= drupal_get_form('advpoll_writein_promote_form', $node);
$output .= drupal_get_form('advpoll_writein_merge_form', $node);
echo theme('page', $output);
}
function advpoll_writein_merge_form($node) {
$form = array();
$form['fieldset'] = array(
'#type' => 'fieldset',
'#collapsible' => FALSE,
'#title' => t('Merge write-ins'),
);
$form['fieldset']['note'] = array(
'#value' => '<div class="description">' . t('This will delete the write-in and change any votes for it into votes for the selected chocie.') . '</div>',
);
$form['fieldset']['merge'] = array(
'#prefix' => '<div class="container-inline">' . t('Merge') . ' ',
'#suffix' => '</div>',
);
$writein_list = array();
$choice_list = array();
foreach ($node->choice as $index => $choice) {
$choice_list[$index] = $choice['label'];
if ($choice['writein']) {
$writein_list[$index] = $choice['label'];
}
}
$form['fieldset']['merge']['source'] = array(
'#type' => 'select',
'#options' => $writein_list,
);
$form['fieldset']['merge']['into'] = array(
'#value' => t(' into '),
);
$form['fieldset']['merge']['destination'] = array(
'#type' => 'select',
'#options' => $choice_list,
);
$form['fieldset']['merge']['submit'] = array(
'#type' => 'submit',
'#value' => t('Merge'),
);
$form['nid'] = array(
'#type' => 'value',
'#value' => $node->nid,
);
return $form;
}
function advpoll_writein_merge_form_validate($form_id, $form_values) {
if ($form_values['source'] == $form_values['destination']) {
form_set_error('destination', t('The write-in cannot be merged into itself.'));
}
}
function advpoll_writein_merge_form_submit($form_id, $form_values) {
$raw_votes = db_query('SELECT * FROM {votingapi_vote} WHERE content_id = %d', $form_values['nid']);
$voters = array();
$affected_voters = array();
while ($vote = db_fetch_object($raw_votes)) {
$key = $vote->uid . '-' . $vote->hostname;
if (!isset($voters[$key])) {
$voters[$key] = array();
}
array_push($voters[$key], $vote);
if ($vote->tag == $form_values['source']) {
$affected_voters[$key] = count($voters[$key]) - 1;
}
}
foreach ($affected_voters as $key => $source_index) {
$voted_for_destination = FALSE;
foreach ($voters[$key] as $index => $vote) {
if ($vote->tag == $form_values['destination']) {
$voted_for_destination = TRUE;
break;
}
}
if ($voted_for_destination) {
db_query('DELETE FROM {votingapi_vote} WHERE vote_id = %d AND tag = %d', $voters[$key][$index]->vote_id, $form_values['source']);
}
else {
db_query('UPDATE {votingapi_vote} SET tag = %d WHERE vote_id = %d AND tag = %d', $form_values['destination'], $voters[$key][$index]->vote_id, $form_values['source']);
}
}
db_query('DELETE FROM {advpoll_choices} WHERE cid = %d', $form_values['source']);
votingapi_recalculate_results('advpoll', $form_values['nid']);
drupal_set_message(t('Write-in merged.'));
unset($_REQUEST['destination']);
drupal_goto('node/' . $form_values['nid'] . '/writeins');
}
function advpoll_writein_promote_form($node) {
$form = array();
$form['fieldset'] = array(
'#type' => 'fieldset',
'#collapsible' => FALSE,
'#title' => t('Promote write-ins'),
);
$form['fieldset']['note'] = array(
'#value' => '<p class="description">' . t('Write-ins can be converted to regular choices. This is useful if users cannot see past write-ins but you want to promote specific write-ins so that they can be seen by users who vote in the future.') . '</p>',
);
$writein_list = array();
foreach ($node->choice as $index => $choice) {
if ($choice['writein']) {
$writein_list[$index] = $choice['label'];
}
}
$form['fieldset']['promote'] = array(
'#type' => 'checkboxes',
'#options' => $writein_list,
);
$form['fieldset']['submit'] = array(
'#type' => 'submit',
'#value' => t('Promote'),
);
$form['nid'] = array(
'#type' => 'value',
'#value' => $node->nid,
);
return $form;
}
function advpoll_writein_promote_form_submit($form_id, $form_values) {
if (count($form_values['promote'])) {
db_query('UPDATE {advpoll_choices} SET writein = 0 WHERE nid = %d AND cid IN(%s)', $form_values['nid'], implode(', ', $form_values['promote']));
drupal_set_message(format_plural(count($form_values['promote']), 'Write-in promoted.', 'Write-ins promoted.'));
}
drupal_goto('node/' . $form_values['nid']);
}