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('<', '<', $user); 133 $user = str_replace('>', '>', $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 = ' '; 194 } else { 195 $class = 'notokay'; 196 $title = ' '; 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> </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