poll.module 14.5 KB
Newer Older
1
<?php
2
// $Id$
3

Dries's avatar
   
Dries committed
4
5
6
7
8
9
/**
 * @file
 * Enables your site to capture votes on different topics in the form of multiple
 * choice questions.
 */

10
11
12
13
/**
 * Implementation of hook_help().
 */
function poll_help($section) {
Steven Wittens's avatar
Steven Wittens committed
14
15
  switch ($section) {
    case 'admin/help#poll':
16
      return t("
Steven Wittens's avatar
Steven Wittens committed
17
18
19
20
21
22
23
      <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>
24
      <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/configure/permission"), "%poll" => url("poll")));
Dries's avatar
   
Dries committed
25
    case 'admin/modules#description':
26
      return t("Enables your site to capture votes on different topics in the form of multiple choice questions.");
Steven Wittens's avatar
Steven Wittens committed
27
    case 'node/add#poll':
28
      return t("A poll is a multiple-choice question which visitors can vote on.");
Steven Wittens's avatar
Steven Wittens committed
29
  }
30
31
}

32
33
34
/**
 * Implementation of hook_access().
 */
35
function poll_access($op, $node) {
Steven Wittens's avatar
Steven Wittens committed
36
37
  if ($op == 'create') {
    return user_access('create polls');
Dries's avatar
   
Dries committed
38
  }
Steven Wittens's avatar
Steven Wittens committed
39
40
}

41
42
43
44
45
/**
 * Implementation of hook_block().
 *
 * Generates a block containing the latest poll.
 */
Steven Wittens's avatar
Steven Wittens committed
46
47
48
49
function poll_block($op = 'list', $delta = 0) {
  if (user_access('access content')) {
    if ($op == 'list') {
      $blocks[0]['info'] = t('Most recent poll');
Dries's avatar
   
Dries committed
50
51
      return $blocks;
    }
52
    else if ($op == 'view') {
53
      // Retrieve the latest poll.
Dries's avatar
   
Dries committed
54
      $timestamp = db_result(db_query('SELECT MAX(n.created) FROM {node} n '. node_access_join_sql() ." WHERE n.type = 'poll' AND n.status = 1 AND ". node_access_where_sql() .' AND n.moderate = 0'));
Dries's avatar
   
Dries committed
55
      if ($timestamp) {
Steven Wittens's avatar
Steven Wittens committed
56
57
        $poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'moderate' => 0, 'status' => 1));

Dries's avatar
   
Dries committed
58
        if ($poll->nid) {
59
          // poll_view() dumps the output into $poll->body.
60
          poll_view($poll, 1, 0, 1);
Dries's avatar
   
Dries committed
61
        }
Dries's avatar
   
Dries committed
62
      }
Steven Wittens's avatar
Steven Wittens committed
63
64
      $block['subject'] = t('Poll');
      $block['content'] = $poll->body;
Dries's avatar
   
Dries committed
65
      return $block;
66
67
68
69
    }
  }
}

70
71
72
73
74
/**
 * Implementation of hook_cron().
 *
 * Closes polls that have exceeded their allowed runtime.
 */
75
function poll_cron() {
Dries's avatar
   
Dries committed
76
  $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's avatar
   
Dries committed
77
  while ($poll = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
78
    db_query("UPDATE {poll} SET active='0' WHERE nid = %d", $poll->nid);
Dries's avatar
   
Dries committed
79
  }
80
81
}

82
83
84
/**
 * Implementation of hook_delete().
 */
85
function poll_delete($node) {
Dries's avatar
   
Dries committed
86
87
  db_query("DELETE FROM {poll} WHERE nid=%d", $node->nid);
  db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
88
89
}

90
91
92
/**
 * Implementation of hook_validate().
 */
