source: sipes/cord/modules/poll/poll.module @ 8a8efa8

stableversion-3.0
Last change on this file since 8a8efa8 was d7a822e, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio del cord

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