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
  $blocks[0][subject] = strtr(t("Latest poll: %t"), array("%t" => $poll->title));
24
  $blocks[0][content] = $poll->body;
25
  $blocks[0][info] = t("Most recent poll");
26
  return $blocks;
27 28
}

29 30 31
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'");
Dries's avatar
 
Dries committed
32
  while ($poll = db_fetch_object($result)) {
33
    db_query("UPDATE poll SET active='0' WHERE lid='$poll->lid'");
Dries's avatar
 
Dries committed
34
  }
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
  db_query("INSERT INTO poll (nid, runtime, voters, active) VALUES ('$node->nid', '$node->runtime', '', '$node->active')");
Dries's avatar
 
Dries committed
106

107 108 109 110
  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
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'"));
Dries's avatar
 
Dries committed
129

130 131 132 133 134 135 136
  $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
function poll_view(&$node, $main = 0, $block = 0) {
  global $theme, $user;
Dries's avatar
 
Dries committed
184

185
  /* When a poll is displayed twice on the same page (e.g. on the front page and in the side bar)
Dries's avatar
 
Dries committed
186
     we only want to vote on one of them. We keep count using $pollid */
187 188
  global $pollidcount, $pollvote, $pollid, $REMOTE_ADDR, $REQUEST_URI;
  $pollidcount++;
Dries's avatar
 
Dries committed
189

190 191 192 193 194 195 196 197 198 199 200 201 202
  // 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;
    }
Dries's avatar
 
Dries committed
203
  }
204 205 206

  if (($pollid == $pollidcount) && isset($pollvote) && ($allowvotes)) {
    // The user has submitted a valid vote
Dries's avatar
 
Dries committed
207
    if (!empty($node->choice[$pollvote])) {
208 209 210 211 212 213
      $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
  }
Dries's avatar
 
Dries committed
215

216 217
  if ($allowvotes) {
    // Display the vote form
Dries's avatar
 
Dries committed
218
    $url = $REQUEST_URI . (strstr($REQUEST_URI, "?") ? "&" : "?") . "pollid=" . $pollidcount;
219 220 221 222 223 224 225 226 227 228 229 230 231 232
    $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
  }
Dries's avatar
 
Dries committed
234
  else {
235
    // Display the results
Dries's avatar
 
Dries committed
236

237 238 239 240 241 242
    // 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);
Dries's avatar
 
Dries committed
243

244 245 246 247 248
    // 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>";
Dries's avatar
 
Dries committed
249

250 251 252 253 254 255 256
    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) {
Dries's avatar
 
Dries committed
257
          $output .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"95%\" align=\"center\"><tr><td class=\"pollbg\" width=\"100%\">&nbsp;</td></tr></table>";
258 259 260 261 262 263 264
        }
        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
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];
Dries's avatar
 
Dries committed
286
    $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
?>