93
function poll_validate(&$node) {
94
95
  if (isset($node->title)) {
    // Check for at least two options and validate amount of votes:
Steven Wittens's avatar
Steven Wittens committed
96
97
98
99
    $realchoices = 0;
    foreach ($node->choice as $i => $choice) {
      if ($choice['chtext'] != '') {
        $realchoices++;
100
      }
Dries's avatar
   
Dries committed
101

Steven Wittens's avatar
Steven Wittens committed
102
      if ($choice['chvotes'] < 0) {
Dries's avatar
   
Dries committed
103
        form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
104
      }
105
    }
Dries's avatar
   
Dries committed
106

Steven Wittens's avatar
Steven Wittens committed
107
    if ($realchoices < 2) {
Dries's avatar
   
Dries committed
108
      form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
109
110
    }
  }
111
112
113
114

  $node->teaser = poll_teaser($node);
}

115
116
117
/**
 * Implementation of hook_form().
 */
Dries's avatar
   
Dries committed
118
function poll_form(&$node) {
Steven Wittens's avatar
Steven Wittens committed
119
  $admin = user_access('administer nodes');
120

Steven Wittens's avatar
Steven Wittens committed
121
122
123
  if (function_exists('taxonomy_node_form')) {
    $output = implode('', taxonomy_node_form('poll', $node));
  }
124

Steven Wittens's avatar
Steven Wittens committed
125
126
127
  if (!isset($node->choices)) {
    $node->choices = max(2, count($node->choice) ? count($node->choice) : 5);
  }
Dries's avatar
   
Dries committed
128

129
  // User ticked 'need more choices'.
Steven Wittens's avatar
Steven Wittens committed
130
131
  if ($node->morechoices) {
    $node->choices *= 2;
132
133
  }

Steven Wittens's avatar
Steven Wittens committed
134
  $output .= '<div class="poll-form">';
Dries's avatar
   
Dries committed
135

Steven Wittens's avatar
Steven Wittens committed
136
  // Poll choices
Dries's avatar
   
Dries committed
137
  $opts = drupal_map_assoc(range(2, $node->choices * 2 + 5));
138
  for ($a = 0; $a < $node->choices; $a++) {
Dries's avatar
   
Dries committed
139
    $group1 .= form_textfield(t('Choice %n', array('%n' => ($a + 1))), "choice][$a][chtext", $node->choice[$a]['chtext'], 50, 127);
140
    if ($admin) {
Dries's avatar
   
Dries committed
141
      $group1 .= form_textfield(t('Votes for choice %n', array('%n' => ($a + 1))), "choice][$a][chvotes", (int)$node->choice[$a]['chvotes'], 7, 7);
142
143
    }
  }
Steven Wittens's avatar
Steven Wittens committed
144
145
146
  $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's avatar
   
Dries committed
147

Dries's avatar
   
Dries committed
148

Steven Wittens's avatar
Steven Wittens committed
149
  // Poll attributes
150
  $_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval");
Steven Wittens's avatar
Steven Wittens committed
151
  $_active = array(0 => t('Closed'), 1 => t('Active'));
Dries's avatar
   
Dries committed
152

Steven Wittens's avatar
Steven Wittens committed
153
154
  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's avatar
   
Dries committed
155
  }
Steven Wittens's avatar
Steven Wittens committed
156
  $group2 .= form_select(t('Poll duration'), 'runtime', $node->runtime ? $node->runtime : 0, $_duration, t('After this period, the poll will be closed automatically.'));
Dries's avatar
   
Dries committed
157
158

  $output .= form_group(t('Settings'), $group2);
Steven Wittens's avatar
Steven Wittens committed
159
  $output .= '</div>';
Dries's avatar
   
Dries committed
160
161

  return $output;
162
}
163

164
function poll_insert($node) {
Steven Wittens's avatar
Steven Wittens committed
165
  if (!user_access('administer nodes')) {
166
    // Make sure all votes are 0 initially
Steven Wittens's avatar
Steven Wittens committed
167
168
169
    foreach ($node->choice as $i => $choice) {
      $node->choice[$i]['chvotes'] = 0;
    }
170
171
    $node->active = 1;
  }
172

Dries's avatar
   
Dries committed
173
  db_query("INSERT INTO {poll} (nid, runtime, voters, active) VALUES (%d, %d, '', %d)", $node->nid, $node->runtime, $node->active);
Dries's avatar
   
Dries committed
174

Steven Wittens's avatar
Steven Wittens committed
175
176
177
  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++);
