[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/modules/poll/ -> poll.module (source)

   1  <?php
   2  // $Id: poll.module,v 1.263.2.5 2010/05/11 12:40:43 goba Exp $
   3  
   4  /**
   5   * @file
   6   * Enables your site to capture votes on different topics in the form of multiple
   7   * choice questions.
   8   */
   9  
  10  /**
  11   * Implementation of hook_help().
  12   */
  13  function poll_help($path, $arg) {
  14    switch ($path) {
  15      case 'admin/help#poll':
  16        $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>';
  17        $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>';
  18        $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>';
  19        return $output;
  20    }
  21  }
  22  
  23  /**
  24   * Implementation of hook_init().
  25   */
  26  function poll_init() {
  27    drupal_add_css(drupal_get_path('module', 'poll') .'/poll.css');
  28  }
  29  
  30  /**
  31   * Implementation of hook_theme()
  32   */
  33  function poll_theme() {
  34    return array(
  35      'poll_vote' => array(
  36        'template' => 'poll-vote',
  37        'arguments' => array('form' => NULL),
  38      ),
  39      'poll_choices' => array(
  40        'arguments' => array('form' => NULL),
  41      ),
  42      'poll_results' => array(
  43        'template' => 'poll-results',
  44        'arguments' => array('raw_title' => NULL, 'results' => NULL, 'votes' => NULL, 'raw_links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL),
  45      ),
  46      'poll_bar' => array(
  47        'template' => 'poll-bar',
  48        'arguments' => array('title' => NULL, 'votes' => NULL, 'total_votes' => NULL, 'vote' => NULL, 'block' => NULL),
  49      ),
  50    );
  51  }
  52  
  53  /**
  54   * Implementation of hook_perm().
  55   */
  56  function poll_perm() {
  57    return array('create poll content', 'delete own poll content', 'delete any poll content', 'edit any poll content', 'edit own poll content', 'vote on polls', 'cancel own vote', 'inspect all votes');
  58  }
  59  
  60  /**
  61   * Implementation of hook_access().
  62   */
  63  function poll_access($op, $node, $account) {
  64    switch ($op) {
  65      case 'create':
  66        return user_access('create poll content', $account) ? TRUE : NULL;
  67      case 'update':
  68        return user_access('edit any poll content', $account) || (user_access('edit own poll content', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
  69      case 'delete':
  70        return user_access('delete any poll content', $account) || (user_access('delete own poll content', $account) && ($node->uid == $account->uid)) ? TRUE : NULL;
  71    }
  72  }
  73  
  74  /**
  75   * Implementation of hook_menu().
  76   */
  77  function poll_menu() {
  78    $items['poll'] = array(
  79      'title' => 'Polls',
  80      'page callback' => 'poll_page',
  81      'access arguments' => array('access content'),
  82      'type' => MENU_SUGGESTED_ITEM,
  83      'file' => 'poll.pages.inc',
  84    );
  85  
  86    $items['node/%node/votes'] = array(
  87      'title' => 'Votes',
  88      'page callback' => 'poll_votes',
  89      'page arguments' => array(1),
  90      'access callback' => '_poll_menu_access',
  91      'access arguments' => array(1, 'inspect all votes', FALSE),
  92      'weight' => 3,
  93      'type' => MENU_LOCAL_TASK,
  94      'file' => 'poll.pages.inc',
  95    );
  96  
  97    $items['node/%node/results'] = array(
  98      'title' => 'Results',
  99      'page callback' => 'poll_results',
 100      'page arguments' => array(1),
 101      'access callback' => '_poll_menu_access',
 102      'access arguments' => array(1, 'access content', TRUE),
 103      'weight' => 3,
 104      'type' => MENU_LOCAL_TASK,
 105      'file' => 'poll.pages.inc',
 106    );
 107  
 108    $items['poll/js'] = array(
 109      'title' => 'Javascript Choice Form',
 110      'page callback' => 'poll_choice_js',
 111      'access arguments' => array('access content'),
 112      'type' => MENU_CALLBACK,
 113    );
 114  
 115    return $items;
 116  }
 117  
 118  /**
 119   * Callback function to see if a node is acceptable for poll menu items.
 120   */
 121  function _poll_menu_access($node, $perm, $inspect_allowvotes) {
 122    return user_access($perm) && ($node->type == 'poll') && ($node->allowvotes || !$inspect_allowvotes);
 123  }
 124  
 125  /**
 126   * Implementation of hook_block().
 127   *
 128   * Generates a block containing the latest poll.
 129   */
 130  function poll_block($op = 'list', $delta = 0) {
 131    if (user_access('access content')) {
 132      if ($op == 'list') {
 133        $blocks[0]['info'] = t('Most recent poll');
 134        return $blocks;
 135      }
 136      else if ($op == 'view') {
 137        // Retrieve the latest poll.
 138        $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");
 139        $timestamp = db_result(db_query($sql));
 140        if ($timestamp) {
 141          $poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'status' => 1));
 142  
 143          if ($poll->nid) {
 144            $poll = poll_view($poll, TRUE, FALSE, TRUE);
 145          }
 146        }
 147        $block['subject'] = t('Poll');
 148        $block['content'] = drupal_render($poll->content);
 149        return $block;
 150      }
 151    }
 152  }
 153  
 154  /**
 155   * Implementation of hook_cron().
 156   *
 157   * Closes polls that have exceeded their allowed runtime.
 158   */
 159  function poll_cron() {
 160    $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');
 161    while ($poll = db_fetch_object($result)) {
 162      db_query("UPDATE {poll} SET active = 0 WHERE nid = %d", $poll->nid);
 163    }
 164  }
 165  
 166  /**
 167   * Implementation of hook_node_info().
 168   */
 169  function poll_node_info() {
 170    return array(
 171      'poll' => array(
 172        'name' => t('Poll'),
 173        'module' => 'poll',
 174        '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.'),
 175        'title_label' => t('Question'),
 176        'has_body' => FALSE,
 177      )
 178    );
 179  }
 180  
 181  /**
 182   * Implementation of hook_form().
 183   */
 184  function poll_form(&$node, $form_state) {
 185    global $user;
 186  
 187    $admin = user_access('administer nodes') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid);
 188  
 189    $type = node_get_types('type', $node);
 190  
 191    $form = array(
 192      '#cache' => TRUE,
 193    );
 194  
 195    $form['title'] = array(
 196      '#type' => 'textfield',
 197      '#title' => check_plain($type->title_label),
 198      '#required' => TRUE,
 199      '#default_value' => $node->title,
 200      '#weight' => -5,
 201    );
 202  
 203    if (isset($form_state['choice_count'])) {
 204      $choice_count = $form_state['choice_count'];
 205    }
 206    else {
 207      $choice_count = max(2, empty($node->choice) ? 2 : count($node->choice));
 208    }
 209  
 210    // Add a wrapper for the choices and more button.
 211    $form['choice_wrapper'] = array(
 212      '#tree' => FALSE,
 213      '#weight' => -4,
 214      '#prefix' => '<div class="clear-block" id="poll-choice-wrapper">',
 215      '#suffix' => '</div>',
 216    );
 217  
 218    // Container for just the poll choices.
 219    $form['choice_wrapper']['choice'] = array(
 220      '#prefix' => '<div id="poll-choices">',
 221      '#suffix' => '</div>',
 222      '#theme' => 'poll_choices',
 223    );
 224  
 225    // Add the current choices to the form.
 226    for ($delta = 0; $delta < $choice_count; $delta++) {
 227      $text = isset($node->choice[$delta]['chtext']) ? $node->choice[$delta]['chtext'] : '';
 228      $votes = isset($node->choice[$delta]['chvotes']) ? $node->choice[$delta]['chvotes'] : 0;
 229  
 230      $form['choice_wrapper']['choice'][$delta] = _poll_choice_form($delta, $text, $votes);
 231    }
 232  
 233    // We name our button 'poll_more' to avoid conflicts with other modules using
 234    // AHAH-enabled buttons with the id 'more'.
 235    $form['choice_wrapper']['poll_more'] = array(
 236      '#type' => 'submit',
 237      '#value' => t('More choices'),
 238      '#description' => t("If the amount of boxes above isn't enough, click here to add more choices."),
 239      '#weight' => 1,
 240      '#submit' => array('poll_more_choices_submit'), // If no javascript action.
 241      '#ahah' => array(
 242        'path' => 'poll/js',
 243        'wrapper' => 'poll-choices',
 244        'method' => 'replace',
 245        'effect' => 'fade',
 246      ),
 247    );
 248  
 249    // Poll attributes
 250    $_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval");
 251    $_active = array(0 => t('Closed'), 1 => t('Active'));
 252  
 253    if ($admin) {
 254      $form['settings'] = array(
 255        '#type' => 'fieldset',
 256        '#collapsible' => TRUE,
 257        '#title' => t('Poll settings'),
 258        '#weight' => -3,
 259      );
 260  
 261      $form['settings']['active'] = array(
 262        '#type' => 'radios',
 263        '#title' => t('Poll status'),
 264        '#default_value' => isset($node->active) ? $node->active : 1,
 265        '#options' => $_active,
 266        '#description' => t('When a poll is closed, visitors can no longer vote for it.')
 267      );
 268    }
 269    $form['settings']['runtime'] = array(
 270      '#type' => 'select',
 271      '#title' => t('Poll duration'),
 272      '#default_value' => isset($node->runtime) ? $node->runtime : 0,
 273      '#options' => $_duration,
 274      '#description' => t('After this period, the poll will be closed automatically.'),
 275    );
 276  
 277    return $form;
 278  }
 279  
 280  /**
 281   * Submit handler to add more choices to a poll form. This handler is used when
 282   * javascript is not available. It makes changes to the form state and the
 283   * entire form is rebuilt during the page reload.
 284   */
 285  function poll_more_choices_submit($form, &$form_state) {
 286    // Set the form to rebuild and run submit handlers.
 287    node_form_submit_build_node($form, $form_state);
 288  
 289    // Make the changes we want to the form state.
 290    if ($form_state['values']['poll_more']) {
 291      $n = $_GET['q'] == 'poll/js' ? 1 : 5;
 292      $form_state['choice_count'] = count($form_state['values']['choice']) + $n;
 293    }
 294  }
 295  
 296  function _poll_choice_form($delta, $value = '', $votes = 0) {
 297    $form = array(
 298      '#tree' => TRUE,
 299    );
 300  
 301    // We'll manually set the #parents property of these fields so that
 302    // their values appear in the $form_state['values']['choice'] array.
 303    $form['chtext'] = array(
 304      '#type' => 'textfield',
 305      '#title' => t('Choice @n', array('@n' => ($delta + 1))),
 306      '#default_value' => $value,
 307      '#parents' => array('choice', $delta, 'chtext'),
 308    );
 309    $form['chvotes'] = array(
 310      '#type' => 'textfield',
 311      '#title' => t('Votes for choice @n', array('@n' => ($delta + 1))),
 312      '#default_value' => $votes,
 313      '#size' => 5,
 314      '#maxlength' => 7,
 315      '#parents' => array('choice', $delta, 'chvotes'),
 316      '#access' => user_access('administer nodes'),
 317    );
 318  
 319    return $form;
 320  }
 321  
 322  /**
 323   * Menu callback for AHAH additions.
 324   */
 325  function poll_choice_js() {
 326    include_once  'modules/node/node.pages.inc';
 327    $form_state = array('storage' => NULL, 'submitted' => FALSE);
 328    $form_build_id = $_POST['form_build_id'];
 329    // Get the form from the cache.
 330    $form = form_get_cache($form_build_id, $form_state);
 331    $args = $form['#parameters'];
 332    $form_id = array_shift($args);
 333    // We will run some of the submit handlers so we need to disable redirecting.
 334    $form['#redirect'] = FALSE;
 335    // We need to process the form, prepare for that by setting a few internals
 336    // variables.
 337    $form['#post'] = $_POST;
 338    $form['#programmed'] = FALSE;
 339    $form_state['post'] = $_POST;
 340    // Build, validate and if possible, submit the form.
 341    drupal_process_form($form_id, $form, $form_state);
 342    // This call recreates the form relying solely on the form_state that the
 343    // drupal_process_form set up.
 344    $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
 345    // Render the new output.
 346    $choice_form = $form['choice_wrapper']['choice'];
 347    unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers.
 348    $output = theme('status_messages') . drupal_render($choice_form);
 349  
 350    drupal_json(array('status' => TRUE, 'data' => $output));
 351  }
 352  
 353  /**
 354   * Renumbers fields and creates a teaser when a poll node is submitted.
 355   */
 356  function poll_node_form_submit(&$form, &$form_state) {
 357    // Renumber fields
 358    $form_state['values']['choice'] = array_values($form_state['values']['choice']);
 359    $form_state['values']['teaser'] = poll_teaser((object)$form_state['values']);
 360  }
 361  
 362  /**
 363   * Implementation of hook_validate().
 364   */
 365  function poll_validate($node) {
 366    if (isset($node->title)) {
 367      // Check for at least two options and validate amount of votes:
 368      $realchoices = 0;
 369      // Renumber fields
 370      $node->choice = array_values($node->choice);
 371      foreach ($node->choice as $i => $choice) {
 372        if ($choice['chtext'] != '') {
 373          $realchoices++;
 374        }
 375        if (isset($choice['chvotes']) && $choice['chvotes'] < 0) {
 376          form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
 377        }
 378      }
 379  
 380      if ($realchoices < 2) {
 381        form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
 382      }
 383    }
 384  }
 385  
 386  /**
 387   * Implementation of hook_load().
 388   */
 389  function poll_load($node) {
 390    global $user;
 391  
 392    $poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid));
 393  
 394    // Load the appropriate choices into the $poll object.
 395    $result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid = %d ORDER BY chorder", $node->nid);
 396    while ($choice = db_fetch_array($result)) {
 397      $poll->choice[$choice['chorder']] = $choice;
 398    }
 399  
 400    // Determine whether or not this user is allowed to vote.
 401    $poll->allowvotes = FALSE;
 402    if (user_access('vote on polls') && $poll->active) {
 403      if ($user->uid) {
 404        $result = db_fetch_object(db_query('SELECT chorder FROM {poll_votes} WHERE nid = %d AND uid = %d', $node->nid, $user->uid));
 405      }
 406      else {
 407        $result = db_fetch_object(db_query("SELECT chorder FROM {poll_votes} WHERE nid = %d AND hostname = '%s'", $node->nid, ip_address()));
 408      }
 409      if (isset($result->chorder)) {
 410        $poll->vote = $result->chorder;
 411      }
 412      else {
 413        $poll->vote = -1;
 414        $poll->allowvotes = TRUE;
 415      }
 416    }
 417    return $poll;
 418  }
 419  
 420  /**
 421   * Implementation of hook_insert().
 422   */
 423  function poll_insert($node) {
 424    if (!user_access('administer nodes')) {
 425      // Make sure all votes are 0 initially
 426      foreach ($node->choice as $i => $choice) {
 427        $node->choice[$i]['chvotes'] = 0;
 428      }
 429      $node->active = 1;
 430    }
 431  
 432    db_query("INSERT INTO {poll} (nid, runtime, active) VALUES (%d, %d, %d)", $node->nid, $node->runtime, $node->active);
 433  
 434    $i = 0;
 435    foreach ($node->choice as $choice) {
 436      if ($choice['chtext'] != '') {
 437        db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $choice['chtext'], $choice['chvotes'], $i++);
 438      }
 439    }
 440  }
 441  
 442  /**
 443   * Implementation of hook_update().
 444   */
 445  function poll_update($node) {
 446    // Update poll settings.
 447    db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
 448  
 449    // Clean poll choices.
 450    db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
 451  
 452    // Poll choices come in the same order with the same numbers as they are in
 453    // the database, but some might have an empty title, which signifies that
 454    // they should be removed. We remove all votes to the removed options, so
 455    // people who voted on them can vote again.
 456    $new_chorder = 0;
 457    foreach ($node->choice as $old_chorder => $choice) {
 458      $chvotes = isset($choice['chvotes']) ? (int)$choice['chvotes'] : 0;
 459      $chtext = $choice['chtext'];
 460  
 461      if (!empty($chtext)) {
 462        db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $new_chorder);
 463        if ($new_chorder != $old_chorder) {
 464          // We can only remove items in the middle, not add, so
 465          // new_chorder is always <= old_chorder, making this safe.
 466          db_query("UPDATE {poll_votes} SET chorder = %d WHERE nid = %d AND chorder = %d", $new_chorder, $node->nid, $old_chorder);
 467        }
 468        $new_chorder++;
 469      }
 470      else {
 471        db_query("DELETE FROM {poll_votes} WHERE nid = %d AND chorder = %d", $node->nid, $old_chorder);
 472      }
 473    }
 474  }
 475  
 476  /**
 477   * Implementation of hook_delete().
 478   */
 479  function poll_delete($node) {
 480    db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
 481    db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
 482    db_query("DELETE FROM {poll_votes} WHERE nid = %d", $node->nid);
 483  }
 484  
 485  /**
 486   * Implementation of hook_view().
 487   *
 488   * @param $block
 489   *   An extra parameter that adapts the hook to display a block-ready
 490   *   rendering of the poll.
 491   */
 492  function poll_view($node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
 493    global $user;
 494    $output = '';
 495  
 496    // Special display for side-block
 497    if ($block) {
 498      // No 'read more' link
 499      $node->readmore = FALSE;
 500  
 501      $links = module_invoke_all('link', 'node', $node, 1);
 502      $links[] = array('title' => t('Older polls'), 'href' => 'poll', 'attributes' => array('title' => t('View the list of polls on this site.')));
 503      if ($node->allowvotes && $block) {
 504        $links[] = array('title' => t('Results'), 'href' => 'node/'. $node->nid .'/results', 'attributes' => array('title' => t('View the current poll results.')));
 505      }
 506  
 507      $node->links = $links;
 508    }
 509  
 510    if (!empty($node->allowvotes) && ($block || empty($node->show_results))) {
 511      $node->content['body'] = array(
 512        '#value' => drupal_get_form('poll_view_voting', $node, $block),
 513      );
 514    }
 515    else {
 516      $node->content['body'] = array(
 517        '#value' => poll_view_results($node, $teaser, $page, $block),
 518      );
 519    }
 520    return $node;
 521  }
 522  
 523  /**
 524   * Creates a simple teaser that lists all the choices.
 525   *
 526   * This is primarily used for RSS.
 527   */
 528  function poll_teaser($node) {
 529    $teaser = NULL;
 530    if (is_array($node->choice)) {
 531      foreach ($node->choice as $k => $choice) {
 532        if ($choice['chtext'] != '') {
 533          $teaser .= '* '. check_plain($choice['chtext']) ."\n";
 534        }
 535      }
 536    }
 537    return $teaser;
 538  }
 539  
 540  /**
 541   * Generates the voting form for a poll.
 542   *
 543   * @ingroup forms
 544   * @see poll_vote()
 545   * @see phptemplate_preprocess_poll_vote()
 546   */
 547  function poll_view_voting(&$form_state, $node, $block) {
 548    if ($node->choice) {
 549      $list = array();
 550      foreach ($node->choice as $i => $choice) {
 551        $list[$i] = check_plain($choice['chtext']);
 552      }
 553      $form['choice'] = array(
 554        '#type' => 'radios',
 555        '#default_value' => -1,
 556        '#options' => $list,
 557      );
 558    }
 559  
 560    $form['vote'] = array(
 561      '#type' => 'submit',
 562      '#value' => t('Vote'),
 563      '#submit' => array('poll_vote'),
 564    );
 565  
 566    // Store the node so we can get to it in submit functions.
 567    $form['#node'] = $node;
 568    $form['#block'] = $block;
 569  
 570    // Set form caching because we could have multiple of these forms on
 571    // the same page, and we want to ensure the right one gets picked.
 572    $form['#cache'] = TRUE;
 573  
 574    // Provide a more cleanly named voting form theme.
 575    $form['#theme'] = 'poll_vote';
 576    return $form;
 577  }
 578  
 579  /**
 580   * Validation function for processing votes
 581   */
 582  function poll_view_voting_validate($form, &$form_state) {
 583    if ($form_state['values']['choice'] == -1) {
 584      form_set_error( 'choice', t('Your vote could not be recorded because you did not select any of the choices.'));
 585    }
 586  }
 587  
 588  /**
 589   * Submit handler for processing a vote
 590   */
 591  function poll_vote($form, &$form_state) {
 592    $node = $form['#node'];
 593    $choice = $form_state['values']['choice'];
 594  
 595    global $user;
 596    if ($user->uid) {
 597      db_query('INSERT INTO {poll_votes} (nid, chorder, uid) VALUES (%d, %d, %d)', $node->nid, $choice, $user->uid);
 598    }
 599    else {
 600      db_query("INSERT INTO {poll_votes} (nid, chorder, hostname) VALUES (%d, %d, '%s')", $node->nid, $choice, ip_address());
 601    }
 602  
 603    // Add one to the votes.
 604    db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
 605  
 606    cache_clear_all();
 607    drupal_set_message(t('Your vote was recorded.'));
 608  
 609    // Return the user to whatever page they voted from.
 610  }
 611  
 612  /**
 613   * Themes the voting form for a poll.
 614   *
 615   * Inputs: $form
 616   */
 617  function template_preprocess_poll_vote(&$variables) {
 618    $form = $variables['form'];
 619    $variables['choice'] = drupal_render($form['choice']);
 620    $variables['title'] = check_plain($form['#node']->title);
 621    $variables['vote'] = drupal_render($form['vote']);
 622    $variables['rest'] = drupal_render($form);
 623    $variables['block'] = $form['#block'];
 624    // If this is a block, allow a different tpl.php to be used.
 625    if ($variables['block']) {
 626      $variables['template_files'][] = 'poll-vote-block';
 627    }
 628  }
 629  
 630  /**
 631   * Generates a graphical representation of the results of a poll.
 632   */
 633  function poll_view_results(&$node, $teaser, $page, $block) {
 634    // Count the votes and find the maximum
 635    $total_votes = 0;
 636    $max_votes = 0;
 637    foreach ($node->choice as $choice) {
 638      if (isset($choice['chvotes'])) {
 639        $total_votes += $choice['chvotes'];
 640        $max_votes = max($max_votes, $choice['chvotes']);
 641      }
 642    }
 643  
 644    $poll_results = '';
 645    foreach ($node->choice as $i => $choice) {
 646      if (!empty($choice['chtext'])) {
 647        $chvotes = isset($choice['chvotes']) ? $choice['chvotes'] : NULL;
 648        $poll_results .= theme('poll_bar', $choice['chtext'], $chvotes, $total_votes, isset($node->vote) && $node->vote == $i, $block);
 649      }
 650    }
 651  
 652    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);
 653  }
 654  
 655  
 656  /**
 657   * Theme the admin poll form for choices.
 658   *
 659   * @ingroup themeable
 660   */
 661  function theme_poll_choices($form) {
 662    // Change the button title to reflect the behavior when using JavaScript.
 663    drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $("#edit-poll-more").val("'. t('Add another choice') .'"); }); }', 'inline');
 664  
 665    $rows = array();
 666    $headers = array(
 667      t('Choice'),
 668      t('Vote count'),
 669    );
 670  
 671    foreach (element_children($form) as $key) {
 672      // No need to print the field title every time.
 673      unset($form[$key]['chtext']['#title'], $form[$key]['chvotes']['#title']);
 674  
 675      // Build the table row.
 676      $row = array(
 677        'data' => array(
 678          array('data' => drupal_render($form[$key]['chtext']), 'class' => 'poll-chtext'),
 679          array('data' => drupal_render($form[$key]['chvotes']), 'class' => 'poll-chvotes'),
 680        ),
 681      );
 682  
 683      // Add additional attributes to the row, such as a class for this row.
 684      if (isset($form[$key]['#attributes'])) {
 685        $row = array_merge($row, $form[$key]['#attributes']);
 686      }
 687      $rows[] = $row;
 688    }
 689  
 690    $output = theme('table', $headers, $rows);
 691    $output .= drupal_render($form);
 692    return $output;
 693  }
 694  
 695  /**
 696   * Preprocess the poll_results theme hook.
 697   *
 698   * Inputs: $raw_title, $results, $votes, $raw_links, $block, $nid, $vote. The
 699   * $raw_* inputs to this are naturally unsafe; often safe versions are
 700   * made to simply overwrite the raw version, but in this case it seems likely
 701   * that the title and the links may be overridden by the theme layer, so they
 702   * are left in with a different name for that purpose.
 703   *
 704   * @see poll-results.tpl.php
 705   * @see poll-results-block.tpl.php
 706   * @see theme_poll_results()
 707   */
 708  function template_preprocess_poll_results(&$variables) {
 709    $variables['links'] = theme('links', $variables['raw_links']);
 710    if (isset($variables['vote']) && $variables['vote'] > -1 && user_access('cancel own vote')) {
 711      $variables['cancel_form'] = drupal_get_form('poll_cancel_form', $variables['nid']);
 712    }
 713    $variables['title'] = check_plain($variables['raw_title']);
 714  
 715    // If this is a block, allow a different tpl.php to be used.
 716    if ($variables['block']) {
 717      $variables['template_files'][] = 'poll-results-block';
 718    }
 719  }
 720  
 721  /**
 722   * Preprocess the poll_bar theme hook.
 723   *
 724   * Inputs: $title, $votes, $total_votes, $voted, $block
 725   *
 726   * @see poll-bar.tpl.php
 727   * @see poll-bar-block.tpl.php
 728   * @see theme_poll_bar()
 729   */
 730  function template_preprocess_poll_bar(&$variables) {
 731    if ($variables['block']) {
 732      $variables['template_files'][] = 'poll-bar-block';
 733    }
 734    $variables['title'] = check_plain($variables['title']);
 735    $variables['percentage'] = round($variables['votes'] * 100 / max($variables['total_votes'], 1));
 736  }
 737  
 738  /**
 739   * Builds the cancel form for a poll.
 740   *
 741   * @ingroup forms
 742   * @see poll_cancel()
 743   */
 744  function poll_cancel_form(&$form_state, $nid) {
 745    // Store the nid so we can get to it in submit functions.
 746    $form['#nid'] = $nid;
 747  
 748    $form['submit'] = array(
 749      '#type' => 'submit',
 750      '#value' => t('Cancel your vote'),
 751      '#submit' => array('poll_cancel')
 752    );
 753  
 754    $form['#cache'] = TRUE;
 755  
 756    return $form;
 757  }
 758  
 759  /**
 760   * Submit callback for poll_cancel_form
 761   */
 762  function poll_cancel($form, &$form_state) {
 763    $node = node_load($form['#nid']);
 764    global $user;
 765  
 766    if ($user->uid) {
 767      db_query('DELETE FROM {poll_votes} WHERE nid = %d and uid = %d', $node->nid, $user->uid);
 768    }
 769    else {
 770      db_query("DELETE FROM {poll_votes} WHERE nid = %d and hostname = '%s'", $node->nid, ip_address());
 771    }
 772  
 773    // Subtract from the votes.
 774    db_query("UPDATE {poll_choices} SET chvotes = chvotes - 1 WHERE nid = %d AND chorder = %d", $node->nid, $node->vote);
 775  }
 776  
 777  /**
 778   * Implementation of hook_user().
 779   */
 780  function poll_user($op, &$edit, &$user) {
 781    if ($op == 'delete') {
 782      db_query('UPDATE {poll_votes} SET uid = 0 WHERE uid = %d', $user->uid);
 783    }
 784  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7