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