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}