drupal/modules/poll.module

295 lines
11 KiB
Plaintext

<?php
// $Id$
function poll_access($op, $node) {
if ($op == "view") {
return $node->status;
}
if ($op == "create") {
return 1;
}
}
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);
}
}
$blocks[0][subject] = strtr(t("Latest poll: %t"), array("%t" => $poll->title));
$blocks[0][content] = $poll->body;
$blocks[0][info] = t("Most recent poll");
return $blocks;
}
function poll_cron() {
// Close polls that have exceeded their allowed runtime
$result = db_query("SELECT p.nid 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 nid='$poll->nid'");
}
}
function poll_delete($node) {
db_query("DELETE FROM poll WHERE nid='$node->nid'");
db_query("DELETE FROM poll_choices WHERE nid='$node->nid'");
}
function poll_form(&$node, &$help, &$error) {
$admin = user_access("administer nodes");
$_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 => t("Closed"), 1 => t("Active"));
$node->choices = $node->choices ? $node->choices : max(2, count($node->choices) ? count($node->choices) : 5);
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++;
}
if ($node->chvotes[$i] < 0) {
$error["chvotes][$i"] = "<span style=\"color: red;\">" . t("Negative values are not allowed.") . "</span>";
}
}
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", "");
}
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>";
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"]);
}
}
if ($admin) {
$output .= form_select(t("Poll status"), "active", isset($node->active) ? $node->active : 1, $_active);
}
$output .= form_select(t("Poll duration"), "runtime", $node->runtime ? $node->runtime : 0, $_duration, t("After this period, the poll will automatically be closed."));
return $output;
}
function poll_help() {
?><p>Drupal's poll module allows users to submit multiple-choice questions that others can vote on.</p>
<?php
}
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;
}
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;
if ($choice->chtext != "") {
db_query("INSERT INTO poll_choices (nid, chtext, chvotes, chorder) VALUES ('$node->nid', '$choice->chtext', '$choice->chvotes', '$choice->chorder')");
}
}
}
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>";
}
return $links ? $links : array();
}
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;
}
function poll_node($field) {
$info["name"] = t("poll");
$info["description"] = t("A poll is a multiple-choice question which visitors can vote on.");
return $info[$field];
}
function poll_perm() {
return array("vote on polls");
}
function poll_save($op, $node) {
if ($op == "approve") {
return array("status" => 1, "promote" => 1);
}
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));
}
}
if ($op == "decline") {
return array("status" => 0, "promote" => 0);
}
if ($op == "update") {
return array("runtime", "active", "choice", "choices", "chvotes");
}
}
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;
}
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]++;
}
}
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>";
}
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>";
}
}
}
$output .= "<br><div align=\"center\">Total votes: " . $votestotal . "</div>";
}
// Force the output on both the mainpage and elsewhere
$node->body = $output;
$node->teaser = $output;
// We also use poll_view() for the side-block
if ($block == 0) {
$theme->node($node, $main);
}
}
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;
if ($choice->chtext != "") {
db_query("INSERT INTO poll_choices (nid, chtext, chvotes, chorder) VALUES ('$node->nid', '$choice->chtext', '$choice->chvotes', '$choice->chorder')");
}
}
}
?>