178
179
    }
  }
180
181
}

Dries's avatar
   
Dries committed
182
183
184
/**
 * Implementation of hook_link().
 */
Steven Wittens's avatar
Steven Wittens committed
185
function poll_link($type, $node = 0, $main) {
Dries's avatar
   
Dries committed
186
187
  $links = array();

Dries's avatar
   
Dries committed
188
  if ($type == 'page' && user_access('access content')) {
Steven Wittens's avatar
Steven Wittens committed
189
    $links[] = l(t('polls'), 'poll', array('title' => t('View the list of polls on this site.')));
Steven Wittens's avatar
Steven Wittens committed
190
  }
Dries's avatar
   
Dries committed
191
192

  return $links;
193
}
Dries's avatar
   
Dries committed
194

Dries's avatar
   
Dries committed
195
196
197
/**
 * Implementation of hook_menu().
 */
Dries's avatar
   
Dries committed
198
function poll_menu($may_cache) {
Dries's avatar
   
Dries committed
199
  $items = array();
Dries's avatar
   
Dries committed
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

  if ($may_cache) {
    $items[] = array('path' => 'node/add/poll', 'title' => t('poll'),
      'access' => user_access('create polls'));
    $items[] = array('path' => 'poll', 'title' => t('polls'),
      'callback' => 'poll_page',
      'access' => user_access('access content'),
      'type' => MENU_SUGGESTED_ITEM);

    $items[] = array('path' => 'poll/vote',
      'title' => t('vote'),
      'callback' => 'poll_vote',
      'access' => user_access('vote on polls'),
      'type' => MENU_CALLBACK);
  }
  else {
    if (arg(0) == 'node' && is_numeric(arg(1))) {
      $node = node_load(array('nid' => arg(1)));

      if ($node->type == 'poll' && $node->allowvotes) {
        $items[] = array('path' => 'node/'. arg(1) .'/results',
          'title' => t('results'),
          'callback' => 'poll_results',
          'access' => user_access('access content'),
          'weight' => 3,
          'type' => MENU_LOCAL_TASK);
      }
Steven Wittens's avatar
Steven Wittens committed
227
228
    }
  }
Dries's avatar
   
Dries committed
229

Dries's avatar
   
Dries committed
230
231
232
  return $items;
}

Steven Wittens's avatar
Steven Wittens committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/**
 * 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;
}

249
250
251
/**
 * Implementation of hook_load().
 */
252
253
function poll_load($node) {
  // Load the appropriate choices into the $node object
Dries's avatar
   
Dries committed
254
  $poll = db_fetch_object(db_query("SELECT runtime, voters, active FROM {poll} WHERE nid = %d", $node->nid));
Dries's avatar
   
Dries committed
255

Dries's avatar
   
Dries committed
256
  $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
257
258
  while ($choice = db_fetch_array($result)) {
    $poll->choice[$choice['chorder']] = $choice;
259
  }
Steven Wittens's avatar
Steven Wittens committed
260

Steven Wittens's avatar
Steven Wittens committed
261
262
263
264
265
266
267
  // 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;
    }
  }
268
269
  return $poll;
}
Dries's avatar
   
Dries committed
270

271
272
273
/**
 * Implementation of hook_node_name().
 */
Dries's avatar
   
Dries committed
274
275
function poll_node_name($node) {
  return t("poll");
276
}
277

Steven Wittens's avatar
Steven Wittens committed
278
function poll_page() {
Steven Wittens's avatar
Steven Wittens committed
279
  // List all polls
Dries's avatar
   
Dries committed
280
  $result = pager_query("SELECT DISTINCT(n.nid), n.title, p.active, n.created, SUM(c.chvotes) AS votes FROM {node} n ". node_access_join_sql() ." 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 ". node_access_where_sql() ." AND moderate = 0 GROUP BY n.nid, n.title, p.active, n.created ORDER BY n.created DESC", 15);
Steven Wittens's avatar
Steven Wittens committed
281
  $output = '<ul>';
Steven Wittens's avatar
Steven Wittens committed
282
  while ($node = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
283
    $output .= '<li>'. l($node->title, "node/$node->nid") .' - '. format_plural($node->votes, '1 vote', '%count votes') .' - '. ($node->active ? t('open') : t('closed')) .'</li>';
Steven Wittens's avatar
Steven Wittens committed
284
  }
Steven Wittens's avatar
Steven Wittens committed
285
286
287
  $output .= '</ul>';
  $output .= theme("pager", NULL, 15);
  print theme('page', $output);
Steven Wittens's avatar
Steven Wittens committed
288
289
}

