]> sipb.mit.edu Git - ikiwiki.git/commitdiff
add a poll plugin
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Sun, 26 Nov 2006 19:46:11 +0000 (19:46 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Sun, 26 Nov 2006 19:46:11 +0000 (19:46 +0000)
IkiWiki/Plugin/poll.pm [new file with mode: 0644]
basewiki/style.css
debian/changelog
doc/plugins/poll.mdwn [new file with mode: 0644]

diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm
new file mode 100644 (file)
index 0000000..b862ccd
--- /dev/null
@@ -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
index 032665e7056d4ca86c87893cba065a73d7cf3f55..1017e957f37e6a2b31c0fd92b38fadd5b33ec132 100644 (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;
index 900e62de4b4a22783a8b42d1daa96be9d03eaa2a..345878cfcb98e75d5e09692e74990c77bf54d897 100644 (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
 
diff --git a/doc/plugins/poll.mdwn b/doc/plugins/poll.mdwn
new file mode 100644 (file)
index 0000000..385a78b
--- /dev/null
@@ -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".