xref: /plugin/davcal/syntax/table.php (revision b8265976447044920a0a086e71de1b1b2f6b7620)
1<?php
2/**
3 * DokuWiki Plugin DAVCal (Table Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Böhler <dev@aboehler.at>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
13require_once(DOKU_PLUGIN.'syntax.php');
14
15class syntax_plugin_davcal_table extends DokuWiki_Syntax_Plugin {
16
17    protected $hlp = null;
18
19    // Load the helper plugin
20    public function syntax_plugin_davcal_table() {
21        $this->hlp =& plugin_load('helper', 'davcal');
22    }
23
24
25    /**
26     * What kind of syntax are we?
27     */
28    function getType(){
29        return 'substition';
30    }
31
32    /**
33     * What about paragraphs?
34     */
35    function getPType(){
36        return 'normal';
37    }
38
39    /**
40     * Where to sort in?
41     */
42    function getSort(){
43        return 165;
44    }
45
46    /**
47     * Connect pattern to lexer
48     */
49    function connectTo($mode) {
50        $this->Lexer->addSpecialPattern('\{\{davcaltable>[^}]*\}\}',$mode,'plugin_davcal_table');
51    }
52
53    /**
54     * Handle the match
55     */
56    function handle($match, $state, $pos, Doku_Handler $handler){
57        global $ID;
58        $options = trim(substr($match,14,-2));
59        $options = explode(',', $options);
60
61        $data = array('id' => array(),
62                      'startdate' => 'today',
63                      'numdays' => 30,
64                      'startisend' => false,
65                      'dateformat' => 'Y-m-d H:i',
66                      'alldayformat' => 'Y-m-d',
67                      'onlystart' => false,
68                      'location' => true,
69                      'calname' => false,
70                      'sort' => 'desc',
71                      'timezone' => 'local'
72                      );
73        $lastid = $ID;
74
75        foreach($options as $option)
76        {
77            list($key, $val) = explode('=', $option);
78            $key = strtolower(trim($key));
79            $val = trim($val);
80            switch($key)
81            {
82                case 'id':
83                    $lastid = $val;
84                    if(!in_array($val, $data['id']))
85                        $data['id'][$val] = '#3a87ad';
86                break;
87                case 'onlystart':
88                    if(($val === 'on') || ($val === 'true'))
89                        $data['onlystart'] = true;
90                break;
91                case 'startisend':
92                    if(($val === 'on') || ($val === 'true'))
93                        $data['startisend'] = true;
94                break;
95                case 'timezone':
96                    $tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL);
97                    if(in_array($val, $tzlist) || $val === 'no')
98                        $data['timezone'] = $val;
99                    else
100                        msg($this->getLang('error_timezone_not_in_list'), -1);
101                break;
102                case 'nolocation':
103                    $data['location'] = false;
104                break;
105                case 'calname':
106                    $data['calname'] = true;
107                break;
108                default:
109                    $data[$key] = $val;
110            }
111        }
112
113        // Handle the default case when the user didn't enter a different ID
114        if(empty($data['id']))
115        {
116            $data['id'] = array($ID => '#3a87ad');
117        }
118
119        return $data;
120    }
121
122    private static function sort_events_asc($a, $b)
123    {
124        $from1 = new \DateTime($a['start']);
125        $from2 = new \DateTime($b['start']);
126        return $from2 < $from1;
127    }
128
129    private static function sort_events_desc($a, $b)
130    {
131        $from1 = new \DateTime($a['start']);
132        $from2 = new \DateTime($b['start']);
133        return $from1 < $from2;
134    }
135
136    /**
137     * Create output
138     */
139    function render($format, Doku_Renderer $R, $data) {
140        if($format == 'metadata')
141        {
142            $R->meta['plugin_davcal']['table'] = true;
143            return true;
144        }
145        if(($format != 'xhtml') && ($format != 'odt')) return false;
146        global $ID;
147
148        $events = array();
149        $from = $data['startdate'];
150        $toStr = null;
151
152        // Handle the various options to 'startDate'
153        if($from === 'today')
154        {
155            $from = new \DateTime();
156        }
157        elseif(strpos($from, 'today-') === 0)
158        {
159            $days = intval(str_replace('today-', '', $from));
160            $from = new \DateTime();
161            $from->sub(new \DateInterval('P'.$days.'D'));
162        }
163        elseif(strpos($from, 'today+') === 0)
164        {
165            $days = intval(str_replace('today+', '', $from));
166            $from = new \DateTime();
167            $from->add(new \DateInterval('P'.$days.'D'));
168        }
169        else
170        {
171            $from = new \DateTime($from);
172        }
173
174        // Handle the option 'startisend'
175        if($data['startisend'] === true)
176        {
177            if($data['numdays'] > 0)
178            {
179                $to = clone $from;
180                $to->sub(new \DateInterval('P'.$data['numdays'].'D'));
181                $fromStr = $to->format('Y-m-d');
182            }
183            else
184            {
185                $fromStr = null;
186            }
187            $toStr = $from->format('Y-m-d');
188        }
189        else
190        {
191            if($data['numdays'] > 0)
192            {
193                $to = clone $from;
194                $to->add(new \DateInterval('P'.$data['numdays'].'D'));
195                $toStr = $to->format('Y-m-d');
196            }
197            else
198            {
199                $toStr = null;
200            }
201            $fromStr = $from->format('Y-m-d');
202        }
203
204        // Support for timezone
205        $timezone = $data['timezone'];
206
207        // Filter events by user permissions
208        $userEvents = $this->hlp->filterCalendarPagesByUserPermission($data['id']);
209
210        // Fetch the events
211        foreach($userEvents as $calPage => $color)
212        {
213            $events = array_merge($events, $this->hlp->getEventsWithinDateRange($calPage,
214                                      $user, $fromStr, $toStr, $timezone));
215        }
216
217        // Sort the events
218        if($data['sort'] === 'desc')
219            usort($events, array("syntax_plugin_davcal_table", "sort_events_desc"));
220        else
221            usort($events, array("syntax_plugin_davcal_table", "sort_events_asc"));
222
223        // Create tabular output
224        $R->table_open();
225        $R->tablethead_open();
226        $R->tableheader_open();
227        $R->doc .= $data['onlystart'] ? hsc($this->getLang('at')) : hsc($this->getLang('from'));
228        $R->tableheader_close();
229        if(!$data['onlystart'])
230        {
231            $R->tableheader_open();
232            $R->doc .= hsc($this->getLang('to'));
233            $R->tableheader_close();
234        }
235        $R->tableheader_open();
236        $R->doc .= hsc($this->getLang('title'));
237        $R->tableheader_close();
238        if($data['location'])
239        {
240            $R->tableheader_open();
241            $R->doc .= hsc($this->getLang('location'));
242            $R->tableheader_close();
243        }
244        if($data['calname'])
245        {
246            $R->tableheader_open();
247            $R->doc .= hsc($this->getLang('calendar'));
248            $R->tableheader_close();
249        }
250        $R->tableheader_open();
251        $R->doc .= hsc($this->getLang('description'));
252        $R->tableheader_close();
253        $R->tablethead_close();
254        foreach($events as $event)
255        {
256            $R->tablerow_open();
257            $R->tablecell_open();
258            $from = new \DateTime($event['start']);
259            if($timezone !== 'local')
260            {
261                $from->setTimezone(new \DateTimeZone($timezone));
262                $to->setTimezone(new \DateTimeZone($timezone));
263            }
264            if($event['allDay'] === true)
265                $R->doc .= $from->format($data['alldayformat']);
266            else
267                $R->doc .= $from->format($data['dateformat']);
268            $R->tablecell_close();
269            if(!$data['onlystart'])
270            {
271                $to = new \DateTime($event['end']);
272                // Fixup all day events, which have one day in excess
273                if($event['allDay'] === true)
274                {
275                    $to->sub(new \DateInterval('P1D'));
276                }
277                $R->tablecell_open();
278                if($event['allDay'] === true)
279                    $R->doc .= $to->format($data['alldayformat']);
280                else
281                    $R->doc .= $to->format($data['dateformat']);
282                $R->tablecell_close();
283            }
284            $R->tablecell_open();
285            $R->doc .= hsc($event['title']);
286            $R->tablecell_close();
287            if($data['location'])
288            {
289                $R->tablecell_open();
290                $R->doc .= hsc($event['location']);
291                $R->tablecell_close();
292            }
293			if($data['calname'])
294            {
295                $R->tablecell_open();
296                $R->doc .= hsc($event['calendarname']);
297                $R->tablecell_close();
298            }
299            $R->tablecell_open();
300            $R->doc .= hsc($event['description']);
301            $R->tablecell_close();
302            $R->tablerow_close();
303        }
304        $R->table_close();
305    }
306
307
308
309}
310
311// vim:ts=4:sw=4:et:enc=utf-8:
312