1<?php 2/** 3 * Poll Plugin: allows to create simple polls 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Esther Brunner <wikidesign@gmail.com> 7 */ 8 9if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 11require_once(DOKU_PLUGIN.'syntax.php'); 12 13/** 14 * All DokuWiki plugins to extend the parser/rendering mechanism 15 * need to inherit from this class 16 */ 17class syntax_plugin_poll extends DokuWiki_Syntax_Plugin { 18 19 function getType() { return 'substition';} 20 function getPType() { return 'block';} 21 function getSort() { return 167; } 22 23 /** 24 * Connect pattern to lexer 25 */ 26 function connectTo($mode) { 27 $this->Lexer->addSpecialPattern('<poll.*?>.+?</poll>', $mode, 'plugin_poll'); 28 } 29 30 /** 31 * Handle the match 32 */ 33 function handle($match, $state, $pos, Doku_Handler $handler) { 34 $match = substr($match, 6, -7); // strip markup 35 list($title, $options) = preg_split('/>/u', $match, 2); 36 if (!$options) { 37 $options = $title; 38 $title = NULL; 39 } 40 $options = explode('*', $options); 41 42 $c = count($options); 43 for ($i = 0; $i < $c; $i++) { 44 $options[$i] = trim($options[$i]); 45 } 46 47 return array(trim($title), $options); 48 } 49 50 /** 51 * Create output 52 */ 53 function render($mode, Doku_Renderer $renderer, $data) { 54 55 if ($mode == 'xhtml') { 56 global $ID; 57 58 $options = $data[1]; 59 $title = $renderer->_xmlEntities($data[0]); 60 61 // prevent caching to ensure the poll results are fresh 62 $renderer->info['cache'] = false; 63 64 // get poll file contents 65 $pfile = metaFN(md5($title), '.poll'); 66 $poll = unserialize(@file_get_contents($pfile)); 67 68 // output the poll 69 $renderer->doc .= '<fieldset class="poll">'. 70 '<legend>'.$title.'</legend>'; 71 $more = trim(array_shift($options)); 72 if ($more) { 73 $renderer->doc .= '<div>'.$renderer->_xmlEntities($more).'</div>'; 74 } 75 76 // check if user has voted already 77 $ip = clientIP(true); 78 if (isset($poll['ips']) && in_array($ip, $poll['ips'])) { 79 80 // display results 81 $renderer->doc .= $this->_pollResults($poll); 82 83 } elseif ($vote = $_REQUEST['vote']) { 84 85 // user has just voted -> update results 86 $c = count($options); 87 for ($i = 0; $i < $c; $i++) { 88 $opt = $renderer->_xmlEntities($options[$i]); 89 if ($vote == $opt) { 90 $poll['results'][$opt] += 1; 91 $poll['votes'] += 1; 92 $poll['ips'][] = $ip; 93 } elseif (!isset($poll['results'][$opt])) { 94 $poll['results'][$opt] = 0; 95 } 96 } 97 $fh = fopen($pfile, 'w'); 98 fwrite($fh, serialize($poll)); 99 fclose($fh); 100 101 // display results 102 $renderer->doc .= $this->_pollResults($poll); 103 104 } elseif (count($options) > 0) { 105 106 // display poll form 107 $renderer->doc .= $this->_pollForm($options, $renderer); 108 109 } else { 110 111 // display results 112 $renderer->doc .= $this->_pollResults($poll); 113 114 } 115 $renderer->doc .= '</fieldset>'; 116 117 return true; 118 } 119 return false; 120 } 121 122 function _pollResults($poll) { 123 $total = $poll['votes']; 124 if ($total == 0) return ''; 125 126 $ret = '<table class="blind">'; 127 $c = count($poll['results']); 128 $options = array_keys($poll['results']); 129 $votes = array_values($poll['results']); 130 for ($i = 0; $i < $c; $i++) { 131 $absolute = $votes[$i]; 132 $percent = round(($absolute*100)/$total); 133 $ret .= '<tr><td>'.$options[$i].'</td><td><div class="poll_bar">'; 134 if ($percent) $ret .= '<div class="poll_full" style="width:'.($percent*2).'px"> </div>'; 135 $ret .= '</div></td><td class="rightalign">'.$percent.'%</td>'. 136 '<td class="rightalign">('.$absolute.')</td></tr>'; 137 } 138 $ret .= '</table>'; 139 140 return $ret; 141 } 142 143 function _pollForm($options, &$renderer) { 144 global $lang; 145 global $ID; 146 147 $i = 0; 148 $ret = '<form id="poll__form" method="post" action="'.script().'" accept-charset="'.$lang['encoding'].'"><div class="no">'. 149 '<input type="hidden" name="do" value="show" />'. 150 '<input type="hidden" name="id" value="'.$ID.'" />'; 151 foreach ($options as $option) { 152 $i++; 153 $option = $renderer->_xmlEntities($option); 154 $ret.= '<label class="simple" for="poll__option'.$i.'">'. 155 '<input type="radio" name="vote" id="poll__option'.$i.'" '. 156 'value="'.$option.'" /> <span>'.$option.'</span></label>'; 157 } 158 $ret .= '<input class="button" type="submit" '. 159 'value="'.$this->getLang('btn_vote').'" />'. 160 '</div></form>'; 161 162 return $ret; 163 } 164} 165// vim:ts=4:sw=4:et:enc=utf-8: 166