1<?php 2/** 3 * Timetrack Plugin 4 * 5 * @author peterfromearth <coder@peterfromearth.de> 6 * @package dokuwiki\plugin\timetrack 7 * 8 */ 9 10if(!defined('DOKU_INC')) die(); 11 12/** 13 * handles all the editor related things 14 * 15 * like displaying the editor and adding custom edit buttons 16*/ 17class syntax_plugin_timetrack extends DokuWiki_Syntax_Plugin { 18 19 /** 20 * @var helper_plugin_timetrack will hold the timetrack helper plugin 21 */ 22 public $tthlp = null; 23 24 /** 25 * Constructor. Load helper plugin 26 */ 27 function __construct() { 28 $this->tthlp = plugin_load('helper', 'timetrack'); 29 if(!$this->tthlp) msg('Loading the timetrack helper failed. Make sure the timetrack plugin is installed.', -1); 30 } 31 32 public function getType() { return 'substition'; } 33 public function getSort() { return 200; } 34 35 function connectTo($mode) { 36 $this->Lexer->addSpecialPattern('\{\{timetrack>?.*?\}\}',$mode,'plugin_timetrack'); 37 } 38 39 function handle($match, $state, $pos, Doku_Handler $handler) { 40 global $ID; 41 if($namespace = trim($this->getConf('namespace_allowed'))) { 42 if($this->tthlp->checkPageInNamespace($ID,$namespace) === false) return false; 43 } 44 $command = trim(substr($match, 11 ,-2),'> '); 45 $flags = explode('&', $command); 46 $flags = array_map('trim', $flags); 47 $flags = array_filter($flags); 48 49 $flags = $this->parseFlags($flags); 50 51 $data = array( 52 'flags' => $flags, 53 ); 54 55 return $data; 56 } 57 58 function render($mode, Doku_Renderer $r, $data) { 59 global $ID; 60 global $INFO; 61 $flags = $data['flags']; 62 63 if(!$this->tthlp->ready()) { 64 msg('DB not ready.', -1); 65 return false; 66 } 67 68 69 70 $project_name = $flags['project']['name'] ? $flags['project']['name'] : p_get_first_heading($ID); 71 $project_abbr = $flags['project']['id'] ? $flags['project']['id'] : noNS($ID); 72 if(!$project_name) $project_name = noNS($ID); 73 74 75 // $data is what the function handle return'ed. 76 if($mode === 'xhtml'){ 77 78 $project_id = $this->tthlp->getProject($ID, $project_abbr); 79 if(!$project_id) return false; 80 81 $range = $this->tthlp->getMinMaxDayByProject($project_id); 82 $data = $this->tthlp->getProjectSumByWeek($project_id); 83 84 $dateStart = new DateTime($range['min']); 85 $dateEnd = new DateTime($range['max']); 86 if($dateStart == $dateEnd) { 87 $dateEnd->add(new DateInterval('P1D')); 88 } 89 90 $dateStartCopy = clone $dateStart; 91 if($dateEnd <= $dateStartCopy->add(new DateInterval('P7D')) && $dateStart->format('W') !== $dateEnd->format('W')) { 92 $dateEnd->add(new DateInterval('P7D')); 93 } 94 95 $dateInterval = new DateInterval('P7D'); 96 97 $datePeriod = new DatePeriod($dateStart,$dateInterval,$dateEnd); 98 99 100 $r->table_open(); 101 102 $r->tablerow_open(); 103 $r->tableheader_open(); 104 $r->doc .= $r->_xmlEntities($project_name); 105 $r->tableheader_close(); 106 foreach($datePeriod as $date) { 107 $week = $date->format("W"); 108 $content = ($last_year !== $date->format("Y")) ? $date->format("Y") . '/' : ''; 109 $content .= $week; 110 111 $r->tableheader_open(); 112 $r->doc .= $r->_xmlEntities($content); 113 $r->tableheader_close(); 114 115 $last_year = $date->format("Y"); 116 } 117 $r->tableheader_open(); 118 $r->doc .= $r->_xmlEntities($this->getLang('sum')); 119 $r->tableheader_close(); 120 $r->tablerow_close(); 121 122 $sum_date = array(); 123 $sum_task = array(); 124 125 foreach($data as $task_id=>$weekValues) { 126 $r->tablerow_open(); 127 $r->tableheader_open(); 128 $r->doc .= $r->_xmlEntities(reset($weekValues)['task_name']); 129 $r->tableheader_close(); 130 foreach($datePeriod as $date) { 131 $week = $date->format("YW"); 132 $r->tablecell_open(); 133 $cell = isset($weekValues[$week]['hours'])?(int)$weekValues[$week]['hours']:0; 134 $r->doc .= $r->_xmlEntities($cell); 135 $sum_date[$week] += $cell; 136 $sum_task[$task_id] += $cell; 137 $r->tablecell_close(); 138 } 139 140 $r->tableheader_open(); 141 $r->doc .= $r->_xmlEntities($sum_task[$task_id]); 142 $r->tableheader_close(); 143 144 $r->tablerow_close(); 145 } 146 147 //SUMS 148 if(count($data) > 1) { 149 $r->tablerow_open(); 150 $r->tableheader_open(); 151 $r->doc .= $r->_xmlEntities($this->getLang('sum')); 152 $r->tableheader_close(); 153 foreach($datePeriod as $date) { 154 $week = $date->format("YW"); 155 $r->tableheader_open(); 156 $r->doc .= $r->_xmlEntities($sum_date[$week]); 157 $r->tableheader_close(); 158 } 159 160 $r->tableheader_open(); 161 $r->doc .= $r->_xmlEntities(array_sum($sum_date)); 162 $r->tableheader_close(); 163 164 $r->tablerow_close(); 165 } 166 $r->table_close(); 167 168 p_set_metadata($ID, array( 169 'plugin_timetrack' => array( 170 'update_time'=>$this->tthlp->getMaxUpdateTime($ID) 171 ))); 172 173 return true; 174 } else if ($mode === 'metadata') { 175 $project_id = $this->tthlp->updateProject($ID, $project_abbr, $project_name,$flags['from'],$flags['to']); 176 if(!$project_id) return false; 177 178 179 foreach($flags['tasks'] as $task_id => $task_name) { 180 $this->tthlp->updateTask($project_id,$task_id,$task_name); 181 } 182 183 $this->tthlp->setActiveTasks($project_id,array_merge(array($project_abbr),array_keys($flags['tasks']))); 184 185 186 } 187 return false; 188 } 189 190 /* 191 * parseFlags checks for tagfilter flags and returns them as true/false 192 * @param $flags array 193 * @return array tagfilter flags 194 */ 195 function parseFlags($flags){ 196 if(!is_array($flags)) return false; 197 198 $conf = array( 199 'project' => array('id'=>'','name'=>''), 200 'tasks' => array(), 201 'from' => null, 202 'to' => null, 203 ); 204 foreach($flags as $k=>$flag) { 205 list($flag,$value) = explode('=',$flag,2); 206 switch($flag) { 207 case 'project': 208 $data = explode('=',$value,2); 209 if(count($data)!==2) { 210 $data[1] = $data[0]; 211 $data[0] = ''; 212 } 213 $conf['project']['id'] = $data[0]; 214 $conf['project']['name'] = $data[1]; 215 break; 216 case 'task': 217 $data = explode('=',$value,2); 218 if(count($data) != 2) continue; 219 $conf['tasks'][$data[0]] = $data[1]; 220 break; 221 case 'from': 222 case 'start': 223 $conf['from'] = strtotime($value); 224 break; 225 case 'to': 226 case 'end': 227 $conf['to'] = strtotime($value); 228 break; 229 } 230 } 231 232 return $conf; 233 } 234 235 236}