290
291
292
/**
 * Implementation of hook_perm().
 */
293
function poll_perm() {
Steven Wittens's avatar
Steven Wittens committed
294
  return array('create polls', 'vote on polls');
295
}
Dries's avatar
   
Dries committed
296

297
298
299
/**
 * Creates a simple teaser that lists all the choices.
 */
300
function poll_teaser($node) {
Dries's avatar
Dries committed
301
  if (is_array($node->choice)) {
Steven Wittens's avatar
Steven Wittens committed
302
303
    foreach ($node->choice as $k => $choice) {
      $teaser .= '* '. $choice['chtext'] .'\n';
304
305
306
307
    }
  }
  return $teaser;
}
308

Steven Wittens's avatar
Steven Wittens committed
309
/**
310
 * Generates the voting form for a poll.
Steven Wittens's avatar
Steven Wittens committed
311
312
 */
function poll_view_voting(&$node, $main, $page, $block) {
Dries's avatar
   
Dries committed
313
  $output = '<div class="poll">';
Dries's avatar
   
Dries committed
314

Dries's avatar
   
Dries committed
315
  $form = '<div class="vote-form">';
Steven Wittens's avatar
Steven Wittens committed
316
  $form .= '<div class="choices">';
Dries's avatar
   
Dries committed
317
  if ($node->choice) {
Steven Wittens's avatar
Steven Wittens committed
318
319
320
    $list = array();
    foreach ($node->choice as $i => $choice) {
      $list[$i] = drupal_specialchars($choice['chtext']);
321
    }
Steven Wittens's avatar
Steven Wittens committed
322
    $form .= form_radios($page ? '' : $node->title, 'choice', -1, $list);
Dries's avatar
   
Dries committed
323
  }
Steven Wittens's avatar
Steven Wittens committed
324
325
326
327
  $form .= '</div>';
  $form .= form_hidden('nid', $node->nid);
  $form .= form_submit(t('Vote'), 'vote') .'</div>';

Steven Wittens's avatar
Steven Wittens committed
328
  $output .= form($form, 'post', url('poll/vote/'. $node->nid));
Steven Wittens's avatar
Steven Wittens committed
329
  $output .= '</div>';
Steven Wittens's avatar
Steven Wittens committed
330
331
332
333

  return $output;
}

334
335
336
/**
 * Generates a graphical representation of the results of a poll.
 */
Steven Wittens's avatar
Steven Wittens committed
337
function poll_view_results(&$node, $main, $page, $block) {
Steven Wittens's avatar
Steven Wittens committed
338
  // Display the results
Dries's avatar
   
Dries committed
339

Steven Wittens's avatar
Steven Wittens committed
340
  // Count the votes and find the maximum
Steven Wittens's avatar
Steven Wittens committed
341
342
343
  foreach ($node->choice as $choice) {
    $votestotal += $choice['chvotes'];
    $votesmax = max($votesmax, $choice['chvotes']);
Steven Wittens's avatar
Steven Wittens committed
344
345
  }

Dries's avatar
   
Dries committed
346
  // Output the divs for the text, bars and percentages
Steven Wittens's avatar
Steven Wittens committed
347
348
349
350
351
352
353
354
355
356
357
358
  $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>';
359
    }
360
  }
Steven Wittens's avatar
Steven Wittens committed
361
  $output .= '<div class="total">'. t('Total votes') .": $votestotal</div>";
Dries's avatar
   
Dries committed
362

Steven Wittens's avatar
Steven Wittens committed
363
  $output .= '</div>';
Steven Wittens's avatar
Steven Wittens committed
364
365
366
367

  return $output;
}

