1<?php 2/** 3 * Task Plugin, task component: Handles individual tasks on a wiki page 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Esther Brunner <wikidesign@gmail.com> 7 */ 8 9class syntax_plugin_task_task extends DokuWiki_Syntax_Plugin { 10 11 var $my = NULL; 12 var $task = array(); 13 14 function getType() { return 'substition'; } 15 function getSort() { return 305; } 16 function getPType() { return 'block';} 17 18 function connectTo($mode) { 19 $this->Lexer->addSpecialPattern('~~TASK.*?~~', $mode, 'plugin_task_task'); 20 } 21 22 function handle($match, $state, $pos, Doku_Handler $handler) { 23 global $ID; 24 global $INFO; 25 global $ACT; 26 global $REV; 27 28 // strip markup and split arguments 29 $match = substr($match, 6, -2); 30 $priority = strspn(strstr($match, '!'), '!'); 31 $match = trim($match, ':!'); 32 list($user, $date) = explode('?', $match); 33 34 if ($my =& plugin_load('helper', 'task')) { 35 $date = $my->_interpretDate($date); 36 37 $task = array( 38 'user' => array('name' => $user), 39 'date' => array('due' => $date), 40 'priority' => $priority 41 ); 42 43 // save task meta file if changes were made 44 // but only for already existing tasks, or when the page is saved 45 // $REV prevents overwriting current task information with old revision ones 46 if(@file_exists(metaFN($ID, '.task')) && $ACT != 'preview' && !$REV) { 47 $current = $my->readTask($ID); 48 if (($current['user']['name'] != $user) || ($current['date']['due'] != $date) || ($current['priority'] != $priority)) { 49 $my->writeTask($ID, $task); 50 } 51 } elseif ($ACT != 'preview' && !$REV) { 52 $my->writeTask($ID, $task); 53 } 54 } 55 return array($user, $date, $priority); 56 } 57 58 function render($mode, Doku_Renderer $renderer, $data) { 59 global $ID; 60 61 list($user, $date, $priority) = $data; 62 63 // XHTML output 64 if ($mode == 'xhtml') { 65 $renderer->nocache(); 66 67 // prepare data 68 $this->_loadHelper(); 69 70 $task = array(); 71 if(@file_exists(metaFN($ID, '.task'))) { 72 $task = $this->my->readTask($ID); 73 } 74 75 $status = $this->_getStatus($user, $sn); 76 $due = ''; 77 78 if ($date && ($sn < 3)) { 79 if ($date + 86400 < time()) $due = 'overdue'; 80 elseif ($date < time()) $due = 'due'; 81 } 82 83 $class = ' class="vtodo'; 84 if ($priority) $class .= ' priority' . $priority; 85 if ($due) { 86 $class .= ' '.$due; 87 $due = ' class="'.$due.'"'; 88 } 89 90 $class .= '"'; 91 92 // generate output 93 $renderer->doc .= '<div class="vcalendar">'.DOKU_LF 94 . '<fieldset'.$class.'>'.DOKU_LF 95 . '<legend>'.$this->_icsDownload().$this->getLang('task').'</legend>'.DOKU_LF 96 . '<table class="blind">'.DOKU_LF; 97 98 if ($user) { 99 $this->_tablerow('user', $this->_hCalUser($user), $renderer, '', 'organizer'); 100 } elseif ($task['user']['name']) { 101 $this->_tablerow('user', $this->_hCalUser($task['user']['name']), $renderer, '', 'organizer'); 102 } 103 104 if ($date) { 105 $this->_tablerow('date', $this->_hCalDate($date), $renderer, $due); 106 } elseif ($task['date']['due']) { 107 $this->_tablerow('date', $this->_hCalDate($task['date']['due']), $renderer, $due); 108 } 109 110 // show status update form only to logged in users 111 if(isset($_SERVER['REMOTE_USER'])) { 112 $this->_tablerow('status', $status, $renderer); 113 } 114 115 $renderer->doc .= '</table>'.DOKU_LF; 116 $renderer->doc .= '</fieldset>'.DOKU_LF. 117 '</div>'.DOKU_LF; 118 119 return true; 120 121 // for metadata renderer 122 } elseif ($mode == 'metadata') { 123 return true; 124 } 125 126 return false; 127 } 128 129 /** 130 * Outputs a table row 131 */ 132 function _tablerow($header, $data, &$renderer, $trclass = '', $tdclass = '') { 133 if ($tdclass) $tdclass = ' class="'.$tdclass.'"'; 134 135 $renderer->doc .= '<tr'.$trclass.'>'.DOKU_LF; 136 $renderer->tableheader_open(1, ''); 137 if ($header) $renderer->doc .= hsc($this->getLang($header)).':'; 138 $renderer->tableheader_close(); 139 $renderer->doc .= '<td'.$tdclass.'>'.$data; 140 $renderer->tablecell_close(); 141 $renderer->tablerow_close(); 142 } 143 144 /** 145 * Loads the helper plugin and gets task data for current ID 146 */ 147 function _loadHelper() { 148 global $ID; 149 $this->my =& plugin_load('helper', 'task'); 150 if (!is_object($this->my)) return false; 151 $this->task = $this->my->readTask($ID); 152 return $true; 153 } 154 155 /** 156 * Returns the status cell contents 157 */ 158 function _getStatus($user, &$status) { 159 global $INFO; 160 161 $ret = ''; 162 $status = $this->task['status']; 163 $responsible = $this->my->_isResponsible($user); 164 165 if ($INFO['perm'] == AUTH_ADMIN) { 166 $ret = $this->_statusMenu(array(-1, 0, 1, 2, 3, 4), $status); 167 } elseif ($responsible) { 168 if ($status < 3) $ret = $this->_statusMenu(array(-1, 0, 1, 2, 3), $status); 169 } else { 170 if ($status == 0) { 171 $ret = $this->_statusMenu(array(0, 1), $status); 172 } elseif ($status == 3) { 173 $ret = $this->_statusMenu(array(2, 3, 4), $status); 174 } 175 } 176 177 if (!$ret && $this->my) $ret = $this->my->statusLabel($status); 178 179 return '<abbr class="status" title="'.$this->my->_vstatus($status).'">'. $ret .'</abbr>'; 180 } 181 182 /** 183 * Returns the XHTML for the status drop down list. 184 * Just forwards call to the old or new function. 185 */ 186 function _statusMenu($options, $status) { 187 if (class_exists('dokuwiki\Form\Form')) { 188 return $this->_statusMenuNew($options, $status); 189 } else { 190 return $this->_statusMenuOld($options, $status); 191 } 192 } 193 194 /** 195 * Returns the XHTML for the status popup menu. 196 * This is the new version using class dokuwiki\Form\Form. 197 * 198 * @see _statusMenu 199 */ 200 function _statusMenuNew($options, $status) { 201 global $ID, $lang; 202 203 $form = new dokuwiki\Form\Form(array('id' => 'task__changetask_form')); 204 $pos = 1; 205 206 $form->addHTML('<div class="no">', $pos++); 207 208 // Set hidden fields 209 $form->setHiddenField ('id', $ID); 210 $form->setHiddenField ('do', 'changetask'); 211 212 // Select status from drop down list 213 $dropDownOptions = array(); 214 $selected = NULL; 215 $value = 0; 216 foreach ($options as $option) { 217 if ($status == $option) { 218 $selected = $option.' '; 219 } 220 $dropDownOptions [$option.' '] = $this->my->statusLabel($option); 221 } 222 $input = $form->addDropdown('status', $dropDownOptions, NULL, $pos++); 223 $input->val($selected); 224 225 // Add button 226 $form->addButton(NULL, $this->getLang('btn_change'), $pos++); 227 228 $form->addHTML('</div>', $pos++); 229 230 return $form->toHTML(); 231 } 232 233 /** 234 * Returns the XHTML for the status popup menu. 235 * Old function generating all HTML on its own. 236 * 237 * @see _statusMenu 238 */ 239 function _statusMenuOld($options, $status) { 240 global $ID; 241 global $lang; 242 243 $ret = '<form id="task__changetask_form" method="post" action="'.script().'" accept-charset="'.$lang['encoding'].'">'; 244 $ret .= '<div class="no">'; 245 $ret .= '<input type="hidden" name="id" value="'.$ID.'" />'; 246 $ret .= '<input type="hidden" name="do" value="changetask" />'; 247 $ret .= '<select name="status" size="1" class="edit">'; 248 249 foreach ($options as $option) { 250 $ret .= '<option value="'.$option.'"'; 251 if ($status == $option) $ret .= ' selected="selected"'; 252 $ret .= '>'.$this->my->statusLabel($option).'</option>'; 253 } 254 255 $ret .= '</select>'; 256 $ret .= '<input class="button" type="submit" value="'.$this->getLang('btn_change').'" />'; 257 $ret .= '</div>'; 258 $ret .= '</form>'.DOKU_LF; 259 260 return $ret; 261 } 262 263 /** 264 * Returns the download link for the iCal file 265 */ 266 function _icsDownload() { 267 global $ID; 268 global $INFO; 269 270 $uid = hsc($ID.'@'.$_SERVER['SERVER_NAME']); 271 $title = hsc($INFO['meta']['title']); 272 $link = DOKU_BASE.'lib/plugins/task/ics.php?id='.$ID; 273 $src = DOKU_BASE.'lib/plugins/task/images/ics.gif'; 274 275 $out = '<a href="'.$link.'" class="uid" title="'.$uid.'">' 276 . '<img src="'.$src.'" class="summary" alt="'.$title.'" title="'.$title.'" width="16" height="16"/>' 277 . '</a> '; 278 279 return $out; 280 } 281 282 /** 283 * Returns the organizer in hCalendar format as hCard 284 */ 285 function _hCalUser($user) { 286 return '<span class="vcard"><span class="fn">' . hsc($user) . '</span></span>'; 287 } 288 289 /** 290 * Returns the date in hCalendar format 291 */ 292 function _hCalDate($date) { 293 global $conf; 294 295 // strip time from preferred date format 296 $onlydate = preg_replace('#%[HIMprRST]|:#', '', ($conf['dformat'])); 297 298 return '<abbr class="due" title="'.$this->my->_vdate($date, true).'">' . strftime($onlydate, $date) . '</abbr>'; 299 } 300} 301// vim:ts=4:sw=4:et:enc=utf-8: 302