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

4
5
6
function poll_access($op, $node) {
  if ($op == "view") {
    return $node->status;
7
8
  }

9
10
  if ($op == "create") {
    return 1;
Dries's avatar
   
Dries committed
11
  }
Steven Wittens's avatar
Steven Wittens committed
12
13
}

14
15
16
17
18
19
20
function poll_block() {
  $timestamp = db_result(db_query("SELECT MAX(created) FROM node WHERE type='poll' AND status='1'"));
  if ($timestamp) {
    $poll = node_load(array("type" => "poll", "created" => $timestamp, "status" => "1"));
    if ($poll->nid) {
      // Poll_view dumps the output into $poll->body
      poll_view($poll, 0, 1);
21
22
    }
  }
23
24
25
26
  $blocks[0][subject] = "Latest poll";
  $blocks[0][content] = $poll->body;
  $blocks[0][info] = "Most recent poll";
  return $blocks;
27
28
}

29
30
31
32
33
34
function poll_cron() {
  // Close polls that have exceeded their allowed runtime
  $result = db_query("SELECT p.lid FROM poll p LEFT JOIN node n ON p.nid=n.nid WHERE (n.created + p.runtime) < '" . time() . "' AND p.active = '1' AND p.runtime != '0'");
  while ($poll = db_fetch_object($result)) {  
    db_query("UPDATE poll SET active='0' WHERE lid='$poll->lid'");
  } 
35
36
}

37
38
39
function poll_delete($node) {
  db_query("DELETE FROM poll WHERE nid='$node->nid'");
  db_query("DELETE FROM poll_choices WHERE nid='$node->nid'");
40
41
}

42
43
function poll_form(&$node, &$help, &$error) {
  $admin = user_access("administer nodes");
44

45
46
  $_duration = array(0 => t("Unlimited"), 86400 => format_interval(86400), 172800 => format_interval(172800), 345600 => format_interval(345600), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200), 4838400 => format_interval(4838400), 9676800 => format_interval(9676800), 31536000 => format_interval(31536000));
  $_active = array(0 => "Closed", 1 => "Active");
Dries's avatar
   
Dries committed
47

48
  $node->choices = $node->choices ? $node->choices : max(2, count($node->choices) ? count($node->choices) : 5);
49

50
51
52
53
54
55
  if (isset($node->title)) {
    // Check for at least two options and validate amount of votes:
    for ($i = 0; $i < $node->choices; $i++) {
      if ($node->choice[$i] != "") {
        $actualchoices++;
      }
Dries's avatar
   
Dries committed
56

57
58
      if ($node->chvotes[$i] < 0) {
        $error["chvotes][$i"] = "<span style=\"color: red;\">" . t("Negative values are not allowed.") . "</span>";
59
      }
60
    }
Dries's avatar
   
Dries committed
61

62
63
64
65
66
67
68
    if ($actualchoices < 2) {
      $error["choice][0"] = "<span style=\"color: red;\">" . t("You must fill in at least two choices.") . "</span>";
    }
  }
  else {
    $help = variable_get("poll_help", "");
  }
Dries's avatar
   
Dries committed
69

70
71
72
73
74
  for ($c = 2; $c <= 20; $c++) {
    $opts[$c] = $c;
  }
  $output .= form_select(t("Number of choices"), "choices", $node->choices, $opts, t("This item only specifies the number of boxes in this form, but it doesn't have to equal the actual amount of options: you can leave the extra boxes empty."));
  $output .= form_submit(t("Preview")) . "<br><br><br>";
Dries's avatar
   
Dries committed
75

76
77
78
79
80
81
  for ($a = 0; $a < $node->choices; $a++) {
    $output .= form_textfield(t("Choice"). " " . ($a + 1), "choice][$a", $node->choice[$a], 50, 127, $error["choice][$a"]);
    if ($admin) {
      $output .= form_textfield(strtr(t("Votes for choice %n"), array("%n" => ($a + 1))), "chvotes][$a", $node->chvotes[$a] ? $node->chvotes[$a] : 0, 7, 7, $error["chvotes][$a"]);
    }
  }
Dries's avatar
   
Dries committed
82

83
84
85
  if ($admin) {
    $output .= form_select(t("Poll status"), "active", isset($node->active) ? $node->active : 1, $_active);
  }
86

87
  $output .= form_select(t("Poll duration"), "runtime", $node->runtime ? $node->runtime : 0, $_duration, t("After this period, the poll will automatically be closed."));
