add a poll plugin

master
joey 2006-11-26 19:46:11 +00:00
parent 7aab2d2ac6
commit 5800d2160c
4 changed files with 200 additions and 1 deletions

View File

@ -0,0 +1,160 @@
#!/usr/bin/perl
package IkiWiki::Plugin::poll;
use warnings;
use strict;
use IkiWiki;
use URI;
sub import { #{{{
hook(type => "preprocess", id => "poll", call => \&preprocess);
hook(type => "cgi", id => "poll", call => \&cgi);
} # }}}
sub yesno ($) { #{{{
my $val=shift;
return (defined $val && lc($val) eq "yes");
} #}}}
my %pagenum;
sub preprocess (@) { #{{{
my %params=(open => "yes", total => "yes", percent => "yes", @_);
my $open=yesno($params{open});
my $showtotal=yesno($params{total});
my $percent=yesno($params{percent});
$pagenum{$params{page}}++;
my %choices;
my @choices;
my $total=0;
while (@_) {
my $key=shift;
my $value=shift;
next unless $key =~ /^\d+/;
my $num=$key;
$key=shift;
$value=shift;
$choices{$key}=$num;
push @choices, $key;
$total+=$num;
}
my $ret="";
foreach my $choice (@choices) {
my $percent=int($choices{$choice} / $total * 100);
if ($percent) {
$ret.="$choice ($percent%) ";
}
else {
$ret.="$choice ($choices{$choice}) ";
}
if ($open && exists $config{cgiurl}) {
my $url=URI->new($config{cgiurl});
$url->query_form(
"do" => "poll",
"num" => $pagenum{$params{page}},
"page" => $params{page},
"choice" => $choice,
);
$ret.="<a class=pollbutton href=\"$url\">vote</a>";
}
$ret.="<br />\n<hr class=poll align=left width=\"$percent%\"/>\n";
}
if ($showtotal) {
$ret.="<span>Total votes: $total</span>\n";
}
return "<div class=poll>$ret</div>";
} # }}}
sub cgi ($) { #{{{
my $cgi=shift;
if (defined $cgi->param('do') && $cgi->param('do') eq "poll") {
my $choice=$cgi->param('choice');
if (! defined $choice) {
error("no choice specified");
}
my $num=$cgi->param('num');
if (! defined $num) {
error("no num specified");
}
my $page=IkiWiki::possibly_foolish_untaint($cgi->param('page'));
if (! defined $page || ! exists $pagesources{$page}) {
error("bad page name");
}
# Did they vote before? If so, let them change their vote,
# and check for dups.
my $session=IkiWiki::cgi_getsession();
my $choice_param="poll_choice_${page}_$num";
my $oldchoice=$session->param($choice_param);
if (defined $oldchoice && $oldchoice eq $choice) {
# Same vote; no-op.
IkiWiki::redirect($cgi, "$config{url}/".htmlpage($page));
}
my $content=readfile(srcfile($pagesources{$page}));
# Now parse the content, find the right poll,
# and find the choice within it, and increment its number.
# If they voted before, decrement that one.
my $edit=sub {
my $escape=shift;
my $params=shift;
return "\\[[poll $params]]" if $escape;
return $params unless --$num == 0;
my @bits=split(' ', $params);
my @ret;
while (@bits) {
my $n=shift @bits;
if ($n=~/=/) {
# val=param setting
push @ret, $n;
next;
}
my $c=shift @bits;
$c=~s/^"(.*)"/$1/g;
next unless defined $n && defined $c;
if ($c eq $choice) {
$n++;
}
if (defined $oldchoice && $c eq $oldchoice) {
$n--;
}
push @ret, $n, "\"$c\"";
}
return "[[poll ".join(" ", @ret)."]]";
};
$content =~ s{(\\?)\[\[poll\s+([^]]+)\s*\]\]}{$edit->($1, $2)}seg;
# Store their vote, update the page, and redirect to it.
writefile($pagesources{$page}, $config{srcdir}, $content);
$session->param($choice_param, $choice);
IkiWiki::cgi_savesession($session);
$oldchoice=$session->param($choice_param);
if ($config{rcs}) {
# prevent deadlock with post-commit hook
IkiWiki::unlockwiki();
IkiWiki::rcs_commit($pagesources{$page}, "poll vote",
IkiWiki::rcs_prepedit($pagesources{$page}),
$session->param("name"), $ENV{REMOTE_ADDR});
}
else {
require IkiWiki::Render;
IkiWiki::refresh();
IkiWiki::saveindex();
}
# Need to set cookie in same http response that does the
# redir.
eval q{use CGI::Cookie};
error($@) if $@;
my $cookie = CGI::Cookie->new(-name=> $session->name, -value=> $session->id);
print $cgi->redirect(-cookie => $cookie,
-url => "$config{url}/".htmlpage($page));
exit;
}
} #}}}
1

View File

@ -206,6 +206,19 @@ li.L8 {
list-style: upper-alpha;
}
hr.poll {
height: 10pt;
color: white !important;
background: #eee;
border: 2px solid black;
}
div.poll {
margin-top: 1ex;
margin-bottom: 1ex;
padding: 1ex 1ex;
border: 1px solid #aaa;
}
input#openid_url {
background: url(http://openid.net/login-bg.gif) no-repeat;
background-color: #fff;

4
debian/changelog vendored
View File

@ -44,8 +44,10 @@ ikiwiki (1.34) UNRELEASED; urgency=low
and their IP address, and needs to construct its own commit message
containing them, or do something more appropriate for the given RCS.
* Add softwaresite example.
* Add a poll plugin.
* Add quick mode for archive page generation.
-- Joey Hess <joeyh@debian.org> Wed, 22 Nov 2006 09:59:12 -0500
-- Joey Hess <joeyh@debian.org> Thu, 23 Nov 2006 17:13:32 -0500
ikiwiki (1.33) unstable; urgency=low

View File

@ -0,0 +1,24 @@
[[template id=plugin name=poll included=1 author="[[Joey]]"]]
[[tag type/useful]]
This plugin allows you to create online polls in the wiki. Here's an
example use:
\[[poll 0 "red" 0 "green" 0 "blue"]]
The numbers indicate how many users voted for that choice. When a user
votes for a choice in the poll, the page is modified and the number
incremented.
While some basic precautions are taken to prevent users from accidentially
voting twice, this sort of poll is should not be counted on the be very
accurate; all the usual concerns about web based polling apply. Unless the
page that the poll is in is locked, users can even edit the page and change
the numbers!
Parameters:
* `open` - Whether voting is still open. Set to "no" to close the poll to
voting.
* `total` - Show total number of votes at bottom of poll. Default is "yes".
* `percent` - Whether to display percents. Default is "yes".