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
?>