diff --git a/action.php b/action.php index f851d2d..61441e9 100644 --- a/action.php +++ b/action.php @@ -9,19 +9,18 @@ class action_plugin_task extends DokuWiki_Action_Plugin { /** * register the eventhandlers */ - function register(Doku_Event_Handler $contr) { - $contr->register_hook('ACTION_ACT_PREPROCESS', - 'BEFORE', - $this, - 'handle_act_preprocess', - array()); + public function register(Doku_Event_Handler $controller) { + $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleTaskActions', []); } /** * Checks if 'newentry' was given as action, if so we * do handle the event our self and no further checking takes place + * + * @param Doku_Event $event + * @param $param */ - function handle_act_preprocess(&$event, $param) { + public function handleTaskActions($event, $param) { if ($event->data != 'newtask' && $event->data != 'changetask') return; // we can handle it -> prevent others @@ -29,10 +28,10 @@ function handle_act_preprocess(&$event, $param) { switch($event->data) { case 'newtask': - $event->data = $this->_newTask(); + $event->data = $this->newTask(); break; case 'changetask': - $event->data = $this->_changeTask(); + $event->data = $this->changeTask(); break; } } @@ -40,12 +39,11 @@ function handle_act_preprocess(&$event, $param) { /** * Creates a new task page */ - function _newTask() { - global $ID; - global $INFO; + protected function newTask() { + global $ID, $INFO, $INPUT; - $ns = cleanID($_REQUEST['ns']); - $title = str_replace(':', '', $_REQUEST['title']); + $ns = cleanID($INPUT->post->str('ns')); + $title = str_replace(':', '', $INPUT->post->str('title')); $back = $ID; $ID = ($ns ? $ns.':' : '').cleanID($title); $INFO = pageinfo(); @@ -53,7 +51,7 @@ function _newTask() { // check if we are allowed to create this file if ($INFO['perm'] >= AUTH_CREATE) { - //check if locked by anyone - if not lock for my self + //check if locked by anyone - if not lock for my self if ($INFO['locked']) { return 'locked'; } else { @@ -64,12 +62,12 @@ function _newTask() { if (!@file_exists($INFO['filepath'])) { global $TEXT; - $user = $_REQUEST['user']; - $date = $_REQUEST['date']; - $priority = $_REQUEST['priority']; + $user = $INPUT->post->str('user'); + $date = $INPUT->post->str('date'); + $priority = $INPUT->post->str('priority'); // create wiki page - $data = array( + $data = [ 'id' => $ID, 'ns' => $ns, 'title' => $title, @@ -77,7 +75,7 @@ function _newTask() { 'priority' => $priority, 'user' => $user, 'date' => $date, - ); + ]; $TEXT = $this->_pageTemplate($data); return 'preview'; @@ -88,9 +86,20 @@ function _newTask() { return 'show'; } } - + /** * Adapted version of pageTemplate() function + * + * @param array $data with: + * 'id' => string page id, + * 'ns' => string namespace, + * 'user' => string user id, + * 'date' => string date Y-m-d, + * 'back' => string page id of page to go back to, + * 'title' => string page title, + * 'priority' => string zero to three exclamation marks(!) + * + * @return string raw wiki text */ function _pageTemplate($data) { global $INFO; @@ -99,7 +108,7 @@ function _pageTemplate($data) { $tpl = io_readFile(DOKU_PLUGIN.'task/_template.txt'); // standard replacements - $replace = array( + $replace = [ '@ID@' => $id, '@NS@' => $data['ns'], '@PAGE@' => strtr(noNS($id),'_',' '), @@ -107,7 +116,7 @@ function _pageTemplate($data) { '@NAME@' => $INFO['userinfo']['name'], '@MAIL@' => $INFO['userinfo']['mail'], '@DATE@' => $data['date'], - ); + ]; // additional replacements $replace['@BACK@'] = $data['back']; @@ -115,34 +124,32 @@ function _pageTemplate($data) { $replace['@PRIORITY@'] = $data['priority']; // tag if tag plugin is available - if ((@file_exists(DOKU_PLUGIN.'tag/syntax/tag.php')) && (!plugin_isdisabled('tag'))) { + if (!plugin_isdisabled('tag')) { $replace['@TAG@'] = "\n\n{{tag>}}"; } else { $replace['@TAG@'] = ''; } // discussion if discussion plugin is available - if ((@file_exists(DOKU_PLUGIN.'discussion/syntax/comments.php')) && (!plugin_isdisabled('discussion'))) { + if (!plugin_isdisabled('discussion')) { $replace['@DISCUSSION@'] = "~~DISCUSSION~~"; } else { $replace['@DISCUSSION@'] = ''; } // do the replace - $tpl = str_replace(array_keys($replace), array_values($replace), $tpl); - return $tpl; + return str_replace(array_keys($replace), array_values($replace), $tpl); } - + /** * Changes the status of a task */ - function _changeTask() { - global $ID; - global $INFO; + protected function changeTask() { + global $ID, $INFO, $INPUT; - $status = $_REQUEST['status']; + $status = $INPUT->post->int('status'); //TODO check if other default then 0? $status = trim($status); - if (!is_numeric($status) || ($status < -1) || ($status > 4)) { + if (!is_numeric($status) || $status < -1 || $status > 4) { //FIXME is_numeric not needed if ($this->getConf('show_error_msg')) { $message = $this->getLang('msg_rcvd_invalid_status'); $message = str_replace('%status%', $status, $message); @@ -152,8 +159,9 @@ function _changeTask() { } // load task data - if ($my =& plugin_load('helper', 'task')) { - $task = $my->readTask($ID); + /** @var helper_plugin_task $helper */ + if ($helper = $this->loadHelper('task', false)) { + $task = $helper->readTask($ID); } else { if ($this->getConf('show_error_msg')) { msg($this->getLang('msg_load_helper_failed'), -1); @@ -169,14 +177,14 @@ function _changeTask() { return 'show'; } - $responsible = $my->_isResponsible($task['user']['name']); + $responsible = $helper->isResponsible($task['user']['name']); // some additional checks if change not performed by an admin // FIXME error messages? if ($INFO['perm'] != AUTH_ADMIN) { // responsible person can't verify her / his own tasks - if ($responsible && ($status == 4)) { + if ($responsible && $status == 4) { if ($this->getConf('show_info_msg')) { msg ($this->getLang('msg_responsible_no_verify')); } @@ -195,7 +203,7 @@ function _changeTask() { // assign task to a user if (!$task['user']['name']) { // FIXME error message? - if (!$_SERVER['REMOTE_USER']) { + if (!$INPUT->server->has('REMOTE_USER')) { // no logged in user if ($this->getConf('show_info_msg')) { msg($this->getLang('msg_not_logged_in')); @@ -211,27 +219,26 @@ function _changeTask() { saveWikiText($ID, $new, $summary, true); // save as minor edit } - $task['user'] = array( - 'id' => $_SERVER['REMOTE_USER'], + $task['user'] = [ + 'id' => $INPUT->server->str('REMOTE_USER'), 'name' => $INFO['userinfo']['name'], 'mail' => $INFO['userinfo']['mail'], - ); + ]; } // save .task meta file and clear xhtml cache $oldstatus = $task['status']; $task['status'] = $status; - $my->writeTask($ID, $task); - $_REQUEST['purge'] = true; + $helper->writeTask($ID, $task); + $INPUT->set('purge', true); if ($this->getConf('show_success_msg')) { $message = $this->getLang('msg_status_changed'); - $message = str_replace('%status%', $my->statusLabel($status), $message); - $message = str_replace('%oldstatus%', $my->statusLabel($oldstatus), $message); + $message = str_replace('%status%', $helper->statusLabel($status), $message); + $message = str_replace('%oldstatus%', $helper->statusLabel($oldstatus), $message); msg($message, 1); } return 'show'; } } -// vim:ts=4:sw=4:et:enc=utf-8: diff --git a/helper.php b/helper.php index 9621f1f..f9ced9c 100644 --- a/helper.php +++ b/helper.php @@ -1,91 +1,116 @@ */ class helper_plugin_task extends DokuWiki_Plugin { - - function getMethods() { - $result = array(); - $result[] = array( + + public function getMethods() { + $result = []; + $result[] = [ 'name' => 'th', 'desc' => 'returns the header of the task column for pagelist', - 'return' => array('header' => 'string'), - ); - $result[] = array( + 'return' => ['header' => 'string'], + ]; + $result[] = [ 'name' => 'td', 'desc' => 'returns the status of the task', - 'params' => array('id' => 'string'), - 'return' => array('label' => 'string'), - ); - $result[] = array( + 'params' => ['id' => 'string'], + 'return' => ['label' => 'string'], + ]; + $result[] = [ 'name' => 'getTasks', 'desc' => 'get task pages, sorted by priority', - 'params' => array( + 'params' => [ 'namespace' => 'string', 'number (optional)' => 'integer', - 'filter (optional)' => 'string'), - 'return' => array('pages' => 'array'), - ); - $result[] = array( + 'filter (optional)' => 'string'], + 'return' => ['pages' => 'array'], + ]; + $result[] = [ 'name' => 'readTask', 'desc' => 'get a single task metafile', - 'params' => array('id' => 'string'), - 'return' => array('task on success, else false' => 'array, (boolean)'), - ); - $result[] = array( + 'params' => ['id' => 'string'], + 'return' => ['task on success, else false' => 'array, (boolean)'], + ]; + $result[] = [ 'name' => 'writeTask', 'desc' => 'save task metdata in a file', - 'params' => array( + 'params' => [ 'id' => 'string', - 'task' => 'array'), - 'return' => array('success' => 'boolean'), - ); - $result[] = array( + 'task' => 'array'], + 'return' => ['success' => 'boolean'], + ]; + $result[] = [ 'name' => 'statusLabel', 'desc' => 'returns the status label for a given integer', - 'params' => array('status' => 'integer'), - 'return' => array('label' => 'string'), - ); + 'params' => ['status' => 'integer'], + 'return' => ['label' => 'string'], + ]; return $result; } - + /** * Returns the column header for the Pagelist Plugin + * + * @return string header text, escaped by Pagelist */ - function th() { + public function th() { return $this->getLang('status'); } /** * Returns the status of the task + * + * Used by pagelist plugin for filling the cells of the table + * and in listing by the tagfilter + * + * @param string $id page id of row + * @return string html with escaped values */ - function td($id) { + public function td($id) { $task = $this->readTask($id); return $this->statusLabel($task['status']); } /** * Returns an array of task pages, sorted by priority + * + * @param string $ns only tasks from this namespace including its subnamespaces + * @param int|null $num max number of returned rows, null is all + * @param string $filter 'all', 'rejected', 'accepted', 'started', 'done', 'verified', 'my', 'new', 'due', 'overdue' + * @param string $user show task of given user FIXME not used?? + * @return array with the rows: + * string sortkey => [ + * 'id' => string page id, + * 'date' => int timestamp of due date, + * 'user' => string name of user, + * 'status' => string translated status + * 'priority' => int in range 0 to 4 + * 'perm' => int ACL permission + * 'file' => string .task metadata file + * 'exists' => true + * ] */ - function getTasks($ns, $num = NULL, $filter = '', $user = NULL) { - global $conf; - - if (!$filter) $filter = strtolower($_REQUEST['filter']); + public function getTasks($ns, $num = null, $filter = '', $user = null) { + global $conf, $INPUT; - require_once(DOKU_INC.'inc/search.php'); - - $dir = $conf['datadir'].($ns ? '/'.str_replace(':', '/', $ns): ''); + if (!$filter) { + $filter = strtolower($INPUT->str('filter')); + } // returns the list of pages in the given namespace and it's subspaces - $items = array(); - $opts = array(); + $items = []; + $opts = []; $ns = utf8_encodeFN(str_replace(':', '/', $ns)); search($items, $conf['datadir'], 'search_allpages', $opts, $ns); // add pages with comments to result - $result = array(); + $result = []; foreach ($items as $item) { $id = $item['id']; @@ -93,7 +118,7 @@ function getTasks($ns, $num = NULL, $filter = '', $user = NULL) { if (!$task = $this->readTask($id)) continue; $date = $task['date']['due']; - $responsible = $this->_isResponsible($task['user']); + $responsible = $this->isResponsible($task['user']); // Check status in detail if filter is not 'all' if ($filter != 'all') { @@ -114,24 +139,25 @@ function getTasks($ns, $num = NULL, $filter = '', $user = NULL) { if ($task['status'] != 4) continue; } else { // No pure status filter, skip done and closed tasks - if (($task['status'] < 0) || ($task['status'] > 2)) continue; + if ($task['status'] < 0 || $task['status'] > 2) continue; } } // skip other's tasks if filter is 'my' - if (($filter == 'my') && (!$responsible)) continue; + if ($filter == 'my' && !$responsible) continue; // skip assigned and not new tasks if filter is 'new' - if (($filter == 'new') && ($task['user']['name'] || ($task['status'] != 0))) continue; + if ($filter == 'new' && ($task['user']['name'] || $task['status'] != 0)) continue; - // filter is 'due' or 'overdue' - if (in_array($filter, array('due', 'overdue'))) { - if (!$date || ($date > time()) || ($task['status'] > 2)) continue; - elseif (($date + 86400 < time()) && ($filter == 'due')) continue; - elseif (($date + 86400 > time()) && ($filter == 'overdue')) continue; - } + // filter is 'due' or 'overdue' + if (in_array($filter, ['due', 'overdue'])) { + if (!$date || $date > time() || $task['status'] > 2) continue; + elseif ($date + 86400 < time() && $filter == 'due') continue; + elseif ($date + 86400 > time() && $filter == 'overdue') continue; + } + $perm = auth_quickaclcheck($id); - $result[$task['key']] = array( + $result[$task['key']] = [ 'id' => $id, 'date' => $date, 'user' => $task['user']['name'], @@ -140,69 +166,125 @@ function getTasks($ns, $num = NULL, $filter = '', $user = NULL) { 'perm' => $perm, 'file' => $task['file'], 'exists' => true, - ); + ]; } // finally sort by time of last comment krsort($result); - if (is_numeric($num)) $result = array_slice($result, 0, $num); + if (is_numeric($num)) { + $result = array_slice($result, 0, $num); + } return $result; } /** * Reads the .task metafile + * + * @param string $id page id + * @return array|false returns data array, otherwise false, + * with: + * 'date' => [ + * 'created' => int, + * 'modified' => int, + * 'due' => int, + * 'completed' => int + * ], + * 'user' => [ + * 'name' => ... + * ], + * 'file' => string, + * 'exists' => bool + * 'status' => int, + * 'priority' => string + * 'vtodo' => string vtodo for iCal file download, + * 'key' => string sortkey based at priority and creation date */ - function readTask($id) { + public function readTask($id) { $file = metaFN($id, '.task'); if (!@file_exists($file)) { + //old format? reset stored metadata and replace by .task metadata file $data = p_get_metadata($id, 'task'); if (is_array($data)) { - $data['date'] = array('due' => $data['date']); - $data['user'] = array('name' => $data['user']); - $meta = array('task' => NULL); - if ($this->writeTask($id, $data)) p_set_metadata($id, $meta); + $data['date'] = ['due' => $data['date']]; + $data['user'] = ['name' => $data['user']]; + $meta = ['task' => null]; + if ($this->writeTask($id, $data)) { + p_set_metadata($id, $meta); + } } } else { $data = unserialize(io_readFile($file, false)); } - if (!is_array($data) || empty($data)) return false; + if (!is_array($data) || empty($data)) { + return false; + } $data['file'] = $file; $data['exists'] = true; return $data; } /** - * Saves the .task metafile + * Saves provided data to the .task metafile + * + * @param string $id page id + * @param array $data with at least: + * 'file' => string, + * 'exists' => bool, + * 'date' => [ + * 'created' => int, + * 'modified' => int, + * 'due' => int, + * 'completed' => int + * ] or string due date (old?), + * 'user' => [ + * 'name' string + * ] or string name (old?), + * 'status' => int, + * 'priority' => string + * + * key created before storing: + * 'vtodo' => string vtodo for iCal file download, + * 'key' => string sortkey based at priority and creation date + * + * @return bool success? */ - function writeTask($id, $data) { - if (!is_array($data)) return false; - $file = ($data['file'] ? $data['file'] : metaFN($id, '.task')); + public function writeTask($id, $data) { + if (!is_array($data)) { + return false; + } + $file = ($data['file'] ?: metaFN($id, '.task')); // remove file and exists keys unset($data['file']); unset($data['exists']); // set creation or modification time - if (!is_array($data['date'])) $data['date'] = array('due' => $data['date']); + if (!is_array($data['date'])) { + //old format? + $data['date'] = ['due' => $data['date']]; + } if (!@file_exists($file) || !$data['date']['created']) { $data['date']['created'] = time(); } else { $data['date']['modified'] = time(); } - if (!is_array($data['user'])) $data['user'] = array('name' => $data['user']); + if (!is_array($data['user'])) { + //old format? + $data['user'] = ['name' => $data['user']]; + } if (!isset($data['status'])) { // make sure we don't overwrite status - $current = unserialize(io_readFile($file, false)); - $data['status'] = $current['status']; + $currentTask = unserialize(io_readFile($file, false)); + $data['status'] = $currentTask['status']; } elseif ($data['status'] == 3) { // set task completion time $data['date']['completed'] = time(); } // generate vtodo for iCal file download - $data['vtodo'] = $this->_vtodo($id, $data); + $data['vtodo'] = $this->vtodo($id, $data); // generate sortkey with priority and creation date $data['key'] = chr($data['priority'] + 97).(2000000000 - $data['date']['created']); @@ -211,14 +293,17 @@ function writeTask($id, $data) { $ok = io_saveFile($file, serialize($data)); // and finally notify users - $this->_notify($data); + $this->notify($data); return $ok; } /** * Returns the label of a status + * + * @param int $status + * @return string */ - function statusLabel($status) { + public function statusLabel($status) { switch ($status) { case -1: return $this->getLang('rejected'); @@ -237,8 +322,11 @@ function statusLabel($status) { /** * Returns the label of a priority + * + * @param int $priority + * @return string */ - function priorityLabel($priority) { + public function priorityLabel($priority) { switch ($priority) { case 1: return $this->getLang('medium'); @@ -252,14 +340,26 @@ function priorityLabel($priority) { } /** - * Is the given task assigned to the current user? + * Is the given task user assigned to the current logged-in user? + * + * @param string|array $user string name of user, or array with: + * 'id' => string, + * 'name' => string + * + * @return bool */ - function _isResponsible($user) { - global $INFO; + public function isResponsible($user) { + global $INFO, $INPUT; - if (!$user) return false; + if (!$user) { + return false; + } - if (isset($user['id']) && $user['id'] == $_SERVER['REMOTE_USER'] || isset($user['name']) && $user['name'] == $INFO['userinfo']['name'] || $user == $INFO['userinfo']['name']) { + if ( + isset($user['id']) && $user['id'] == $INPUT->server->str('REMOTE_USER') + || isset($user['name']) && $user['name'] == $INFO['userinfo']['name'] + || $user == $INFO['userinfo']['name'] //was old format? + ) { return true; } @@ -268,9 +368,14 @@ function _isResponsible($user) { /** * Interpret date with strtotime() + * + * @param string $str + * @return false|int|null timestamp or null */ - function _interpretDate($str) { - if (!$str) return NULL; + public function interpretDate($str) { + if (!$str) { + return null; + } // only year given -> time till end of year if (preg_match("/^\d{4}$/", $str)) { @@ -293,34 +398,41 @@ function _interpretDate($str) { // convert to UNIX time $date = strtotime($str); - if ($date === -1) $date = NULL; + if ($date === -1) { + $date = null; + } return $date; } /** * Sends a notify mail on new or changed task * - * @param array $task data array of the task + * @param array $task data array of the task * * @author Andreas Gohr * @author Esther Brunner */ - function _notify($task) { + protected function notify($task) { global $conf; global $ID; - if ((!$conf['subscribers']) && (!$conf['notify'])) return; //subscribers enabled? - $data = array('id' => $ID, 'addresslist' => '', 'self' => false); - trigger_event('COMMON_NOTIFY_ADDRESSLIST', $data, 'subscription_addresslist'); + //subscribers enabled? + if (!$conf['subscribers'] && !$conf['notify']) { + return; + } + $data = ['id' => $ID, 'addresslist' => '', 'self' => false]; + Event::createAndTrigger('COMMON_NOTIFY_ADDRESSLIST', $data, 'subscription_addresslist'); $bcc = $data['addresslist']; - if ((empty($bcc)) && (!$conf['notify'])) return; + if (empty($bcc) && !$conf['notify']) { + return; + } $to = $conf['notify']; $text = io_readFile($this->localFN('subscribermail')); $text = str_replace('@PAGE@', $ID, $text); $text = str_replace('@TITLE@', $conf['title'], $text); if(!empty($task['date']['due'])) { - $dformat = preg_replace('#%[HIMprRST]|:#', '', ($conf['dformat'])); + $dformat = preg_replace('#%[HIMprRST]|:#', '', $conf['dformat']); $text = str_replace('@DATE@', strftime($dformat, $task['date']['due']), $text); } else { $text = str_replace('@DATE@', '', $text); @@ -332,16 +444,23 @@ function _notify($task) { $text = str_replace('@DOKUWIKIURL@', DOKU_URL, $text); $subject = '['.$conf['title'].'] '; - if ($task['status'] == 0) $subject .= $this->getLang('mail_newtask'); - else $subject .= $this->getLang('mail_changedtask'); + if ($task['status'] == 0) { + $subject .= $this->getLang('mail_newtask'); + } else { + $subject .= $this->getLang('mail_changedtask'); + } - mail_send($to, $subject, $text, $conf['mailfrom'], '', $bcc); + mail_send($to, $subject, $text, $conf['mailfrom'], '', $bcc); //FIXME replace } /** * Generates a VTODO section for iCal file download + * + * @param string $id page id + * @param array $task data array of the task + * @return string */ - function _vtodo($id, $task) { + protected function vtodo($id, $task) { if (!defined('CRLF')) define('CRLF', "\r\n"); $meta = p_get_metadata($id); @@ -349,57 +468,79 @@ function _vtodo($id, $task) { $ret = 'BEGIN:VTODO'.CRLF. 'UID:'.$id.'@'.$_SERVER['SERVER_NAME'].CRLF. 'URL:'.wl($id, '', true, '&').CRLF. - 'SUMMARY:'.$this->_vsc($meta['title']).CRLF; - if ($meta['description']['abstract']) - $ret .= 'DESCRIPTION:'.$this->_vsc($meta['description']['abstract']).CRLF; - if ($meta['subject']) - $ret .= 'CATEGORIES:'.$this->_vcategories($meta['subject']).CRLF; - if ($task['date']['created']) - $ret .= 'CREATED:'.$this->_vdate($task['date']['created']).CRLF; - if ($task['date']['modified']) - $ret .= 'LAST-MODIFIED:'.$this->_vdate($task['date']['modified']).CRLF; - if ($task['date']['due']) - $ret .= 'DUE:'.$this->_vdate($task['date']['due']).CRLF; - if ($task['date']['completed']) - $ret .= 'COMPLETED:'.$this->_vdate($task['date']['completed']).CRLF; - if ($task['user']) $ret .= 'ORGANIZER;CN="'.$this->_vsc($task['user']['name']).'":'. - 'MAILTO:'.$task['user']['mail'].CRLF; - $ret .= 'STATUS:'.$this->_vstatus($task['status']).CRLF; - if (is_numeric($task['priority'])) - $ret .= 'PRIORITY:'.(7 - ($task['priority'] * 2)).CRLF; - $ret .= 'CLASS:'.$this->_vclass($id).CRLF. + 'SUMMARY:'.$this->vsc($meta['title']).CRLF; + if ($meta['description']['abstract']) { + $ret .= 'DESCRIPTION:' . $this->vsc($meta['description']['abstract']) . CRLF; + } + if ($meta['subject']) { + $ret .= 'CATEGORIES:' . $this->vcategories($meta['subject']) . CRLF; + } + if ($task['date']['created']) { + $ret .= 'CREATED:' . $this->vdate($task['date']['created']) . CRLF; + } + if ($task['date']['modified']) { + $ret .= 'LAST-MODIFIED:' . $this->vdate($task['date']['modified']) . CRLF; + } + if ($task['date']['due']) { + $ret .= 'DUE:' . $this->vdate($task['date']['due']) . CRLF; + } + if ($task['date']['completed']) { + $ret .= 'COMPLETED:' . $this->vdate($task['date']['completed']) . CRLF; + } + if ($task['user']) { + $ret .= 'ORGANIZER;CN="' . $this->vsc($task['user']['name']) . '":' . + 'MAILTO:' . $task['user']['mail'] . CRLF; + } + $ret .= 'STATUS:'.$this->vstatus($task['status']).CRLF; + if (is_numeric($task['priority'])) { + $ret .= 'PRIORITY:' . (7 - ($task['priority'] * 2)) . CRLF; + } + $ret .= 'CLASS:'.$this->vclass($id).CRLF. 'END:VTODO'.CRLF; return $ret; } /** * Encodes vCard / iCal special characters + * + * @param string|array $string + * @return array|string|string[] */ - function _vsc($string) { - $search = array("\\", ",", ";", "\n", "\r"); - $replace = array("\\\\", "\\,", "\\;", "\\n", "\\n"); + protected function vsc($string) { + $search = ["\\", ",", ";", "\n", "\r"]; + $replace = ["\\\\", "\\,", "\\;", "\\n", "\\n"]; return str_replace($search, $replace, $string); } /** * Generates YYYYMMDD"T"hhmmss"Z" UTC time date format (ISO 8601 / RFC 3339) + * + * @param int $date timestamp + * @param bool $extended other date format + * @return false|string */ - function _vdate($date, $extended = false) { - if ($extended) return strftime('%Y-%m-%dT%H:%M:%SZ', $date); - else return strftime('%Y%m%dT%H%M%SZ', $date); + public function vdate($date, $extended = false) { + if ($extended) { + return strftime('%Y-%m-%dT%H:%M:%SZ', $date); + } else { + return strftime('%Y%m%dT%H%M%SZ', $date); + } } /** * Returns VTODO status + * + * @param int $status + * @return string */ - function _vstatus($status) { + public function vstatus($status) { switch ($status) { case -1: return 'CANCELLED'; - case 1: + case 1: case 2: return 'IN-PROCESS'; - case 3: + case 3: case 4: return 'COMPLETED'; default: @@ -409,55 +550,64 @@ function _vstatus($status) { /** * Returns VTODO categories + * + * @param string|array $cat + * @return string */ - function _vcategories($cat) { - if (!is_array($cat)) $cat = explode(' ', $cat); - return join(',', $this->_vsc($cat)); + protected function vcategories($cat) { + if (!is_array($cat)) { + $cat = explode(' ', $cat); + } + return join(',', $this->vsc($cat)); } /** * Returns access classification for VTODO + * + * @param string $id page id + * @return string */ - function _vclass($id) { - global $USERINFO; // checks access rights for anonymous user - if (auth_aclcheck($id, '', $USERINFO['grps'])) return 'PUBLIC'; - else return 'PRIVATE'; + protected function vclass($id) { + if (auth_quickaclcheck($id) >= AUTH_READ) { + return 'PUBLIC'; + } else { + return 'PRIVATE'; + } } /** * Show the form to create a new task. * The function just forwards the call to the old or new function. - * + * * @param string $ns The DokuWiki namespace in which the new task * page shall be created * @param bool $selectUser If false then create a simple input line for the user field. * If true then create a drop down list. - * @param bool $selectUserGroup If not NULL and if $selectUser==true then the drop down list + * @param bool $selectUserGroup If not null and if $selectUser==true then the drop down list * for the user field will only show users who are members of * the user group given in $selectUserGroup. */ - function _newTaskForm($ns, $selectUser=false, $selectUserGroup=NULL) { + public function newTaskForm($ns, $selectUser=false, $selectUserGroup=null) { if (class_exists('dokuwiki\Form\Form')) { - return $this->_newTaskFormNew($ns, $selectUser, $selectUserGroup); + return $this->newTaskFormNew($ns, $selectUser, $selectUserGroup); } else { - return $this->_newTaskFormOld($ns, $selectUser, $selectUserGroup); + return $this->newTaskFormOld($ns, $selectUser, $selectUserGroup); } } /** * Show the form to create a new task. * This is the new version using class dokuwiki\Form\Form. - * - * @see _newTaskForm + * + * @see newTaskForm */ - protected function _newTaskFormNew($ns, $selectUser=false, $selectUserGroup=NULL) { + protected function newTaskFormNew($ns, $selectUser=false, $selectUserGroup=null) { global $ID, $lang, $INFO, $auth; - $form = new dokuwiki\Form\Form(array('id' => 'task__newtask_form')); - $pos = 1; + $form = new dokuwiki\Form\Form(['id' => 'task__newtask_form']); // Open fieldset - $form->addFieldsetOpen($this->getLang('newtask'), $pos++); + $form->addFieldsetOpen($this->getLang('newtask')); // Set hidden fields $form->setHiddenField ('id', $ID); @@ -465,60 +615,58 @@ protected function _newTaskFormNew($ns, $selectUser=false, $selectUserGroup=NULL $form->setHiddenField ('ns', $ns); // Set input filed for task title - $input = $form->addTextInput('title', NULL, $pos++); + $input = $form->addTextInput('title', null); $input->attr('id', 'task__newtask_title'); $input->attr('size', '40'); // Set input field for user (either text field or drop down box) - $form->addHTML('
'.$this->getLang('user').':', $pos++); + $form->addHTML('', $pos++); + $form->addHTML(''); // Field for due date if ($this->getConf('datefield')) { - $form->addHTML('', $pos++); + $form->addHTML(''); } // Select priority from drop down list $form->addHTML('', $pos++); + $form->addHTML(''); - $form->addHTML('
'.$this->getLang('user').':'); if(!$selectUser) { // Old way input field - $input = $form->addTextInput('user', NULL, $pos++); + $input = $form->addTextInput('user', null); $input->attr('value', hsc($INFO['userinfo']['name'])); } else { // Select user from drop down list - $filter = array(); + $filter = []; $filter['grps'] = $selectUserGroup; - $options = array(); + $options = []; if ($auth) { foreach ($auth->retrieveUsers(0, 0, $filter) as $curr_user) { $options [] = $curr_user['name']; } } - $input = $form->addDropdown('user', $options, NULL, $pos++); + $input = $form->addDropdown('user', $options, null); $input->val($INFO['userinfo']['name']); } - $form->addHTML('
'.$this->getLang('date').':', $pos++); - $input = $form->addTextInput('date', NULL, $pos++); + $form->addHTML('
'.$this->getLang('date').':'); + $input = $form->addTextInput('date', null); $input->attr('value', date('Y-m-d')); - $form->addHTML('
'.$this->getLang('priority').':'); - $filter = array(); - $filter['grps'] = $selectUserGroup; - $options = array(); + $options = []; $options [''] = $this->getLang('low'); $options ['!'] = $this->getLang('medium'); $options ['!!'] = $this->getLang('high'); $options ['!!!'] = $this->getLang('critical'); - $input = $form->addDropdown('priority', $options, NULL, $pos++); + $input = $form->addDropdown('priority', $options, null); $input->attr('size', '1'); $input->val($this->getLang('low')); - $form->addHTML('
', $pos++); + $form->addHTML('
'); // Add button - $form->addButton(NULL, $lang['btn_create'], $pos++); + $form->addButton(null, $lang['btn_create']); // Close fieldset - $form->addFieldsetClose($pos++); + $form->addFieldsetClose(); // Generate the HTML-Representation of the form $ret = '
'; @@ -531,10 +679,11 @@ protected function _newTaskFormNew($ns, $selectUser=false, $selectUserGroup=NULL /** * Show the form to create a new task. * This is the old version, creating all HTML code on its own. - * - * @see _newTaskForm + * + * @see newTaskForm + * @deprecated 2017-03-30 */ - protected function _newTaskFormOld($ns, $selectUser=false, $selectUserGroup=NULL) { + protected function newTaskFormOld($ns, $selectUser=false, $selectUserGroup=null) { global $ID, $lang, $INFO, $auth; $ret = '
'; @@ -556,7 +705,7 @@ protected function _newTaskFormOld($ns, $selectUser=false, $selectUserGroup=NULL $ret .= ''.$this->getLang('user').':'; $ret .= ''; $ret .= ''; $ret .= '
'; - $ret .= ''.DOKU_LF; + $ret .= ''; return $ret; } /** * Returns the download link for the iCal file + * + * @return string html of link */ - function _icsDownload() { - global $ID; - global $INFO; + protected function htmlIcsDownloadLink() { + global $ID, $INFO, $INPUT; - $uid = hsc($ID.'@'.$_SERVER['SERVER_NAME']); - $title = hsc($INFO['meta']['title']); + $uid = hsc($ID.'@'.$INPUT->server->str('SERVER_NAME')); + $title = hsc($INFO['meta']['title'] ?? ''); $link = DOKU_BASE.'lib/plugins/task/ics.php?id='.$ID; $src = DOKU_BASE.'lib/plugins/task/images/ics.gif'; - $out = '' + return '' . ''.$title.'' . ' '; - - return $out; } /** * Returns the organizer in hCalendar format as hCard + * + * @return string html */ - function _hCalUser($user) { + protected function htmlhCalUser($user) { return '' . hsc($user) . ''; } /** * Returns the date in hCalendar format + * + * @return string html */ - function _hCalDate($date) { + protected function htmlhCalDate($date) { global $conf; // strip time from preferred date format - $onlydate = preg_replace('#%[HIMprRST]|:#', '', ($conf['dformat'])); + $onlydateformat = preg_replace('#%[HIMprRST]|:#', '', $conf['dformat']); - return '' . strftime($onlydate, $date) . ''; + return '' . strftime($onlydateformat, $date) . ''; } } -// vim:ts=4:sw=4:et:enc=utf-8: diff --git a/syntax/taskform.php b/syntax/taskform.php index dc790a7..e078779 100644 --- a/syntax/taskform.php +++ b/syntax/taskform.php @@ -1,13 +1,16 @@ helper = plugin_load('helper', 'task'); } - function getType() { return 'substition'; } - function getPType() { return 'block'; } - function getSort() { return 306; } - - function connectTo($mode) { + public function getType() { return 'substition'; } + public function getPType() { return 'block'; } + public function getSort() { return 306; } + + public function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{task>form>.+?\}\}', $mode, 'plugin_task_taskform'); } - function handle($match, $state, $pos, Doku_Handler $handler) { + public function handle($match, $state, $pos, Doku_Handler $handler) { global $ID; // strip {{task>form> from start and }} from end $match = substr($match, 12, -2); - list($ns, $flags) = explode('&', $match, 2); + list($ns, $flags) = array_pad(explode('&', $match, 2), 2,''); $flags = explode('&', $flags); - if (($ns == '*') || ($ns == ':')) $ns = ''; - elseif ($ns == '.') $ns = getNS($ID); - else $ns = cleanID($ns); + if ($ns == '*' || $ns == ':') { + $ns = ''; + } elseif ($ns == '.') { + $ns = getNS($ID); + } else { + $ns = cleanID($ns); + } - $selectUserGroup = NULL; + $selectUserGroup = null; foreach ($flags as $flag) { if (substr($flag, 0, 16) == 'selectUserGroup=') { $selectUserGroup = substr($flag, 16); $selectUserGroup = trim($selectUserGroup, '"'); } } - return array($ns, $flags, $selectUserGroup); + return [$ns, $flags, $selectUserGroup]; } - function render($mode, Doku_Renderer $renderer, $data) { - if ($mode != 'xhtml') { - false; + public function render($format, Doku_Renderer $renderer, $data) { + if ($format != 'xhtml') { + return false; } list($ns, $flags, $selectUserGroup) = $data; $selectUser = in_array('selectUser', $flags); - if ($this->helper) $renderer->doc .= $this->helper->_newTaskForm($ns, $selectUser, $selectUserGroup); + if ($this->helper) { + $renderer->doc .= $this->helper->newTaskForm($ns, $selectUser, $selectUserGroup); + } return true; } } -// vim:et:ts=4:sw=4:enc=utf-8: diff --git a/syntax/tasks.php b/syntax/tasks.php index 4332749..4be461b 100644 --- a/syntax/tasks.php +++ b/syntax/tasks.php @@ -1,13 +1,14 @@ */ class syntax_plugin_task_tasks extends DokuWiki_Syntax_Plugin { - protected $helper = NULL; + /** @var helper_plugin_task */ + protected $helper = null; /** * Constructor. Loads helper plugin. @@ -16,49 +17,76 @@ public function __construct() { $this->helper = plugin_load('helper', 'task'); } - function getType() { return 'substition'; } - function getPType() { return 'block'; } - function getSort() { return 306; } - - function connectTo($mode) { + public function getType() { return 'substition'; } + public function getPType() { return 'block'; } + public function getSort() { return 306; } + + public function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{tasks>.+?\}\}', $mode, 'plugin_task_tasks'); } - function handle($match, $state, $pos, Doku_Handler $handler) { + /** + * @param string $match The text matched by the patterns + * @param int $state The lexer state for the match + * @param int $pos The character position of the matched text + * @param Doku_Handler $handler The Doku_Handler object + * @return array Return an array with all data you want to use in render, false don't add an instruction + */ + public function handle($match, $state, $pos, Doku_Handler $handler) { global $ID; $match = substr($match, 8, -2); // strip {{topic> from start and }} from end - list($match, $flags) = explode('&', $match, 2); + list($match, $flags) = array_pad(explode('&', $match, 2),2,''); $flags = explode('&', $flags); - list($match, $refine) = explode(' ', $match, 2); - list($ns, $filter) = explode('?', $match, 2); + list($match, $refine) = array_pad(explode(' ', $match, 2),2,''); + list($ns, $filter) = array_pad(explode('?', $match, 2),2,''); - if (($ns == '*') || ($ns == ':')) $ns = ''; - elseif ($ns == '.') $ns = getNS($ID); - else $ns = cleanID($ns); + if ($ns == '*' || $ns == ':') { + $ns = ''; + } elseif ($ns == '.') { + $ns = getNS($ID); + } else { + $ns = cleanID($ns); + } - return array($ns, $filter, $flags, $refine); + return [$ns, $filter, $flags, $refine]; } - function render($mode, Doku_Renderer $renderer, $data) { - global $conf; + /** + * @param string $format output format being rendered + * @param Doku_Renderer $renderer the current renderer object + * @param array $data data created by handler() + * @return bool rendered correctly? (however, returned value is not used at the moment) + */ + public function render($format, Doku_Renderer $renderer, $data) { + global $conf, $INPUT; list($ns, $filter, $flags, $refine) = $data; - if (!$filter || ($filter == 'select')) { + $select = false; + if (!$filter || $filter == 'select') { $select = true; - $filter = trim($_REQUEST['filter']); + $filter = trim($INPUT->str('filter')); } $filter = strtolower($filter); - $filters = $this->_viewFilters(); - if (!in_array($filter, $filters)) $filter = 'open'; - if(isset($_REQUEST['view_user'])) $user = $_REQUEST['view_user']; + $filters = $this->viewFilters(); + if (!in_array($filter, $filters)) { + $filter = 'open'; + } + $user = ''; //FIXME getTasks() does not use $user... + if($INPUT->has('view_user')) { + $user = $INPUT->str('view_user'); + } - if ($this->helper) $pages = $this->helper->getTasks($ns, NULL, $filter, $user); + $pages = []; + if ($this->helper) { + $pages = $this->helper->getTasks($ns, null, $filter, $user); + } // use tag refinements? if ($refine) { - if (plugin_isdisabled('tag') || (!$tag = plugin_load('helper', 'tag'))) { + /** @var helper_plugin_tag $tag */ + if (!$tag = $this->loadHelper('tag', false)) { msg('The Tag Plugin must be installed to use tag refinements.', -1); } else { $pages = $tag->tagRefine($pages, $refine); @@ -66,12 +94,18 @@ function render($mode, Doku_Renderer $renderer, $data) { } if(!$pages) { - if($mode != 'xhtml') return true; + if($format != 'xhtml') { + return true; + } $renderer->nocache(); - if($select) $renderer->doc .= $this->_viewMenu($filter); + if($select) { + $renderer->doc .= $this->viewMenu($filter); + } if(auth_quickaclcheck($ns.':*') >= AUTH_CREATE) { if(!in_array('noform', $flags)) { - if ($this->helper) $renderer->doc .= $this->helper->_newTaskForm($ns); + if ($this->helper) { + $renderer->doc .= $this->helper->newTaskForm($ns); + } } } return true; // nothing to display @@ -80,45 +114,67 @@ function render($mode, Doku_Renderer $renderer, $data) { // prepare pagination $c = count($pages); $perpage = ($conf['recent'] != 0) ? $conf['recent'] : 20; // prevent division by zero + $numOfPages = $currentPage = 1; if ($c > $perpage) { $numOfPages = ceil($c / $perpage); - $first = $_REQUEST['first']; - if (!is_numeric($first)) $first = 0; - $currentPage = round($first / $perpage) + 1; + $first = $INPUT->int('first'); + $currentPage = round($first / $perpage) + 1; //TODO check 14/20=0.7==>1, 1+1=2? $pages = array_slice($pages, $first, $perpage); } - if ($mode == 'xhtml') { + if ($format == 'xhtml') { // prevent caching to ensure content is always fresh $renderer->nocache(); // show form to create a new task? - $perm_create = (auth_quickaclcheck($ns.':*') >= AUTH_CREATE); - if($perm_create && ($this->getConf('tasks_formposition') == 'top')) { + $hasCreatePermission = auth_quickaclcheck($ns.':*') >= AUTH_CREATE; + if($hasCreatePermission && $this->getConf('tasks_formposition') == 'top') { if(!in_array('noform', $flags)) { - if ($this->helper) $renderer->doc .= $this->helper->_newTaskForm($ns); + if ($this->helper) { + $renderer->doc .= $this->helper->newTaskForm($ns); + } } } // let Pagelist Plugin do the work for us - if (plugin_isdisabled('pagelist') - || (!$pagelist = plugin_load('helper', 'pagelist'))) { + /** @var helper_plugin_pagelist $pagelist */ + if (!$pagelist = $this->loadHelper('pagelist', false)) { msg('The Pagelist Plugin must be installed for task lists.', -1); return false; } - // show view filter popup if not - if ($select) $renderer->doc .= $this->_viewMenu($filter); + // show view filter popup if not + if ($select) { + $renderer->doc .= $this->viewMenu($filter); + } // prepare pagelist columns - $pagelist->header['page'] = $this->getLang('task'); - $pagelist->header['date'] = str_replace(' ', ' ', $this->getLang('date')); - $pagelist->header['user'] = str_replace(' ', ' ', $this->getLang('user')); - $pagelist->column['date'] = $this->getConf('datefield'); - $pagelist->column['user'] = true; - $pagelist->setFlags($flags); - $pagelist->addColumn('task', 'status'); + /* @deprecated 2022-10-17 */ + if(method_exists($pagelist, 'setHeader')) { + //since 2022-10-17 some new methods are introduced + $pagelist->setHeader([ + 'page' => $this->getLang('task'), + 'date' => str_replace(' ', ' ', $this->getLang('date')), + 'user' => str_replace(' ', ' ', $this->getLang('user')) + ]); + $pagelist->modifyColumn('date', $this->getConf('datefield')); + $pagelist->modifyColumn('user', true); + $pagelist->addColumn('task', 'status'); + $pagelist->setFlags(['header']); //allow override via user provided flags + $pagelist->setFlags($flags); + } else { + //before 2022-10-17 + $pagelist->header['page'] = $this->getLang('task'); + $pagelist->header['date'] = str_replace(' ', ' ', $this->getLang('date')); + $pagelist->header['user'] = str_replace(' ', ' ', $this->getLang('user')); + $pagelist->column['date'] = $this->getConf('datefield'); + $pagelist->column['user'] = true; + $pagelist->setFlags(['header']); //allow override via user provided flags + $pagelist->setFlags($flags); + $pagelist->addColumn('task', 'status'); + } + // output list $pagelist->startList(); @@ -129,19 +185,20 @@ function render($mode, Doku_Renderer $renderer, $data) { $pagelist->addPage($page); } $renderer->doc .= $pagelist->finishList(); - $renderer->doc .= $this->_paginationLinks($numOfPages, $currentPage, $filter); + $renderer->doc .= $this->paginationLinks($numOfPages, $currentPage, $filter); // show form to create a new task? - if($perm_create && ($this->getConf('tasks_formposition') == 'bottom')) { + if($hasCreatePermission && ($this->getConf('tasks_formposition') == 'bottom')) { if(!in_array('noform', $flags)) { - if ($this->helper) $renderer->doc .= $this->helper->_newTaskForm($ns); + if ($this->helper) $renderer->doc .= $this->helper->newTaskForm($ns); } } return true; // for metadata renderer - } elseif ($mode == 'metadata') { + } elseif ($format == 'metadata') { + /** @var Doku_Renderer_metadata $renderer */ foreach ($pages as $page) { $renderer->meta['relation']['references'][$page['id']] = true; } @@ -150,33 +207,33 @@ function render($mode, Doku_Renderer $renderer, $data) { } return false; } - + /* ---------- (X)HTML Output Functions ---------- */ /** * Show a popup to select the task view filter. * Just forwards call to the old or new function. */ - function _viewMenu($filter) { + protected function viewMenu($filter) { if (class_exists('dokuwiki\Form\Form')) { - return $this->_viewMenuNew($filter); + return $this->viewMenuNew($filter); } else { - return $this->_viewMenuOld($filter); + return $this->viewMenuOld($filter); } } /** * Show a popup to select the task view filter. * This is the new version using class dokuwiki\Form\Form. - * - * @see _viewMenu + * + * @see viewMenu */ - function _viewMenuNew($filter) { - global $ID, $lang; + protected function viewMenuNew($filter) { + global $ID, $INPUT; - $options = $this->_viewFilters(); + $options = $this->viewFilters(); - $form = new dokuwiki\Form\Form(array('id' => 'task__changeview_form')); + $form = new dokuwiki\Form\Form(['id' => 'task__changeview_form']); $pos = 1; $form->addHTML('', $pos++); - if(isset($_SERVER['REMOTE_USER'])) { + if($INPUT->server->has('REMOTE_USER')) { $form->addHTML('', $pos++); } // Add button - $form->addButton(NULL, $this->getLang('btn_refresh'), $pos++); + $form->addButton(null, $this->getLang('btn_refresh'), $pos++); $ret = '
'; $ret .= $form->toHTML(); @@ -224,13 +280,13 @@ function _viewMenuNew($filter) { /** * Show a popup to select the task view filter. * Old function generating all HTML on its own. - * - * @see _viewMenu + * + * @see viewMenu */ - function _viewMenuOld($filter) { - global $ID, $lang; + protected function viewMenuOld($filter) { + global $ID, $lang, $INPUT; - $options = $this->_viewFilters(); + $options = $this->viewFilters(); $ret = '
'; $ret .= '
'; @@ -242,17 +298,19 @@ function _viewMenuOld($filter) { foreach ($options as $option) { $ret .= ''; } $ret .= ''; $ret .= ''; - if(isset($_SERVER['REMOTE_USER'])) { + if($INPUT->server->has('REMOTE_USER')) { $ret .= ''; } @@ -261,50 +319,60 @@ function _viewMenuOld($filter) { return $ret; } - + /** * Returns an array of available view filters for the task list */ - function _viewFilters() { - if (!$_SERVER['REMOTE_USER']) $filters = array('all', 'open', 'done'); - else $filters = array('all', 'open', 'new', 'done', 'my', 'rejected', 'started', 'accepted', 'verified'); + protected function viewFilters() { + global $INPUT; + if ($INPUT->server->has('REMOTE_USER')) { + $filters = ['all', 'open', 'new', 'done', 'my', 'rejected', 'started', 'accepted', 'verified']; + } else { + $filters = ['all', 'open', 'done']; + } if ($this->getConf('datefield')) { $filters[] = 'due'; $filters[] = 'overdue'; } return $filters; } - + /** - * Returns pagination links if more than one page - */ - function _paginationLinks($num, $cur, $filter) { - global $ID, $conf; + * Returns html of pagination links if more than one page + * + * @param int $num number of pagination pages + * @param int $cur current pagination page no + * @param string $filter current active filter + * @return string html of pagination links + */ + protected function paginationLinks($num, $cur, $filter) { + global $ID, $conf, $INPUT; - if (!is_numeric($num) || ($num < 2)) return ''; + if (!is_numeric($num) || $num < 2) { + return ''; + } $perpage = ($conf['recent'] != 0) ? $conf['recent'] : 20; // prevent division by zero - $ret = array(); + $ret = []; for ($i = 1; $i <= $num; $i++) { if ($i == $cur) { $ret[] = ''.$i.''; } else { - $opt = array(); - $opt['first'] = $perpage * ($i - 1); - $opt['filter'] = $filer; - if(isset($_REQUEST['view_user'])) { - $user = array(); - $user['id'] = $_REQUEST['view_user']; - if($this->helper->_isResponsible($user)) { - $opt['view_user'] = $_REQUEST['view_user']; + $param = []; + $param['first'] = $perpage * ($i - 1); + $param['filter'] = $filter; + if($INPUT->has('view_user')) { + $user = []; + $user['id'] = $INPUT->str('view_user'); + if($this->helper->isResponsible($user)) { + $param['view_user'] = $INPUT->str('view_user'); } } - $ret[] = ''.$i.''; + $ret[] = ''.$i.''; } } - return '
'.DOKU_LF. - join(' | ', $ret).DOKU_LF. - '
'.DOKU_LF; + return '
'. + join(' | ', $ret). + '
'; } } -// vim:et:ts=4:sw=4:enc=utf-8: