xref: /plugin/wikicalendar-ng/syntax.php (revision f04822b53689fa967819069be5b315ad125c35aa)
1<?php
2/**
3 * DokuWiki Syntax Plugin WikiCalendar-ng
4 *
5 * @license  GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Michael Klier <chi@chimeric.de>
7 * @edited Nick Spindler <n1ck@gmx.at>
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12require_once(DOKU_PLUGIN.'syntax.php');
13
14/**
15 * All DokuWiki plugins to extend the parser/rendering mechanism
16 * need to inherit from this class
17 */
18class syntax_plugin_wikicalendar extends DokuWiki_Syntax_Plugin {
19
20    /**
21     * namespace of the calendar
22     */
23    var $calendar_ns    = '';
24
25    /**
26     * namespace of the current viewed month
27     */
28    var $month_ns       = '';
29
30    /**
31     * indicator if first week of the month has been generated
32     */
33    var $firstWeek      = false;
34
35    /**
36     * array with localisations of weekdays
37     */
38    var $langDays       = array();
39
40    /**
41     * array with localistaions of month
42     */
43    var $langMonth      = array();
44
45    /**
46     * the current date
47     */
48    var $curDate        = array();
49
50    /**
51     * the month to show
52     */
53    var $showMonth      = '';
54
55    /**
56     * the year to show
57     */
58    var $showYear       = '';
59
60    /**
61     * the global timestamp for date-operations
62     */
63    var $gTimestamp     = '';
64
65    /**
66     * number days of the current month
67     */
68    var $numDays        = '';
69
70    /**
71     * date-date to generate the calendar
72     */
73    var $viewDate       = array();
74
75    /**
76     * return some info
77     */
78    function getInfo(){
79        return array(
80            'author' => 'Michael Klier (chi)',
81            'email'  => 'chi@chimeric.de',
82            'date'   => @file_get_contents(DOKU_PLUGIN.'wikicalendar/VERSION'),
83            'name'   => 'WikiCalendar Plugin',
84            'desc'   => 'Implements a simple Calendar with links to wikipages.',
85            'url'    => 'http://dokuwiki.org/plugin:wikicalendar'
86        );
87    }
88
89    /**
90     * Some Information first.
91     */
92    function getType() { return 'substition'; }
93    function getPType() { return 'block'; }
94    function getSort() { return 125; }
95
96    /**
97     * Connect pattern to lexer
98     */
99    function connectTo($mode) {
100        $this->Lexer->addSpecialPattern('{{cal>.+?}}',$mode,'plugin_wikicalendar');
101    }
102
103    /**
104     * Handle the match
105     */
106    function handle($match, $state, $pos, Doku_Handler $handler){
107        $match = substr($match,6,-2);
108        return array($match);
109    }
110
111    /**
112     * Create output
113     */
114    function render($mode, Doku_Renderer $renderer, $data) {
115        global $ID;
116        global $conf;
117
118        if($mode == 'xhtml'){
119
120            $tz = date_default_timezone_get();
121            if($this->getConf('timezone')) {
122                date_default_timezone_set($this->getConf('timezone'));
123            }
124
125            // define some variables first
126            $this->calendar_ns  = ($data[0]) ? $data[0] : $ID;
127            $this->langDays     = $this->getLang('days');
128            $this->langMonth    = $this->getLang('month');
129            $this->curDate      = getdate(time());
130            $requestMonth       = $_REQUEST['plugin_wikicalendar_month'] ?? null;
131            $requestYear        = $_REQUEST['plugin_wikicalendar_year'] ?? null;
132            $this->showMonth    = is_numeric($requestMonth) ? $requestMonth : $this->curDate['mon'];
133            $this->showYear     = is_numeric($requestYear) ? $requestYear : $this->curDate['year'];
134            $this->gTimestamp   = mktime(0,0,0,$this->showMonth,1,$this->showYear);
135            $this->numDays      = date('t',$this->gTimestamp);
136            $this->viewDate     = getdate($this->gTimestamp);
137            $this->today        = ($this->viewDate['mon'] == $this->curDate['mon'] &&
138                                   $this->viewDate['year'] == $this->curDate['year']) ?
139                                   $this->curDate['mday'] : null;
140
141            // if month directory exists we keep the old scheme
142            if(is_dir($conf['datadir'].'/'.str_replace(':','/',$this->calendar_ns.':'.$this->showYear.':'.$this->showMonth))) {
143                $this->month_ns = $this->calendar_ns.':'.$this->showYear.':'.$this->showMonth;
144            } else {
145                if($this->showMonth < 10) {
146                    $this->month_ns = $this->calendar_ns.':'.$this->showYear.':0'.$this->showMonth;
147                } else {
148                    $this->month_ns = $this->calendar_ns.':'.$this->showYear.':'.$this->showMonth;
149                }
150            }
151
152            $this->MonthStart = ($this->viewDate['wday'] == 0) ? 7 : $this->viewDate['wday'];
153            if($this->MonthStart == 7 && $this->getConf('weekstart') == 'Sunday') {
154                $this->MonthStart = 0;
155            }
156
157            // turn off caching
158            $renderer->info['cache'] = false;
159
160            $renderer->doc .= '<div class="plugin_wikicalendar">' . DOKU_LF;
161            $renderer->doc .= $this->_month_xhtml();
162            $renderer->doc .= $this->_form_go2();
163            $renderer->doc .= '</div>' . DOKU_LF;
164
165            date_default_timezone_set($tz);
166            return true;
167        }
168
169        return false;
170    }
171
172    /**
173     * Renders the Calendar (month-view)
174     *
175     * @author Michael Klier <chi@chimeric.de>
176     */
177    function _month_xhtml() {
178        global $ID;
179
180        $out = '';
181        $wd = 0;
182        $this->firstWeek = false;
183
184        $script = script();
185
186        $prevMonth  = ($this->showMonth-1 > 0)  ? ($this->showMonth-1) : 12;
187        $nextMonth  = ($this->showMonth+1 < 13) ? ($this->showMonth+1) : 1;
188
189        switch(true) {
190            case($prevMonth == 12):
191                $prevYear = ($this->showYear-1);
192                $nextYear = $this->showYear;
193                break;
194            case($nextMonth == 1):
195                $nextYear = ($this->showYear+1);
196                $prevYear = $this->showYear;
197                break;
198            default:
199                $prevYear = $this->showYear;
200                $nextYear = $this->showYear;
201                break;
202        }
203
204        // create calendar-header
205        $out .= <<<CALHEAD
206<table class="plugin_wikicalendar">
207  <tr>
208    <th class="month">
209      <form action="{$script}" method="post" class="prevnext">
210        <input type="hidden" name="id" value="{$ID}" />
211        <input type="hidden" name="plugin_wikicalendar_year" value="{$prevYear}" />
212        <input type="hidden" name="plugin_wikicalendar_month" value="{$prevMonth}" />
213        <input type="submit" class="btn_prev_month" name="submit" value="&larr;" accesskey="P" title="{$this->langMonth[$prevMonth]} {$prevYear}" />
214      </form>
215    </th>
216    <th class="blank">&nbsp;</th>
217    <th class="blank">&nbsp;</th>
218    <th class="month">{$this->langMonth[$this->viewDate['mon']]}<br />{$this->showYear}<br /></th>
219    <th class="blank">&nbsp;</th>
220    <th class="blank">&nbsp;</th>
221    <th class="month">
222      <form action="{$script}" method="post" class="prevnext">
223        <input type="hidden" name="id" value="{$ID}" />
224        <input type="hidden" name="plugin_wikicalendar_year" value="{$nextYear}" />
225        <input type="hidden" name="plugin_wikicalendar_month" value="{$nextMonth}" />
226        <input type="submit" class="btn_next_month" name="submit" value="&rarr;" accesskey="N" title="{$this->langMonth[$nextMonth]} {$nextYear}" />
227      </form>
228    </th>
229  </tr>
230CALHEAD;
231
232        // create calendar weekday-headers
233        $out .= "<tr>";
234        if($this->getConf('weekstart') == 'Sunday') {
235            $last = array_pop($this->langDays);
236            array_unshift($this->langDays, $last);
237        }
238        foreach($this->langDays as $day) {
239            $out .= '<td class="weekday">'.$day.'</td>';
240        }
241        $out .= "</tr>\n";
242
243        // create calendar-body
244        for($i=1;$i<=$this->numDays;$i++) {
245            $day = $i;
246            //set day-wikipage - use leading zeros on new pages
247            if($day < 10) {
248                if(page_exists($this->month_ns.':'.$day)) {
249                    $dayWP = $this->month_ns.':'.$day;
250                } else {
251                    $dayWP = $this->month_ns.':0'.$day;
252                }
253            } else {
254                $dayWP = $this->month_ns.':'.$day;
255            }
256            // close row at end of week
257            if($wd == 7) $out .= '</tr>';
258            // set weekday
259            if(!isset($wd) or $wd == 7) { $wd = 0; }
260            // start new row when new week starts
261            if($wd == 0) $out .= '<tr>';
262
263            // create blank fields up to the first day of the month
264            $offset = ($this->getConf('weekstart') == 'Sunday') ? 0 : 1;
265            if(!$this->firstWeek) {
266                while($wd < ($this->MonthStart - $offset)) {
267                    $out .= '<td class="blank">&nbsp;</td>';
268                    $wd++;
269                }
270                // ok - first week is printet
271                $this->firstWeek = true;
272            }
273
274            // check for today
275            if($this->today == $day) {
276                $out .= '<td class="today">'.$this->_calendar_day($dayWP,$day).'</td>';
277            } else {
278                $out .= '<td class="day">'.$this->_calendar_day($dayWP,$day).'</td>';
279            }
280
281            // fill remaining days with blanks
282            if($i == $this->numDays && $wd < 7) {
283                while($wd<7) {
284                    $out .= '<td class="blank">&nbsp;</td>';
285                    $wd++;
286                }
287                $out .= '</tr>';
288            }
289
290            // dont forget to count weekdays
291            $wd++;
292        }
293
294        // finally close the table
295        $out .= '</table>';
296
297        return ($out);
298    }
299
300    /**
301     * Generates the content of each day in the calendar-table.
302     *
303     * @author Michael Klier <chi@chimeric.de>
304     */
305    function _calendar_day($wp, $day) {
306        global $lang;
307        global $ID;
308        $out = '';
309
310        if(file_exists(wikiFN($wp))) {
311            $out .= '<div class="isevent">';
312            if(auth_quickaclcheck($wp) >= AUTH_READ) {
313                $out .= '<a href="' . wl($wp, array('do' => 'edit', 'plugin_wikicalendar_redirect_id' => $ID, 'plugin_wikicalendar_month' => $this->showMonth, 'plugin_wikicalendar_year' => $this->showYear)) . '" class="plugin_wikicalendar_btn" title="' . $lang['btn_edit'] . '"><img src="' . DOKU_BASE . 'lib/plugins/wikicalendar/img/edit01.png" alt="' . $lang['btn_edit'] . '" width="18" height="18" /></a>' . DOKU_LF;
314            }
315            $out .= '<div class="day_num"><a href="' . wl($wp) . '" class="wikilink1" title="' . $wp . '">'.$day.'</a></div>';
316            $out .= '<div class="abstract">' . p_get_metadata($wp, 'description abstract') . '</div>' . DOKU_LF;
317        } else {
318            $out .= '<div class="noevent">';
319            if(auth_quickaclcheck($wp) >= AUTH_CREATE) {
320                //$out .= $this->_btn_add_day($wp);
321                $out .= '<a href="' . wl($wp, array('do' => 'edit', 'plugin_wikicalendar_redirect_id' => $ID, 'plugin_wikicalendar_month' => $this->showMonth, 'plugin_wikicalendar_year' => $this->showYear)) . '" class="plugin_wikicalendar_btn" title="' . $lang['btn_create'] . '"><img src="' . DOKU_BASE . 'lib/plugins/wikicalendar/img/edit01.png" alt="' . $lang['btn_edit'] . '" width="18" height="18" /></a>' . DOKU_LF;
322            }
323            $out .= '<div class="day_num">'.$day.'</div>';
324        }
325        $out .= '</div>';
326        return ($out);
327    }
328
329    /**
330     * Generates a From to jump to selected dates
331     *
332     * @author Michael Klier <chi@chimeric.de>
333     */
334    function _form_go2() {
335        $out = '';
336        global $ID;
337
338        $out .= '<table class="inline plugin_wikicalendar_go2">' . DOKU_LF;
339
340        $out .= '<form action="'.script().'" method="post">' . DOKU_LF;
341        $out .= '<tr class="default">' . DOKU_LF;
342        $out .= '<td><label>'.$this->getLang('year').':</label></td>' . DOKU_LF;
343        $out .= '<td><div class="input">' . DOKU_LF;
344        $out .= '<select id="year" name="plugin_wikicalendar_year">' . DOKU_LF;
345
346        $year_start = ($this->showYear != $this->curDate['year']) ? $this->showYear - 10 : $this->curDate['year'] - 5;
347        $year_end   = $this->showYear + 10;
348
349        for($i=$year_start;$i<=$year_end;$i++) {
350            if($i == $this->showYear || $i == $this->curDate['year']) {
351                $out .= '<option value="'.$i.'" selected="selected">'.$i.'</option>' . DOKU_LF;
352            } else {
353                $out .= '<option value="'.$i.'">'.$i.'</option>' . DOKU_LF;
354            }
355        }
356
357        $out .= '</select>' . DOKU_LF;
358        $out .= '</div>' . DOKU_LF;
359        $out .= '</td>' . DOKU_LF;
360        $out .= '<td><label>'.$this->getLang('mon').':</label></td>' . DOKU_LF;
361        $out .= '<td><div class="input">' . DOKU_LF;
362        $out .= '<select id="month" name="plugin_wikicalendar_month">' . DOKU_LF;
363
364        for($i=1;$i<=12;$i++) {
365            if($i == $this->showMonth) {
366                $out .= '<option value="'.$i.'" selected="selected">'.$this->langMonth[$i].'</option>' . DOKU_LF;
367            } else {
368                $out .= '<option value="'.$i.'">'.$this->langMonth[$i].'</option>' . DOKU_LF;
369            }
370        }
371
372        $out .= '</select>' . DOKU_LF;
373        $out .= '</div>' . DOKU_LF;
374        $out .= '</td>' . DOKU_LF;
375        $out .= '<td><input type="hidden" name="id" value="'.$ID.'" />' . DOKU_LF;
376        $out .= '<input type="submit" class="button" name="go2" value="'.$this->getLang('go').'" />' . DOKU_LF;
377        $out .= '</form>' . DOKU_LF;
378
379        if($this->showYear != $this->curDate['year'] or $this->showMonth != $this->curDate['mon']) {
380            $out .= '<form action="'.script().'" method="post" class="go2" onsubmit="">' . DOKU_LF;
381            $out .= '<input type="hidden" name="id" value="'.$ID.'" />' . DOKU_LF;
382            $out .= '<input type="submit" class="button" name="back2cur" value="'.$this->getLang('current').'" />' . DOKU_LF;
383            $out .= '</form>' . DOKU_LF;
384        } else {
385            $out .= '</td></tr>' . DOKU_LF;
386        }
387
388        $out .= '</table>' . DOKU_LF;
389
390        return ($out);
391    }
392}
393//Setup Vim: tabstop=4 enc=utf8
394