1<?php
2/**
3 * Doodle Plugin: helps to schedule meetings
4 *
5 * @license	GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author	 Jonathan Tsai <tryweb@ichiayi.com>
7 * @previsou  author	 Esther Brunner <wikidesign@gmail.com>
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12require_once(DOKU_PLUGIN.'syntax.php');
13
14/**
15 * All DokuWiki plugins to extend the parser/rendering mechanism
16 * need to inherit from this class
17 */
18class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin {
19	/**
20	* return some info
21	*/
22  function getInfo(){
23	return array(
24		'author' => 'Jonathan Tsai',
25		'email'  => 'tryweb@ichiayi.com',
26		'date'   => '2009/08/10',
27		'name'   => 'Doodle Plugin',
28		'desc'   => 'helps to schedule meetings',
29		'url'	=> 'http://wiki.splitbrain.org/plugin:doodle',
30	);
31  }
32
33  function getType(){ return 'substition';}
34  function getPType(){ return 'block';}
35  function getSort(){ return 168; }
36
37	/**
38	* Connect pattern to lexer
39	*/
40  function connectTo($mode){
41	$this->Lexer->addSpecialPattern('<doodle.*?>.+?</doodle>', $mode, 'plugin_doodle');
42  }
43
44	/**
45	* Handle the match
46	*/
47  function handle($match, $state, $pos, Doku_Handler $handler){
48	$match = substr($match, 8, -9);  // strip markup
49	list($title, $options) = preg_split('/>/u', $match, 2);
50	list($leftstr, $rightstr) = explode ('\|', $title);
51	if ($rightstr == "") {
52		$title = $leftstr;
53		$disable = "";
54		$single = "";
55		$login = "";
56	}
57	else {
58		$title = $rightstr;
59		$disable = strpos($leftstr, "disable");
60		$single = strpos($leftstr, "single");
61		$login = strpos($leftstr, "login");
62	}
63	if (!$options){
64		$options = $title;
65		$title   = NULL;
66	}
67	$options = explode('^', $match);
68
69	$c = count($options);
70	for ($i = 0; $i < $c; $i++){
71		$options[$i] = trim($options[$i]);
72	}
73
74	return array(trim($title), $options, $disable, $single, $login);
75  }
76
77	/**
78	* Create output
79	*/
80  function render($mode, Doku_Renderer $renderer, $data) {
81	if ($mode == 'xhtml'){
82		global $lang;
83
84		$options = $data[1];
85		$c = count($options)-1;
86		$title   = $renderer->_xmlEntities($data[0]);
87		$disable   = $renderer->_xmlEntities($data[2]);
88		$single   = $renderer->_xmlEntities($data[3]);
89		$login   = $renderer->_xmlEntities($data[4]);
90		$dID	 = md5($title);
91
92		// prevent caching to ensure the poll results are fresh
93		$renderer->info['cache'] = false;
94
95		// get doodle file contents
96		$dfile   = metaFN($dID, '.doodle');
97		$old_dfile   = metaFN(md5(cleanID($title)), '.doodle');
98		// rename old meta File
99		if (file_exists($old_dfile)) {
100			rename($old_dfile, $dfile);
101		}
102		$doodle  = unserialize(@file_get_contents($dfile));
103
104		if ($c == 0){
105			// no options given: reset the doodle
106			$doodle = NULL;
107		}
108
109		// output the doodle
110		$renderer->table_open();
111		if ($title){
112			$renderer->tablerow_open();
113			$renderer->tableheader_open($c);
114			$renderer->doc .= $title;
115			$renderer->tableheader_close();
116			$renderer->tablerow_close();
117		}
118		$renderer->tablerow_open();
119		$renderer->tableheader_open();
120		$renderer->doc .= $lang['fullname'];
121		$renderer->tableheader_close();
122		for ($i = 1; $i < $c; $i++){
123			$renderer->tableheader_open();
124			$renderer->doc .= $renderer->_xmlEntities($options[$i]);
125			$renderer->tableheader_close();
126		}
127		$renderer->tablerow_close();
128
129		if ($submit = $_REQUEST[$dID.'-submit']){
130			// user has just voted -> update results
131			$user = trim($_REQUEST['fullname']);
132			$user = str_replace('<', '&lt;', $user);
133			$user = str_replace('>', '&gt;', $user);
134			if (!empty($user)){
135				for ($i = 1; $i < $c; $i++){
136					$opt = md5($options[$i]);
137					$opt_old = $renderer->_xmlEntities($options[$i]);
138					if (isset($doodle[$user][$opt_old])) {
139						$doodle[$user][$opt_old] = false;
140					}
141					if ($_REQUEST[$dID.'-option'.$i]){
142						$doodle[$user][$opt] = true;
143					} else {
144						$doodle[$user][$opt] = false;
145					}
146				}
147				$doodle[$user]['time']=time();
148			}
149			$fh = fopen($dfile, 'w');
150			fwrite($fh, serialize($doodle));
151			fclose($fh);
152		}
153
154		// display results
155		if (is_array($doodle)) $renderer->doc .= $this->_doodleResults($doodle, $options);
156			// display entry form
157			if ($disable=="") {
158				$renderer->doc .= $this->_doodleForm($c, $dID, $doodle, $options, $login, $single);
159			}
160			$renderer->table_close();
161			return true;
162		}
163
164		return false;
165	}
166
167  function _doodleResults($doodle, $options){
168	$cuser = count($doodle);
169	if ($cuser < 1) return '';
170	$copt  = count($options)-1;
171	$users = array_keys($doodle);
172	$ret   = '';
173	$count = array();
174
175	// table okay / not okay
176	for ($i = 0; $i < $cuser; $i++){
177		$isChecked = 0;
178		$user = $users[$i];
179		$updTime = isset($doodle[$user]['time'])?date('Y-m-d H:i:s', $doodle[$user]['time']):'Okey';
180		$retTmp = '<tr><td class="rightalign">'.$user.'</td>';
181		for ($j = 1; $j < $copt; $j++){
182			$option = md5($options[$j]);
183			$option_old = $options[$j];
184			if ($doodle[$user][$option] || $doodle[$user][$option_old]){
185				$class = 'okay';
186				$title = '<img src="'.DOKU_BASE.'lib/images/success.png" title="'.
187				  $updTime.'" alt="'.$updTime.'" '.
188				  'width="16" height="16" />';
189				$count[$option] += 1;
190				$isChecked = 1;
191			} elseif (!isset($doodle[$user][$option]) && !isset($doodle[$user][$option_old])){
192				$class = 'centeralign';
193				$title = '&nbsp;';
194			} else {
195				$class = 'notokay';
196				$title = '&nbsp;';
197			}
198			$retTmp .= '<td class="'.$class.'">'.$title.'</td>';
199		}
200		$retTmp .= '</tr>';
201		$ret .= ($isChecked==1)?$retTmp:"";
202	}
203
204	// total count
205	$ret .= '<tr><td>&nbsp;</td>';
206	for ($j = 1; $j < $copt; $j++){
207		$option = md5($options[$j]);
208		$ret .= '<td class="centeralign">'.$count[$option].'</td>';
209	}
210	$ret .= '</tr>';
211
212	return $ret;
213  }
214
215  function _doodleForm($n, $dID, $doodle, $options, $login, $single){
216	global $lang;
217	global $ID;
218	global $INFO;
219
220	$user  = ($_SERVER['REMOTE_USER'] ? $INFO['userinfo']['name'] : '');
221	$count = array();
222
223	$ret = '<form id="doodle__form" method="post" action="'.script().
224		'" accept-charset="'.$lang['encoding'].'"><tr>'.
225		'<input type="hidden" name="do" value="show" />'.
226		'<input type="hidden" name="id" value="'.$ID.'" />';
227	if ($login=="") {
228		$ret .= '<td class="rightalign"><input type="text" name="fullname" '.'value="'.$user.'" /></td>';
229	}
230	else {
231		if ($user=="") {
232			return "";
233		}
234		$ret .= '<input type="hidden" name="fullname" value="'.$user.'" />'.'<td class="rightalign">'.$user.'</td>';
235	}
236	$i = 1;
237	while ($i < $n){
238		if (is_array($doodle)){
239			$option = md5($options[$i]);
240			$option_old = $options[$j];
241			if ($doodle[$user][$option] || $doodle[$user][$option_old]){
242				$checked = 'checked="checked" ';
243			} else {
244				$checked = ' ';
245			}
246		} else {
247			$checked = ' ';
248		}
249		$onclickstr = "";
250		if ($single!="") {
251			$onclickstr = 'onclick="javascript:';
252			for ($j=1;$j<$n;$j++) {
253				if ($j!=$i) {
254					$onclickstr .= 'form[\''.$dID.'-option'.$j.'\'].checked=false;';
255				}
256			}
257			$onclickstr .= '"';
258		}
259		$ret.= '<td class="centeralign"><input type="checkbox" '.
260			'name="'.$dID.'-option'.$i.'" value="1" '.$checked.' '.$onclickstr.'/></td>';
261		$i++;
262	}
263	$ret .= '</tr><tr><td class="centeralign" colspan="'.($n).'">'.
264		'<input class="button" type="submit" name="'.$dID.'-submit" '.
265		'value="'.$this->getLang('btn_submit').'" />'.
266		'</td></tr></form>';
267
268	return $ret;
269  }
270}
271
272?>
273