xref: /plugin/davcal/syntax/table.php (revision 4858fc45e42a316f3e67de7b942c5b2cadbd426f)
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, &$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                      'sort' => 'desc',
69                      'timezone' => 'local'
70                      );
71        $lastid = $ID;
72
73        foreach($options as $option)
74        {
75            list($key, $val) = explode('=', $option);
76            $key = strtolower(trim($key));
77            $val = trim($val);
78            switch($key)
79            {
80                case 'id':
81                    $lastid = $val;
82                    if(!in_array($val, $data['id']))
83                        $data['id'][$val] = '#3a87ad';
84                break;
85                case 'onlystart':
86                    if(($val === 'on') || ($val === 'true'))
87                        $data['onlystart'] = true;
88                break;
89                case 'startisend':
90                    if(($val === 'on') || ($val === 'true'))
91                        $data['startisend'] = true;
92                break;
93                case 'timezone':
94                    $tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL);
95                    if(in_array($val, $tzlist) || $val === 'no')
96                        $data['timezone'] = $val;
97                    else
98                        msg($this->getLang('error_timezone_not_in_list'), -1);
99                break;
100                default:
101                    $data[$key] = $val;
102            }
103        }
104
105        // Handle the default case when the user didn't enter a different ID
106        if(empty($data['id']))
107        {
108            $data['id'] = array($ID => '#3a87ad');
109        }
110
111        return $data;
112    }
113
114    private static function sort_events_asc($a, $b)
115    {
116        $from1 = new \DateTime($a['start']);
117        $from2 = new \DateTime($b['start']);
118        return $from2 < $from1;
119    }
120
121    private static function sort_events_desc($a, $b)
122    {
123        $from1 = new \DateTime($a['start']);
124        $from2 = new \DateTime($b['start']);
125        return $from1 < $from2;
126    }
127
128    /**
129     * Create output
130     */
131    function render($format, &$R, $data) {
132        if($format == 'metadata')
133        {
134            $R->meta['plugin_davcal']['table'] = true;
135            return true;
136        }
137        if(($format != 'xhtml') && ($format != 'odt')) return false;
138        global $ID;
139
140        $events = array();
141        $from = $data['startdate'];
142        $toStr = null;
143
144        // Handle the various options to 'startDate'
145        if($from === 'today')
146        {
147            $from = new \DateTime();
148        }
149        elseif(strpos($from, 'today-') === 0)
150        {
151            $days = intval(str_replace('today-', '', $from));
152            $from = new \DateTime();
153            $from->sub(new \DateInterval('P'.$days.'D'));
154        }
155        elseif(strpos($from, 'today+') === 0)
156        {
157            $days = intval(str_replace('today+', '', $from));
158            $from = new \DateTime();
159            $from->add(new \DateInterval('P'.$days.'D'));
160        }
161        else
162        {
163            $from = new \DateTime($from);
164        }
165
166        // Handle the option 'startisend'
167        if($data['startisend'] === true)
168        {
169            if($data['numdays'] > 0)
170            {
171                $to = clone $from;
172                $to->sub(new \DateInterval('P'.$data['numdays'].'D'));
173                $fromStr = $to->format('Y-m-d');
174            }
175            else
176            {
177                $fromStr = null;
178            }
179            $toStr = $from->format('Y-m-d');
180        }
181        else
182        {
183            if($data['numdays'] > 0)
184            {
185                $to = clone $from;
186                $to->add(new \DateInterval('P'.$data['numdays'].'D'));
187                $toStr = $to->format('Y-m-d');
188            }
189            else
190            {
191                $toStr = null;
192            }
193            $fromStr = $from->format('Y-m-d');
194        }
195
196        // Support for timezone
197        $timezone = $data['timezone'];
198
199        // Fetch the events
200        foreach($data['id'] as $calPage => $color)
201        {
202            $events = array_merge($events, $this->hlp->getEventsWithinDateRange($calPage,
203                                      $user, $fromStr, $toStr, $timezone));
204
205        }
206        // Sort the events
207        if($data['sort'] === 'desc')
208            usort($events, array("syntax_plugin_davcal_table", "sort_events_desc"));
209        else
210            usort($events, array("syntax_plugin_davcal_table", "sort_events_asc"));
211
212        // Create tabular output
213        $R->table_open();
214        $R->tablethead_open();
215        $R->tableheader_open();
216        $R->doc .= $data['onlystart'] ? $this->getLang('at') : $this->getLang('from');
217        $R->tableheader_close();
218        if(!$data['onlystart'])
219        {
220            $R->tableheader_open();
221            $R->doc .= $this->getLang('to');
222            $R->tableheader_close();
223        }
224        $R->tableheader_open();
225        $R->doc .= $this->getLang('title');
226        $R->tableheader_close();
227        $R->tableheader_open();
228        $R->doc .= $this->getLang('description');
229        $R->tableheader_close();
230        $R->tablethead_close();
231        foreach($events as $event)
232        {
233            $R->tablerow_open();
234            $R->tablecell_open();
235            $from = new \DateTime($event['start']);
236            if($timezone !== 'local')
237            {
238                $from->setTimezone($timezone);
239                $to->setTimezone($timezone);
240            }
241            if($event['allDay'] === true)
242                $R->doc .= $from->format($data['alldayformat']);
243            else
244                $R->doc .= $from->format($data['dateformat']);
245            $R->tablecell_close();
246            if(!$data['onlystart'])
247            {
248                $to = new \DateTime($event['end']);
249                // Fixup all day events, which have one day in excess
250                if($event['allDay'] === true)
251                {
252                    $to->sub(new \DateInterval('P1D'));
253                }
254                $R->tablecell_open();
255                if($event['allDay'] === true)
256                    $R->doc .= $to->format($data['alldayformat']);
257                else
258                    $R->doc .= $to->format($data['dateformat']);
259                $R->tablecell_close();
260            }
261            $R->tablecell_open();
262            $R->doc .= $event['title'];
263            $R->tablecell_close();
264            $R->tablecell_open();
265            $R->doc .= $event['description'];
266            $R->tablecell_close();
267            $R->tablerow_close();
268        }
269        $R->table_close();
270    }
271
272
273
274}
275
276// vim:ts=4:sw=4:et:enc=utf-8:
277