2 rcs_id('$Id: WikiPoll.php,v 1.7 2004-05-01 15:59:29 rurban Exp $');
4 Copyright 2004 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
8 PhpWiki is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 PhpWiki is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with PhpWiki; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This plugin provides configurable polls.
26 <?plugin WikiPoll require_all=0 require_least=2
27 question[1]="Do you like PhpWiki?"
28 answer[1][1]="Yes" answer[1][2]="Do not know" answer[1][3]="No"
29 question[2]="Do you have PhpWiki installed by your own?"
30 answer[2][1]="Yes" answer[2][2]="No"
31 question[3]="Did you install any other wiki engine?"
32 answer[3][1]="Yes" answer[3][2]="No"
33 question[4]="What wiki engine do you like most?"
34 answer[4][1]="c2Wiki" answer[4][2]="MoinMoin" answer[4][3]="PhpWiki"
35 answer[4][4]="usemod" answer[4][5]="Twiki" answer[4][5]="guiki"
37 question[5]="Which PhpWiki version do you use?"
38 answer[5][1]="1.2.x" answer[5][2]="1.3. 1-2" answer[5][3]="1.3.3-4"
39 answer[5][4]="1.3.5-8"
43 * <?plugin WikiPoll page=PhpWikiPoll admin=1 ?>
44 * and protect this page properly (e.g. PhpWikiPoll/Admin)
47 * admin page (view and reset statistics)
48 * for now only radio, support checkboxes (multiple selections) also?
53 class WikiPlugin_WikiPoll
62 function getDescription () {
63 return _("Enable configurable polls");
66 function getVersion() {
67 return preg_replace("/[Revision: $]/", '',
71 function getDefaultArguments() {
72 return array('page' => '[pagename]',
74 'require_all' => 1, // 1 if all questions must be answered
75 'require_least' => 0, // how many at least
79 function getArgs($argstr, $request=false, $defaults = false) {
80 if ($defaults === false)
81 $defaults = $this->getDefaultArguments();
82 //Fixme: on POST argstr is empty
84 list ($argstr_args, $argstr_defaults) = $this->parseArgStr($argstr);
85 if (isset($argstr_args["question_1"])) {
86 $args['question'] = $this->str2array("question",$argstr_args);
87 $args['answer'] = array();
88 for ($i = 0; $i <= count($args['question']); $i++) {
89 if ($array = $this->str2array(sprintf("%s_%d","answer",$i),$argstr_args))
90 $args['answer'][$i] = $array;
94 if (!empty($defaults))
95 foreach ($defaults as $arg => $default_val) {
96 if (isset($argstr_args[$arg]))
97 $args[$arg] = $argstr_args[$arg];
98 elseif ( $request and ($argval = $request->getArg($arg)) !== false )
99 $args[$arg] = $argval;
100 elseif (isset($argstr_defaults[$arg]))
101 $args[$arg] = (string) $argstr_defaults[$arg];
103 $args[$arg] = $default_val;
106 $args[$arg] = $this->expandArg($args[$arg], $request);
108 unset($argstr_args[$arg]);
109 unset($argstr_defaults[$arg]);
112 foreach (array_merge($argstr_args, $argstr_defaults) as $arg => $val) {
113 if (!preg_match("/^(answer_|question_)/",$arg))
114 trigger_error(sprintf(_("argument '%s' not declared by plugin"),
115 $arg), E_USER_NOTICE);
121 function handle_plugin_args_cruft($argstr, $args) {
122 $argstr = str_replace("\n"," ",$argstr);
123 $argstr = str_replace(array("[","]"),array("_",""),$argstr);
124 $this->_args = $this->getArgs($argstr, $GLOBALS['request']);
128 function str2array($var, $obarray=false) {
129 if (!$obarray) $obarray = $GLOBALS;
130 $i = 0; $array = array();
131 $name = sprintf("%s_%d",$var,$i);
132 if (isset($obarray[$name])) $array[$i] = $obarray[$name];
135 $name = sprintf("%s_%d",$var,$i);
136 if (isset($obarray[$name])) $array[$i] = $obarray[$name];
137 } while (isset($obarray[$name]));
141 function run($dbi, $argstr, &$request, $basepage) {
142 if (!isset($_SERVER))
143 $_SERVER =& $GLOBALS['HTTP_SERVER_VARS'];
144 $request->setArg('nocache','purge');
145 $args = $this->getArgs($argstr, $request);
147 return $this->error("No page specified");
148 if (!empty($args['admin']) and $request->_user->isAdmin()) {
150 return $this->doPollAdmin($dbi, $request, $page);
152 extract($this->_args);
153 $page = $dbi->getPage($args['page']);
154 // check ip and last visit
155 $poll = $page->get("poll");
156 $ip = $_SERVER['REMOTE_ADDR'];
157 $disable_submit = false;
158 if (isset($poll['ip'][$ip]) and ((time() - $poll['ip'][$ip]) < 20*60)) {
159 //view at least the result or disable the Go button
160 $html = HTML(HTML::strong(
161 _("Sorry! You must wait at least 20 minutes until you can vote again!")));
162 $html->pushContent($this->doPoll(&$page, &$request, $request->getArg('answer'),true));
166 $poll['ip'][$ip] = time();
168 foreach ($poll['ip'] as $ip => $time) {
169 if ((time() - $time) > 21*60)
170 unset($poll['ip'][$ip]);
172 $html = HTML::form(array('action' => $request->getPostURL(),
173 'method' => 'POST'));
175 if ($request->isPost()) {
176 // checkme: check if all answers are answered
177 if ($request->getArg('answer') and (
178 ($args['require_all'] and
179 count($request->getArg('answer')) == count($question))
181 ($args['require_least'] and
182 count($request->getArg('answer')) >= $args['require_least']))) {
183 $page->set("poll",$poll);
184 // update statistics and present them the user
185 return $this->doPoll(&$page, &$request, $request->getArg('answer'));
187 $html->pushContent(HTML::p(HTML::strong(_("Not enough questions answered!"))));
191 $init = isset($question[0]) ? 0 : 1;
192 for ($i = $init; $i <= count($question); $i++) {
193 if (!isset($question[$i])) break;
195 if (!isset($answer[$i]))
196 trigger_error(fmt("Missing %s for %s","answer"."[$i]","question"."[$i]"),
199 if (! is_array($a)) {
201 $html->pushContent(HTML::p(HTML::strong($q)));
202 $html->pushContent(HTML::div(
203 HTML::input(array('type' => 'checkbox',
204 'name' => "answer[$i]",
206 HTML::raw(" "), $a));
209 for ($j=0; $j <= count($a); $j++) {
211 $row->pushContent(HTML::div(
212 HTML::input(array('type' => 'radio',
213 'name' => "answer[$i]",
215 HTML::raw(" "), $a[$j]));
217 $html->pushContent(HTML::p(HTML::strong($q)),$row);
220 if (!$disable_submit)
221 $html->pushContent(HTML::p(
222 HTML::input(array('type' => 'submit',
223 'name' => "WikiPoll",
224 'value' => _("Ok"))),
225 HTML::input(array('type' => 'reset',
227 'value' => _("Reset")))));
229 $html->pushContent(HTML::p(),HTML::strong(
230 _("Sorry! You must wait at least 20 minutes until you can vote again!")));
234 function bar($percent) {
236 return HTML(HTML::img(array('src' => $Theme->getImageUrl('leftbar'),
238 HTML::img(array('src' => $Theme->getImageUrl('mainbar'),
240 'width' => sprintf("%02d",$percent),
242 HTML::img(array('src' => $Theme->getImageUrl('rightbar'),
246 function doPoll($page, $request, $answers, $readonly = false) {
247 $question = $this->_args['question'];
248 $answer = $this->_args['answer'];
249 $html = HTML::table(array('cellspacing' => 2));
250 $init = isset($question[0]) ? 0 : 1;
251 for ($i = $init; $i <= count($question); $i++) {
252 if (!isset($question[$i])) break;
253 $poll = $page->get('poll');
254 @$poll['data']['all'][$i]++;
256 if (!isset($answer[$i]))
257 trigger_error(fmt("Missing %s for %s","answer"."[$i]","question"."[$i]"),
260 $page->set('poll',$poll);
262 $result = (isset($answers[$i])) ? $answers[$i] : -1;
263 if (! is_array($a) ) {
264 $checkbox = HTML::input(array('type' => 'checkbox',
265 'name' => "answer[$i]",
268 $checkbox->setAttr('checked',1);
270 list($percent,$count,$all) = $this->storeResult(&$page, $i, $result ? 1 : 0);
272 list($percent,$count,$all) = $this->getResult(&$page, $i, 1);
273 $print = sprintf(_(" %d%% (%d/%d)"),$percent,$count,$all);
274 $html->pushContent(HTML::tr(HTML::th(array('colspan' => 4,'align'=>'left'),$q)));
275 $html->pushContent(HTML::tr(HTML::td($checkbox),
277 HTML::td($this->bar($percent)),
280 $html->pushContent(HTML::tr(HTML::th(array('colspan' => 4,'align'=>'left'),$q)));
283 $this->storeResult(&$page,$i,$answers[$i]);
284 for ($j=0; $j <= count($a); $j++) {
286 list($percent,$count,$all) = $this->getResult(&$page,$i,$j);
287 $print = sprintf(_(" %d%% (%d/%d)"),$percent,$count,$all);
288 $radio = HTML::input(array('type' => 'radio',
289 'name' => "answer[$i]",
292 $radio->setAttr('checked',1);
293 $row->pushContent(HTML::tr(HTML::td($radio),
295 HTML::td($this->bar($percent)),
299 $html->pushContent($row);
303 return HTML(HTML::h3(_("The result of this poll so far:")),$html,HTML::p(_("Thanks for participating!")));
305 return HTML(HTML::h3(_("The result of this poll so far:")),$html);
309 function getResult($page,$i,$j) {
310 $poll = $page->get("poll");
311 @$count = $poll['data']['count'][$i][$j];
312 @$all = $poll['data']['all'][$i];
313 $percent = sprintf("%d", $count * 100.0 / $all);
314 return array($percent,$count,$all);
317 function storeResult($page, $i, $j) {
318 $poll = $page->get("poll");
320 $poll = array('data' => array('count' => array(),
323 @$poll['data']['count'][$i][$j]++;
324 //@$poll['data']['all'][$i];
325 $page->set("poll",$poll);
326 $percent = sprintf("%d", $poll['data']['count'][$i][$j] * 100.0 / $poll['data']['all'][$i]);
327 return array($percent,$poll['data']['count'][$i][$j],$poll['data']['all'][$i]);
332 // $Log: not supported by cvs2svn $
333 // Revision 1.6 2004/03/01 18:08:53 rurban
334 // oops, checked in the debug version. revert to IP check on
336 // Revision 1.5 2004/03/01 16:11:13 rurban
337 // graphical enhancement
339 // Revision 1.4 2004/02/26 01:42:27 rurban
340 // don't cache this at all
342 // Revision 1.3 2004/02/24 03:54:46 rurban
343 // lock page, more questions, new require_least arg
345 // Revision 1.2 2004/02/24 03:21:46 rurban
346 // enabled require_all check in WikiPoll
347 // better handling of <20 min visiting client: display results so far
356 // c-hanging-comment-ender-p: nil
357 // indent-tabs-mode: nil