]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/WikiPoll.php
a new toy, first version without admin page and check if all questions are asked
[SourceForge/phpwiki.git] / lib / plugin / WikiPoll.php
1 <?php // -*-php-*-
2 rcs_id('$Id: WikiPoll.php,v 1.1 2004-02-24 02:45:45 rurban Exp $');
3 /*
4  Copyright 2004 $ThePhpWikiProgrammingTeam
5  
6  This file is part of PhpWiki.
7
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.
12
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.
17
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
21  */
22 /**
23  * This plugin provides configurable polls.
24  *
25  * Usage:
26  * <?plugin WikiPoll
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]="Did you install other wiki engines before?"
30  *            answer[2][1]="Yes" answer[2][2]="No"
31  *          question[3]="What wiki engine do you like most?"
32  *            answer[3][1]="c2Wiki" answer[3][2]="MoinMoin" answer[3][3]="PhpWiki"
33  *            answer[3][4]="usemod" answer[3][5]="Twiki" answer[3][6]="Other"
34  * ?>
35  *
36  * Administration:
37  * <?plugin WikiPoll page=PhpWikiPoll admin=1 ?>
38  * and protect this page properly (e.g. PhpWikiPoll/Admin)
39  *
40  * TODO:
41  *     check all required buttons if require_all
42  *     admin page (view and reset statistics)
43  *
44  * Author: ReiniUrban
45  */
46
47 class WikiPlugin_WikiPoll
48 extends WikiPlugin
49 {
50     var $_args; 
51     
52     function getName () {
53         return _("WikiPoll");
54     }
55
56     function getDescription () {
57         return _("Enable configurable polls");
58     }
59
60     function getVersion() {
61         return preg_replace("/[Revision: $]/", '',
62                             "\$Revision: 1.1 $");
63     }
64
65     function getDefaultArguments() {
66         return array('page'        => '[pagename]',
67                      'admin'       => false,
68                      'require_all' => 1, // if all questions must be answered
69                     );
70     }
71
72     function getArgs($argstr, $request=false, $defaults = false) {
73         if ($defaults === false)
74             $defaults = $this->getDefaultArguments();
75         //Fixme: on POST argstr is empty
76         $args = array();
77         list ($argstr_args, $argstr_defaults) = $this->parseArgStr($argstr);
78         if (isset($argstr_args["question_1"])) {
79           $args['question'] = $this->str2array("question",$argstr_args);
80           $args['answer'] = array();
81           for ($i = 0; $i <= count($args['question']); $i++) {
82               if ($array = $this->str2array(sprintf("%s_%d","answer",$i),$argstr_args))
83                   $args['answer'][$i] = $array;
84           }
85         }
86         
87         if (!empty($defaults))
88           foreach ($defaults as $arg => $default_val) {
89             if (isset($argstr_args[$arg]))
90                 $args[$arg] = $argstr_args[$arg];
91             elseif ( $request and ($argval = $request->getArg($arg)) !== false )
92                 $args[$arg] = $argval;
93             elseif (isset($argstr_defaults[$arg]))
94                 $args[$arg] = (string) $argstr_defaults[$arg];
95             else
96                 $args[$arg] = $default_val;
97
98             if ($request)
99                 $args[$arg] = $this->expandArg($args[$arg], $request);
100
101             unset($argstr_args[$arg]);
102             unset($argstr_defaults[$arg]);
103         }
104
105         foreach (array_merge($argstr_args, $argstr_defaults) as $arg => $val) {
106             if (!preg_match("/^(answer_|question_)/",$arg))
107                 trigger_error(sprintf(_("argument '%s' not declared by plugin"),
108                                       $arg), E_USER_NOTICE);
109         }
110
111         return $args;
112     }
113     
114     function handle_plugin_args_cruft($argstr, $args) {
115         $argstr = str_replace("\n"," ",$argstr);
116         $argstr = str_replace(array("[","]"),array("_",""),$argstr);
117         $this->_args = $this->getArgs($argstr, $GLOBALS['request']);
118         return;
119     }
120
121     function str2array($var, $obarray=false) {
122         if (!$obarray) $obarray = $GLOBALS;
123         $i = 0; $array = array();
124         $name = sprintf("%s_%d",$var,$i);
125         if (isset($obarray[$name])) $array[$i] = $obarray[$name];
126         do {
127           $i++;
128           $name = sprintf("%s_%d",$var,$i);
129           if (isset($obarray[$name])) $array[$i] = $obarray[$name];
130         } while (isset($obarray[$name]));
131         return $array;
132     }
133     
134     function run($dbi, $argstr, &$request, $basepage) {
135         $args = $this->getArgs($argstr, $request);
136         if (!$args['page'])
137             return $this->error("No page specified");
138         if (!empty($args['admin']) and $request->_user->isAdmin()) {
139             // reset statistics
140             return $this->doPollAdmin($dbi, $request, $page);
141         }
142         extract($this->_args);
143         $page = $dbi->getPage($args['page']);
144         // check ip and last visit
145         $poll = $page->get("poll");
146         $ip = $_SERVER['REMOTE_ADDR'];
147         if (isset($poll['ip'][$ip]) and ((time() - $poll['ip'][$ip]) < 20*60))
148             //todo: view at least the result or disable the Go button
149             return HTML::strong(_("Sorry! You must wait at least 20 minutes until you can vote again!"));
150             
151         $poll['ip'][$ip] = time();
152         // purge older ip's
153         foreach ($poll['ip'] as $ip => $time) {
154             if ((time() - $time) > 21*60)
155                 unset($poll['ip'][$ip]);
156         }
157         $page->set("poll",$poll);    
158
159         if ($request->isPost() and $request->getArg('answer')) {
160             // update statistics and present them the user
161             return $this->doPoll(&$page, &$request, $request->getArg('answer'));
162         }
163         
164         $html = HTML::form(array('action' => $request->getPostURL(),
165                                  'method' => 'POST'));
166         $init = isset($question[0]) ? 0 : 1;
167         for ($i = $init; $i <= count($question); $i++) {
168             if (!isset($question[$i])) break;
169             $q = $question[$i]; 
170             if (!isset($answer[$i]))
171                 trigger_error(fmt("missing %s for %s","answer"."[$i]","question"."[$i]"),
172                               E_USER_ERROR);
173             $a = $answer[$i];
174             if (! is_array($a)) {
175                 // a simple checkbox
176                 $html->pushContent(HTML::p(HTML::strong($q)));
177                 $html->pushContent(HTML::div(
178                                        HTML::input(array('type' => 'checkbox',
179                                                          'name' => "answer[$i]",
180                                                          'value' => 1)),
181                                        HTML::raw("&nbsp;"), $a));
182             } else {
183                 $row = HTML();
184                 for ($j=0; $j <= count($a); $j++) {
185                     if (isset($a[$j]))
186                         $row->pushContent(HTML::div(
187                                               HTML::input(array('type' => 'radio',
188                                                                 'name' => "answer[$i]",
189                                                                 'value' => $j)),
190                                               HTML::raw("&nbsp;"), $a[$j]));
191                 }
192                 $html->pushContent(HTML::p(HTML::strong($q)),$row);
193             }
194         }
195         $html->pushContent(HTML::p(
196                 HTML::input(array('type' => 'submit',
197                                   'name' => "WikiPoll",
198                                   'value' => _("Ok"))),
199                 HTML::input(array('type' => 'reset',
200                                   'name' => "reset",
201                                   'value' => _("Reset")))));
202         return $html;
203     }
204
205     function doPoll($page, $request, $answers) {
206         $question = $this->_args['question'];
207         $answer   = $this->_args['answer'];
208         $html = HTML::table(array('cellspacing' => 2));
209         $init = isset($question[0]) ? 0 : 1;
210         for ($i = $init; $i <= count($question); $i++) {
211             if (!isset($question[$i])) break;
212             $poll = $page->get('poll');
213             @$poll['data']['all'][$i]++;
214             $q = $question[$i]; 
215             if (!isset($answer[$i]))
216                 trigger_error(fmt("missing %s for %s","answer"."[$i]","question"."[$i]"),
217                               E_USER_ERROR);
218             $page->set('poll',$poll);
219             $a = $answer[$i];
220             if (! is_array($a) ) {
221                 $checkbox = HTML::input(array('type' => 'checkbox',
222                                               'name' => "answer[$i]",
223                                               'value' => $a));
224                 if ($answers[$i])
225                     $checkbox->setAttr('checked',1);
226                 list($percent,$count,$all) = $this->storeResult(&$page, $i, $answers[$i] ? 1 : 0);
227                 $result = sprintf(_("  %d%% selected this (%d/%d)"),$percent,$count,$all);
228                 $html->pushContent(HTML::tr(HTML::th(array('colspan' => 3,'align'=>'left'),$q)));
229                 $html->pushContent(HTML::tr(HTML::td($checkbox),
230                                             HTML::td($a),
231                                             HTML::td($result)));
232             } else {
233                 $html->pushContent(HTML::tr(HTML::th(array('colspan' => 3,'align'=>'left'),$q)));
234                 $row = HTML();
235                 $this->storeResult(&$page,$i,$answers[$i]);
236                 for ($j=0; $j <= count($a); $j++) {
237                     if (isset($a[$j])) {
238                         list($percent,$count,$all) = $this->getResult(&$page,$i,$j);
239                         $result = sprintf(_("  %d%% selected this (%d/%d)"),$percent,$count,$all);
240                         $radio = HTML::input(array('type' => 'radio',
241                                                    'name' => "answer[$i]",
242                                                    'value' => $j));
243                         if ($answers[$i] == $j)
244                             $radio->setAttr('checked',1);
245                         $row->pushContent(HTML::tr(HTML::td($radio),
246                                                    HTML::td($a[$j]),
247                                                    HTML::td($result)));
248                     }
249                 }
250                 $html->pushContent($row);
251             }
252         }
253         return HTML($html,HTML::p(_("Thanks for participating!")));
254     }
255     
256     function getResult($page,$i,$j) {
257         $poll = $page->get("poll");
258         @$count = $poll['data']['count'][$i][$j];
259         @$all = $poll['data']['all'][$i];
260         $percent = sprintf("%d", $count * 100.0 / $all);
261         return array($percent,$count,$all);
262     }
263     
264     function storeResult($page, $i, $j) {
265         $poll = $page->get("poll");
266         if (!$poll) {
267             $poll = array('data' => array('count' => array(),
268                                           'all'   => array()));
269         }
270         @$poll['data']['count'][$i][$j]++;
271         //@$poll['data']['all'][$i];
272         $page->set("poll",$poll);
273         $percent = sprintf("%d", $poll['data']['count'][$i][$j] * 100.0 / $poll['data']['all'][$i]);
274         return array($percent,$poll['data']['count'][$i][$j],$poll['data']['all'][$i]);
275     }
276
277 };
278
279 // $Log: not supported by cvs2svn $
280 //
281
282 // For emacs users
283 // Local Variables:
284 // mode: php
285 // tab-width: 8
286 // c-basic-offset: 4
287 // c-hanging-comment-ender-p: nil
288 // indent-tabs-mode: nil
289 // End:
290 ?>