Steven Wittens's avatar
Steven Wittens committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/**
 * Callback for the 'results' tab for polls you can vote on
 */
function poll_results() {
  if ($node = node_load(array('nid' => arg(1)))) {
    print theme('page', node_show($node, 0), $node->title);
  }
  else {
    drupal_not_found();
  }
}

/**
 * Callback for processing a vote
 */
function poll_vote(&$node) {
  $nid = arg(2);
  if ($node = node_load(array('nid' => $nid))) {
    $edit = $_POST['edit'];
    $choice = $edit['choice'];
    $vote = $_POST['vote'];
Steven Wittens's avatar
Steven Wittens committed
389
390
391
392
393
394
395
396
397

    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']++;
Dries's avatar
   
Dries committed
398
        drupal_set_message(t('Your vote was recorded.'));
Steven Wittens's avatar
Steven Wittens committed
399
400
      }
      else {
Dries's avatar
   
Dries committed
401
        drupal_set_message(t("You're not allowed to vote on this poll."), 'error');
Steven Wittens's avatar
Steven Wittens committed
402
403
404
      }
    }
    else {
Dries's avatar
   
Dries committed
405
      drupal_set_message(t("You didn't specify a valid poll choice."), 'error');
Steven Wittens's avatar
Steven Wittens committed
406
    }
Steven Wittens's avatar
Steven Wittens committed
407
408
409
410
411

    drupal_goto('node/'. $nid);
  }
  else {
    drupal_not_found();
Steven Wittens's avatar
Steven Wittens committed
412
413
414
  }
}

415
416
417
418
419
420
421
/**
 * Implementation of hook_view().
 *
 * @param $block
 *   An extra parameter that adapts the hook to display a block-ready
 *   rendering of the poll.
 */
Dries's avatar
   
Dries committed
422
function poll_view(&$node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
Dries's avatar
   
Dries committed
423
  global $user;
Dries's avatar
   
Dries committed
424
  $output = '';
Steven Wittens's avatar
Steven Wittens committed
425

Steven Wittens's avatar
Steven Wittens committed
426
  if ($node->allowvotes && ($block || arg(2) != 'results')) {
Steven Wittens's avatar
Steven Wittens committed
427
428
429
430
431
    $output .= poll_view_voting($node, $main, $page, $block);
  }
  else {
    $output .= poll_view_results($node, $main, $page, $block);
  }
Steven Wittens's avatar
Steven Wittens committed
432

Steven Wittens's avatar
Steven Wittens committed
433
  // Special display for side-block
Steven Wittens's avatar
Steven Wittens committed
434
  if ($block) {
Steven Wittens's avatar
Steven Wittens committed
435
436
    // No 'read more' link
    $node->body = $node->teaser = '';
Steven Wittens's avatar
Steven Wittens committed
437

Steven Wittens's avatar
Steven Wittens committed
438
    $links = link_node($node, $main);
Steven Wittens's avatar
Steven Wittens committed
439
    $links[] = l(t('older polls'), 'poll', array('title' => t('View the list of polls on this site.')));
Steven Wittens's avatar
Steven Wittens committed
440
441
442
    if ($node->allowvotes && $block) {
      $links[] = l(t('results'), 'node/'. $node->nid .'/results', array('title' => t('View the current poll results.')));
    }
Steven Wittens's avatar
Steven Wittens committed
443

Steven Wittens's avatar
Steven Wittens committed
444
    $output .= '<div class="links">'. theme("links", $links) .'</div>';
Steven Wittens's avatar
Steven Wittens committed
445
446
447
  }

  $node->body = $node->teaser = $output;
448
449
}

450
451
452
/**
 * Implementation of hook_update().
 */
453
function poll_update($node) {
Steven Wittens's avatar
Steven Wittens committed
454
  db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
455

Steven Wittens's avatar
Steven Wittens committed
456
457
458
459
  db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
  foreach ($node->choice as $choice) {
    $chvotes = (int)$choice['chvotes'];
    $chtext = $choice['chtext'];
460

Steven Wittens's avatar
Steven Wittens committed
461
462
    if ($chtext != '') {
      db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $i++);
463
    }
464
465
  }
}
466

467
?>