Skip to content
Snippets Groups Projects
poll.module 13 KiB
Newer Older
Steven Wittens's avatar
Steven Wittens committed
function poll_help($section = 'admin/help#poll') {
  $output = '';
Steven Wittens's avatar
Steven Wittens committed
  switch ($section) {
Steven Wittens's avatar
Steven Wittens committed
    case 'admin/help#poll':
      $output .= t("
      <p>Users with the correct <a href=\"%permissions\">permissions</a> can create and/or vote on polls.</p>
      <ul>
      <li>To create a poll a user needs the \"create polls\" permission.</li>
      <li>To vote on a poll question a user must have the \"vote on polls\" permission.</li>
      <li>To view the results one needs the \"access content\" permission.</li>
      <li>To administer polls you need the \"administer nodes\" permission.</li>
      </ul>
      <p>Creating a poll is much like creating any other node. Click \"create poll\" in your user box. The title of the poll should be the question, then enter the answers and the \"base\" vote counts. You can also choose the time period over which the vote will run.</p><p>The <a href=\"%poll\">Poll</a> item in the navigation links will take you to a page where you can see all the current polls, vote on them (if you haven't already) and view the results.</p>", array("%permissions" => url("admin/user/permission"), "%poll" => url("poll")));
      break;
    case 'admin/system/modules#description':
      $output = t("Enables your site to capture votes on different topics in the form of multiple choice questions.");
      break;
    case 'node/add#poll':
      $output = t("A poll is a multiple-choice question which visitors can vote on.");
      break;
Steven Wittens's avatar
Steven Wittens committed

  return $output;
function poll_access($op, $node) {
Steven Wittens's avatar
Steven Wittens committed
  if ($op == 'view') {
    return $node->status;
Steven Wittens's avatar
Steven Wittens committed
  if ($op == 'create') {
    return user_access('create polls');
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Steven Wittens's avatar
Steven Wittens committed
function poll_block($op = 'list', $delta = 0) {
  if (user_access('access content')) {
    if ($op == 'list') {
      $blocks[0]['info'] = t('Most recent poll');
Dries Buytaert's avatar
 
Dries Buytaert committed
      return $blocks;
    }
    else {
Steven Wittens's avatar
Steven Wittens committed
      // Retrieve latest poll
Dries Buytaert's avatar
 
Dries Buytaert committed
      $timestamp = db_result(db_query("SELECT MAX(created) FROM {node} WHERE type = 'poll' AND status = '1' AND moderate = '0'"));
Dries Buytaert's avatar
 
Dries Buytaert committed
      if ($timestamp) {
Steven Wittens's avatar
Steven Wittens committed
        $poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'moderate' => 0, 'status' => 1));

Dries Buytaert's avatar
 
Dries Buytaert committed
        if ($poll->nid) {
          // Poll_view dumps the output into $poll->body
Dries Buytaert's avatar
 
Dries Buytaert committed
        }
Dries Buytaert's avatar
 
Dries Buytaert committed
      }
Steven Wittens's avatar
Steven Wittens committed
      $block['subject'] = t('Poll');
      $block['content'] = $poll->body;
Dries Buytaert's avatar
 
Dries Buytaert committed
      return $block;
function poll_cron() {
  // Close polls that have exceeded their allowed runtime
Dries Buytaert's avatar
 
Dries Buytaert committed
  $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'");
Dries Buytaert's avatar
 
Dries Buytaert committed
  while ($poll = db_fetch_object($result)) {
Dries Buytaert's avatar
 
Dries Buytaert committed
    db_query("UPDATE {poll} SET active='0' WHERE nid = %d", $poll->nid);
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
function poll_delete($node) {
Dries Buytaert's avatar
 
Dries Buytaert committed
  db_query("DELETE FROM {poll} WHERE nid=%d", $node->nid);
  db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
  if (isset($node->title)) {
    // Check for at least two options and validate amount of votes:
Steven Wittens's avatar
Steven Wittens committed
    $realchoices = 0;
    foreach ($node->choice as $i => $choice) {
      if ($choice['chtext'] != '') {
        $realchoices++;
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
      if ($choice['chvotes'] < 0) {
        $error["choice][$i][chvotes"] = theme('error', t("Negative values are not allowed."));
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
    if ($realchoices < 2) {
      $error["choice][0][chtext"] = theme('error', t("You must fill in at least two choices."));
Steven Wittens's avatar
Steven Wittens committed
function poll_form(&$node, &$error) {
  $admin = user_access('administer nodes');
Steven Wittens's avatar
Steven Wittens committed
  if (function_exists('taxonomy_node_form')) {
    $output = implode('', taxonomy_node_form('poll', $node));
  }
Steven Wittens's avatar
Steven Wittens committed
  if (!isset($node->choices)) {
    $node->choices = max(2, count($node->choice) ? count($node->choice) : 5);
  }
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  // User ticked 'need more choices'
  if ($node->morechoices) {
    $node->choices *= 2;
Steven Wittens's avatar
Steven Wittens committed
  $output .= '<div class="poll-form">';
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  // Poll choices
  $opts = drupal_map_assoc(range(2, $node->choices * 2 + 5)); 
  for ($a = 0; $a < $node->choices; $a++) {
Steven Wittens's avatar
Steven Wittens committed
    $group1 .= form_textfield(t('Choice %n', array('%n' => ($a + 1))), "choice][$a][chtext", $node->choice[$a]['chtext'], 50, 127, $error["choice][$a][chtext"]);
    if ($admin) {
Steven Wittens's avatar
Steven Wittens committed
      $group1 .= form_textfield(t('Votes for choice %n', array('%n' => ($a + 1))), "choice][$a][chvotes", (int)$node->choice[$a]['chvotes'], 7, 7, $error["choice][$a][chvotes"]);
Steven Wittens's avatar
Steven Wittens committed
  $group1 .= form_hidden('choices', $node->choices);
  $group1 .= form_checkbox(t('Need more choices'), 'morechoices', 1, 0, t("If the amount of boxes above isn't enough, check this box and click the Preview button below to add some more."));
  $output .= form_group(t('Choices'), $group1);
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  
  // Poll attributes
  $_duration = array_merge(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'));
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  if ($admin) {
    $group2 .= form_radios(t('Poll status'), 'active', isset($node->active) ? $node->active : 1, $_active, t('When a poll is closed, visitors can no longer vote for it.'));
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Steven Wittens's avatar
Steven Wittens committed
  $group2 .= form_select(t('Poll duration'), 'runtime', $node->runtime ? $node->runtime : 0, $_duration, t('After this period, the poll will be closed automatically.'));
  
  $output .= form_group(t('Settings'), $group2); 
  $output .= '</div>';
Dries Buytaert's avatar
 
Dries Buytaert committed

  return $output;
function poll_insert($node) {
Steven Wittens's avatar
Steven Wittens committed
  if (!user_access('administer nodes')) {
    // Make sure all votes are 0 initially
Steven Wittens's avatar
Steven Wittens committed
    foreach ($node->choice as $i => $choice) {
      $node->choice[$i]['chvotes'] = 0;
    }
    $node->active = 1;
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
  db_query("INSERT INTO {poll} (nid, runtime, voters, active) VALUES (%d, %d, '', %d)", $node->nid, $node->runtime, $node->active);
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  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++);
function poll_link($type, $node = 0, $main) {
Dries Buytaert's avatar
 
Dries Buytaert committed
  $links = array();

Steven Wittens's avatar
Steven Wittens committed
  if ($type == 'system') {
Dries Buytaert's avatar
 
Dries Buytaert committed
    if (user_access("create polls")) {
Steven Wittens's avatar
Steven Wittens committed
      menu('node/add/poll', t('poll'), 'node_page', 0);
Dries Buytaert's avatar
 
Dries Buytaert committed
    }
Steven Wittens's avatar
Steven Wittens committed
    if (user_access('access content')) {
      menu('poll', t('polls'), 'poll_page', 0, MENU_HIDE);
Dries Buytaert's avatar
 
Dries Buytaert committed
    }
Steven Wittens's avatar
Steven Wittens committed
  else if ($type == 'page' && user_access('access content')) {
    $links[] = l(t('polls'), 'poll', array('title' => t('View the list of polls on this site.')));
Steven Wittens's avatar
Steven Wittens committed
  }
Steven Wittens's avatar
Steven Wittens committed
  else if ($type == 'node' && $node->type == 'poll') {
    /*
    ** Add links to allow the user to switch between the results and the voting
    ** form, if he/she hasn't voted yet.
    */

Steven Wittens's avatar
Steven Wittens committed
    if ($node->allowvotes) {
      if (arg(3) == 'results') {
        $links[] = l(t('voting form'), 'node/view/'. $node->nid);
      }
      else {
Steven Wittens's avatar
Steven Wittens committed
        $links[] = l(t('view results'), 'node/view/'. $node->nid .'/results');
Dries Buytaert's avatar
 
Dries Buytaert committed

  return $links;
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
/**
 * Determine an adjusted user id, to allow for basic tracking of anonymous
 * users (IP-based).
 */
function poll_uid() {
  global $user;
  if ($user->uid) {
     // Pad the UID with underscores to allow a simple strstr() search
    $id = '_'. $user->uid .'_';
  }
  else {
    $id = $_SERVER['REMOTE_ADDR'];
  }
  return $id;
}

function poll_load($node) {
  // Load the appropriate choices into the $node object
Dries Buytaert's avatar
 
Dries Buytaert committed
  $poll = db_fetch_object(db_query("SELECT runtime, voters, active FROM {poll} WHERE nid = %d", $node->nid));
Dries Buytaert's avatar
 
Dries Buytaert committed

Dries Buytaert's avatar
 
Dries Buytaert committed
  $result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid=%d ORDER BY chorder", $node->nid);
Steven Wittens's avatar
Steven Wittens committed
  while ($choice = db_fetch_array($result)) {
    $poll->choice[$choice['chorder']] = $choice;
Steven Wittens's avatar
Steven Wittens committed
  // Determine whether or not this user is allowed to vote
  $poll->allowvotes = false;
  if (user_access('vote on polls')) {
    if (!strstr($poll->voters, poll_uid())) {
      $poll->allowvotes = $poll->active;
    }
  }
Dries Buytaert's avatar
 
Dries Buytaert committed

Dries Buytaert's avatar
 
Dries Buytaert committed
function poll_node_name($node) {
  return t("poll");
Steven Wittens's avatar
Steven Wittens committed
function poll_page() {
Steven Wittens's avatar
Steven Wittens committed
  // List all polls
  $result = pager_query("SELECT n.nid, n.title, p.active, SUM(c.chvotes) AS votes FROM {node} n INNER JOIN {poll} p ON n.nid=p.nid INNER JOIN {poll_choices} c ON n.nid=c.nid WHERE type = 'poll' AND status = '1' AND moderate = '0' GROUP BY n.nid, n.title, p.active, n.created ORDER BY n.created DESC", 15);
  $output = '<ul>';
Steven Wittens's avatar
Steven Wittens committed
  while ($node = db_fetch_object($result)) {
Steven Wittens's avatar
Steven Wittens committed
    $output .= '<li>'. l($node->title, "node/view/$node->nid") .' - '. format_plural($node->votes, '1 vote', '%count votes') .' - '. ($node->active ? t('open') : t('closed')) .'</li>';
Steven Wittens's avatar
Steven Wittens committed
  }
Steven Wittens's avatar
Steven Wittens committed
  $output .= '</ul>';
  $output .= theme("pager", NULL, 15);
  print theme('page', $output);
Steven Wittens's avatar
Steven Wittens committed
}

function poll_perm() {
Steven Wittens's avatar
Steven Wittens committed
  return array('create polls', 'vote on polls');
Dries Buytaert's avatar
 
Dries Buytaert committed

function poll_teaser($node) {
  // Create a simple teaser that lists all the choices
Dries Buytaert's avatar
Dries Buytaert committed
  if (is_array($node->choice)) {
Steven Wittens's avatar
Steven Wittens committed
    foreach ($node->choice as $k => $choice) {
      $teaser .= '* '. $choice['chtext'] .'\n';
Steven Wittens's avatar
Steven Wittens committed
/**
 * Display the vote form
 */
function poll_view_voting(&$node, $main, $page, $block) {
  $url = request_uri();
Steven Wittens's avatar
Steven Wittens committed
  $output .= '<div class="poll">';
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  $form .= '<div class="vote-form">';
  $form .= '<div class="choices">';
Dries Buytaert's avatar
 
Dries Buytaert committed
  if ($node->choice) {
Steven Wittens's avatar
Steven Wittens committed
    $list = array();
    foreach ($node->choice as $i => $choice) {
      $list[$i] = drupal_specialchars($choice['chtext']);
Steven Wittens's avatar
Steven Wittens committed
    $form .= form_radios($page ? '' : $node->title, 'choice', -1, $list);
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Steven Wittens's avatar
Steven Wittens committed
  $form .= '</div>';
  $form .= form_hidden('nid', $node->nid);
  $form .= form_submit(t('Vote'), 'vote') .'</div>';

  $output .= form($form, 'post', url('node/view/'. $node->nid));
  $output .= '</div>';

  return $output;
}

Steven Wittens's avatar
Steven Wittens committed
function poll_view_results(&$node, $main, $page, $block) {
  // Display the results
Dries Buytaert's avatar
 
Dries Buytaert committed

  // Count the votes and find the maximum
Steven Wittens's avatar
Steven Wittens committed
  foreach ($node->choice as $choice) {
    $votestotal += $choice['chvotes'];
    $votesmax = max($votesmax, $choice['chvotes']);
Dries Buytaert's avatar
 
Dries Buytaert committed
  // Output the divs for the text, bars and percentages
Steven Wittens's avatar
Steven Wittens committed
  $output .= '<div class="poll">';
  if ($block) {
    $output .= '<div class="title">'. $node->title .'</div>';
  }
  foreach ($node->choice as $i => $choice) {
    if ($choice['chtext'] != '') {
      $percentage = round($choice['chvotes'] * 100 / max($votestotal, 1));
      $output .= '<div class="text">'. drupal_specialchars($choice['chtext']) .'</div>';
      $output .= '<div class="bar">';
      $output .= '<div style="width: '. $percentage .'%;" class="foreground"></div>';
      $output .= '</div>';
      $output .= '<div class="percent">'. $percentage .'%'. (!$block ? ' ('. format_plural($choice['chvotes'], '1 vote', '%count votes') .')' : '') .'</div>';
Steven Wittens's avatar
Steven Wittens committed
  $output .= '<div class="total">'. t('Total votes') .": $votestotal</div>";
Dries Buytaert's avatar
 
Dries Buytaert committed

Steven Wittens's avatar
Steven Wittens committed
  $output .= '</div>';

  return $output;
}

function poll_view_processvote(&$node) {
Steven Wittens's avatar
Steven Wittens committed
  $edit = $_POST['edit'];
  $choice = $edit['choice'];
  $vote = $_POST['vote'];

  if ($vote == t('Vote')) {
    if (isset($choice) && isset($node->choice[$choice])) {
      if ($node->allowvotes) {
        $id = poll_uid();
        $node->voters = $node->voters ? ($node->voters .' '. $id) : $id;
        db_query("UPDATE {poll} SET voters='%s' WHERE nid = %d", $node->voters, $node->nid);
        db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
        $node->allowvotes = false;
        $node->choice[$choice]['chvotes']++;
        drupal_set_message(t('Your vote was recorded.'));
      }
      else {
        drupal_set_message(t("You're not allowed to vote on this poll."), 'error');
      }
    }
    else {
      drupal_set_message(t("You didn't specify a valid poll choice."), 'error');
Steven Wittens's avatar
Steven Wittens committed
    }
function poll_view(&$node, $main = 0, $page = 0, $block = 0) {
Dries Buytaert's avatar
 
Dries Buytaert committed
  global $user;
Steven Wittens's avatar
Steven Wittens committed
  if (!$block) {
    // Because the voting form is embedded in the node-display, we process the data here
    poll_view_processvote($node);
  }
Steven Wittens's avatar
Steven Wittens committed
  if ($node->allowvotes && (arg(2) != $node->nid || arg(3) != 'results')) {
    $output .= poll_view_voting($node, $main, $page, $block);
  }
  else {
    $output .= poll_view_results($node, $main, $page, $block);
  }
Steven Wittens's avatar
Steven Wittens committed
  // Special display for side-block
  if ($block) {
Steven Wittens's avatar
Steven Wittens committed
    // No 'read more' link
    $node->body = $node->teaser = '';
Steven Wittens's avatar
Steven Wittens committed
    $links = link_node($node, $main);
Steven Wittens's avatar
Steven Wittens committed
    $links[] = l(t('older polls'), 'poll', array('title' => t('View the list of polls on this site.')));
Steven Wittens's avatar
Steven Wittens committed
    $output .= '<div class="links">'. theme("links", $links) .'</div>';
  }

  $node->body = $node->teaser = $output;
  // We also use poll_view() for the side-block
  if (!$block) {
Steven Wittens's avatar
Steven Wittens committed
    return theme('node', $node, $main, $page);
function poll_update($node) {
Steven Wittens's avatar
Steven Wittens committed
  db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
Steven Wittens's avatar
Steven Wittens committed
  db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
  foreach ($node->choice as $choice) {
    $chvotes = (int)$choice['chvotes'];
    $chtext = $choice['chtext'];
Steven Wittens's avatar
Steven Wittens committed
    if ($chtext != '') {
      db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $i++);