88

89
90
  return $output;
}
Dries's avatar
   
Dries committed
91

92
93
94
95
function poll_help() {
 ?>
 <?php
}
96

97
98
99
100
101
102
103
function poll_insert($node) {
  if (!user_access("administer nodes")) {
    // Make sure all votes are 0 initially
    for ($i = 0; $i < count($node->chvotes); $i++)
      $node->chvotes[$i] = 0;
    $node->active = 1;
  }
104

105
106
107
108
109
110
  db_query("INSERT INTO poll (nid, runtime, voters, active) VALUES ('$node->nid', '$node->runtime', '', '$node->active')");
  
  for ($i = 0; $i < $node->choices; $i++) {
    $choice->chtext = filter($node->choice[$i]);
    $choice->chvotes = (int)$node->chvotes[$i];
    $choice->chorder = $i;
Dries's avatar
   
Dries committed
111

112
113
114
115
    if ($choice->chtext != "") {
      db_query("INSERT INTO poll_choices (nid, chtext, chvotes, chorder) VALUES ('$node->nid', '$choice->chtext', '$choice->chvotes', '$choice->chorder')");
    }
  }
116
117
}

118
119
120
121
function poll_link($type) {
  if ($type == "menu.create" && user_access("post content")) {
    $links[] = "<a href=\"module.php?mod=node&op=add&type=poll\" title=\"". t("Add a new poll.") ."\">". t("create poll") ."</a>";
  }
122

123
124
  return $links ? $links : array();
}
Dries's avatar
   
Dries committed
125

126
127
128
129
130
131
132
133
134
135
136
function poll_load($node) {
  // Load the appropriate choices into the $node object
  $poll = db_fetch_object(db_query("SELECT runtime, voters, active FROM poll WHERE nid = '$node->nid'"));
  
  $result = db_query("SELECT chtext, chvotes, chorder FROM poll_choices WHERE nid='$node->nid' ORDER BY chorder");
  while ($choice = db_fetch_object($result)) {
    $poll->choice[$choice->chorder]  = $choice->chtext;
    $poll->chvotes[$choice->chorder] = $choice->chvotes;
  }
  return $poll;
}
Dries's avatar
   
Dries committed
137

138
139
140
function poll_node($field) {
  $info["name"] = t("poll");
  $info["description"] = t("A poll is a multiple-choice question which visitors can vote on.");
Dries's avatar
   
Dries committed
141

142
143
  return $info[$field];
}
144

145
146
147
function poll_perm() {
  return array("vote on polls");
}
Dries's avatar
   
Dries committed
148

149
150
151
function poll_save($op, $node) {
  if ($op == "approve") {
    return array("status" => 1, "promote" => 1);
152
  }
Dries's avatar
   
Dries committed
153

154
155
156
157
158
159
160
  if ($op == "create") {
    if (user_access("administer nodes")) {
      return array("runtime", "active", "choice", "choices", "chvotes", "body" => "", "teaser" => poll_teaser($node));
    }
    else {
      return array("runtime", "active", "choice", "choices", "chvotes", "body" => "", "moderate" => 1, "teaser" => poll_teaser($node));
    }
161
  }
Dries's avatar
   
Dries committed
162

163
164
  if ($op == "decline") {
    return array("status" => 0, "promote" => 0);
165
166
  }

167
168
169
  if ($op == "update") {
    return array("runtime", "active", "choice", "choices", "chvotes");
  }
170
171
}

172
173
174
175
176
177
178
179
180
function poll_teaser($node) {
  // Create a simple teaser that lists all the choices
  foreach ($node->choice as $k => $v) {
    if ($v != "") {
      $teaser .= "* $v\n";
    }
  }
  return $teaser;
}
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
function poll_view(&$node, $main = 0, $block = 0) {
  global $theme, $user;
  
  /* When a poll is displayed twice on the same page (e.g. on the front page and in the side bar)
     we only want to vote on one of them. We keep count using $pollid */  
  global $pollidcount, $pollvote, $pollid, $REMOTE_ADDR, $REQUEST_URI;
  $pollidcount++;
  
  // Only accept votes on specific cases to prevent double voting
  $allowvotes = false;
  if (user_access("vote on polls")) {
    if ($user->uid) {
      // Pad the UID with underscores to allow a simple strstr() search
      $id = "_" . $user->uid . "_";
    }
    else {
      $id = $REMOTE_ADDR;
    }
    if (!strstr($node->voters, $id)) {
      $allowvotes = $node->active;
    }
  } 

  if (($pollid == $pollidcount) && isset($pollvote) && ($allowvotes)) {
    // The user has submitted a valid vote
    if (!empty($node->choice[$pollvote])) {   
      $node->voters = $node->voters ? ($node->voters . " " . $id) : $id;
      db_query("UPDATE poll SET voters='$node->voters' WHERE nid='$node->nid'");
      db_query("UPDATE poll_choices SET chvotes = chvotes + 1 WHERE nid='$node->nid' AND chorder='$pollvote'");
      $allowvotes = false;
      $node->chvotes[$pollvote]++;
    }
214
  }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  
  if ($allowvotes) {
    // Display the vote form
    $url = $REQUEST_URI . (strstr($REQUEST_URI, "?") ? "&" : "?") . "pollid=" . $pollidcount; 
    $output .= "<form action=\"$url\" method=\"post\">";
    $output .= "<table border=\"0\" align=\"center\"><tr><td>";

    foreach ($node->choice as $key => $value) {
      if ($value != "") {
        $output .= "<input type=\"radio\" name=\"pollvote\" value=\"$key\" /> $value<br />";
      }
    }
    if ($block) {
      $output .= "</td></tr><tr><td><div align=\"center\">" . form_submit(t("Vote")) . "</div></td></tr></table>";
    } else {
      $output .= "</td><td valign=\"middle\"><div align=\"right\">&nbsp;&nbsp;&nbsp;" . form_submit(t("Vote")) . "</div></td></tr></table>";
    }
    $output .= "</form>";
233
  }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  else {    
    // Display the results
    
    // Count the votes and find the maximum
    foreach ($node->choice as $key => $value) {
      $votestotal += $node->chvotes[$key];
      $votesmax = max($votesmax, $node->chvotes[$key]);
    }
    $votesmax = max($votesmax, 1);
    
    // Define CSS classes for the bars
    $output .= "<style type=\"text/css\">";
    $output .= "td.pollfg { background-color: " . $theme->foreground . "; font-size: 5pt; }";
    $output .= "td.pollbg { background-color: " . $theme->background . "; font-size: 5pt; }";
    $output .= "</style>";
        
    foreach ($node->choice as $key => $value) {
      if ($value != "") {
        $width = round($node->chvotes[$key] * 100 / $votesmax);
        $percentage = round($node->chvotes[$key] * 100 / max($votestotal, 1));

        $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"95%\" align=\"center\"><tr><td>$value</td><td><div align=\"right\"> $percentage%" . (!$block ? " (" . $node->chvotes[$key] . " votes)" : "") . "</div></td></tr></table>";
        if ($width == 0) {
          $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"95%\" align=\"center\"><tr><td class=\"pollbg\" width=\"100%\">&nbsp;</td></tr></table>"; 
        }
        else if ($width == 100) {
          $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"95%\" align=\"center\"><tr><td class=\"pollfg\" width=\"100%\">&nbsp;</td></tr></table>";
        }
        else {
          $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"95%\" align=\"center\"><tr><td class=\"pollfg\" width=\"" . $width . "%\">&nbsp;</td><td class=\"pollbg\" width=\"" . (100 - $width) . "%\">&nbsp;</td></tr></table>";
        }
Dries's avatar
   
Dries committed
265
      }
266
    }
267
    $output .= "<br><div align=\"center\">Total votes: " . $votestotal . "</div>";
268
  }
269
270
271
  // Force the output on both the mainpage and elsewhere
  $node->body = $output;
  $node->teaser = $output;
272

273
274
275
  // We also use poll_view() for the side-block
  if ($block == 0) {
    $theme->node($node, $main);
276
277
278
  }
}

279
280
281
282
283
284
285
286
function poll_update($node) {
  db_query("UPDATE poll SET runtime='$node->runtime', active='$node->active' WHERE nid='$node->nid'");

  db_query("DELETE FROM poll_choices WHERE nid='$node->nid'");
  for ($i = 0; $i < $node->choices; $i++) {
    $choice->chtext = filter($node->choice[$i]);
    $choice->chvotes = (int)$node->chvotes[$i];
    $choice->chorder = $i;    
287

288
289
290
    if ($choice->chtext != "") {
      db_query("INSERT INTO poll_choices (nid, chtext, chvotes, chorder) VALUES ('$node->nid', '$choice->chtext', '$choice->chvotes', '$choice->chorder')");
    }
291
292
  }
}
293

294
?>