1<?php
2/**
3 * Date: Run the php command strftime or date.
4 * Usage:
5 * {{date>format}}
6 *
7 * Replacers are handled in a simple key/value pair method.
8 * {{date>format|key=val|key2=val|key3=val}}
9 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
10 * @author     Marcel Pietschmann <mpietsch@astro.physik.uni-potsdam.de>
11 * @version    1.20
12 */
13
14// must be run within DokuWiki
15if(!defined('DOKU_INC')) die();
16
17if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
18require_once(DOKU_PLUGIN.'syntax.php');
19
20/**
21 * All DokuWiki plugins to extend the parser/rendering mechanism
22 * need to inherit from this class
23 */
24class syntax_plugin_date extends DokuWiki_Syntax_Plugin {
25
26    /**
27     * What kind of syntax are we?
28     */
29
30     function getType() { return 'substition'; }
31
32     // function getAllowedTypes(){ return array('container','substition','protected','disabled','formatting'); }
33
34     /**
35     * Paragraph Type
36     */
37    // function getPType(){ return 'normal'; }
38    // function getAllowedTypes() { return array('substition','protected','disabled','formatting','container'); }
39
40    /**
41     * Where to sort in?
42     */
43    function getSort(){ return 195; }
44
45    /**
46     * Connect pattern to lexer
47     */
48    function connectTo($mode) {
49        $this->Lexer->addSpecialPattern('{{date>.+?}}',$mode,'plugin_date');
50        $this->Lexer->addSpecialPattern('{{date=.+?}}',$mode,'plugin_date');
51    }
52
53    /**
54     * Handle the match
55     */
56    function handle($match, $state, $pos, Doku_Handler $handler){
57		//strip strings for non-constant
58        if (strpos($match,'date>',2) !== false) {
59            // strip markup
60            $match = substr($match,7,-2);
61            // Get the key values pairs
62            $replacers = preg_split('/(?<!\\\\)\|/', $match);
63
64            // cut format key
65            $dataformat = array_shift($replacers);
66
67            // handle key=value
68            $replacers = $this->_GetKeyValues($replacers);
69
70            $cnst = null;
71        } else {
72            // strip markup for constanst
73            $cnst = substr($match, 7, -2);
74        }
75        return array($dataformat,$replacers,$cnst);
76    }
77
78    /**
79     * Create output
80     */
81    function render($mode, Doku_Renderer $renderer, $data) {
82        // for XHTML output
83        if ($mode == 'xhtml') {
84
85            // format for the output
86            $format = $data[0];
87
88            // Check if some keys are set -> array has length greater than 0
89            if (count($data[1]) > 0) {
90
91                // search the keys in array and get position in array
92                $timestamp_key = array_search("timestamp",$data[1]['keys']);
93                $now_key = array_search("now",$data[1]['keys']);
94                $locale_key = array_search("locale",$data[1]['keys']);
95                $mode_key = array_search("mode",$data[1]['keys']);
96                $cnst = FALSE;
97            } else {
98            // set FALSE values for correct going
99                $timestamp_key = FALSE;
100                $now_key = FALSE;
101                $locale_key = FALSE;
102                $mode_key = FALSE;
103                    if ($data[2] === '') {
104                        $cnst = FALSE;
105                    } else {
106                        $cnst = $data[2];
107                    }
108            }
109
110            // set locale LC_TIME setting, if some locale key is giving
111            if (!empty($locale_key)) {
112                // save actually settings
113                $localestore = setlocale(LC_TIME,"0");
114                // get values from array
115                $locale_value = $data[1]['vals'][$locale_key];
116                // set LC_TIME
117                setlocale(LC_TIME,$locale_value);
118            }
119
120            if ($mode_key !== false) {
121                // get value from array
122                $mode_value = $data[1]['vals'][$mode_key];
123            } else {
124                $mode_value = "strftime";
125            }
126
127            // check for the different possibilities
128            if ( $timestamp_key !== FALSE and $now_key !== FALSE and $cnst == FALSE ) {
129                // timestamp and now keys are set
130
131                // get values from array
132                $timestamp_value = $data[1]['vals'][$timestamp_key];
133                $now_value = $data[1]['vals'][$now_key];
134
135                // replace " with ' for correct eval
136                $timestamp_value = str_replace('"',"'",$timestamp_value);
137                $now_value = str_replace('"',"'",$now_value);
138
139                // check if in timestamp string the function strtotime is used
140                $pos = strpos($timestamp_value, "strtotime");
141                if ($pos === false) {
142                    // strtotime is not used, so don't use now value
143                    $timestamp_with_now_value = $timestamp_value;
144                } else {
145                    // // strtotime is used, so use now value
146                    $timestamp_with_now_value = substr($timestamp_value,0,strlen($timestamp_value)-1).", ".$now_value.substr($timestamp_value,-1);
147                }
148
149                // eval the timestamp string
150                eval ("\$timestamp_with_now_value = $timestamp_with_now_value;");
151
152                // do the magic date function
153                    if ($mode_value == "date") {
154                        $xhtml = date($format, $timestamp_with_now_value);
155                    } else {
156                        $xhtml = strftime($format, $timestamp_with_now_value);
157                    }
158
159            } else if ( $timestamp_key !== FALSE and $cnst == FALSE ) {
160                // only timestamp key is set
161
162                // get values from array
163                $timestamp_value = $data[1]['vals'][$timestamp_key];
164                // replace " witch ' for correct eval
165                $timestamp_value = str_replace('"',"'",$timestamp_value);
166                // eval the timestamp string
167                eval ("\$timestamp_value = $timestamp_value;");
168
169                // do the magic date function
170                if ($mode_value == "date") {
171                        $xhtml = date($format, $timestamp_value);
172                    } else {
173                        $xhtml = strftime($format, $timestamp_value);
174                    }
175
176            } else if ($cnst == FALSE) {
177                // no keys are set
178                // do the magic date function
179                if ($mode_value == "date") {
180                        $xhtml = date($format);
181                    } else {
182                        $xhtml = strftime($format);
183                    }
184            }
185
186            if ($cnst != FALSE) {
187                $dformat = $this->getConf('dpformat');
188                // handle with the constants
189				if ( strcasecmp($cnst,'today') == 0 ) {
190					$xhtml = strftime($dformat);
191				} else if ( strcasecmp($cnst,'tomorrow') == 0 ) {
192					$xhtml = strftime($dformat, strtotime("+1 day"));
193				} else if ( strcasecmp($cnst,'yesterday') == 0 ) {
194					$xhtml = strftime($dformat, strtotime("-1 day"));
195				} else if ( strcasecmp($cnst,'year') == 0 ) {
196					$xhtml = strftime('%Y');
197				} else if ( strcasecmp($cnst,'nyear') == 0 ) {
198					$xhtml = strftime('%Y',strtotime("+1 year"));;
199				} else if ( strcasecmp($cnst,'pyear') == 0 ) {
200					$xhtml = strftime('%Y',strtotime("-1 year"));
201				} else if ( strcasecmp($cnst,'month') == 0 ) {
202					$xhtml = strftime('%m');
203				} else if ( strcasecmp($cnst,'nmonth') == 0 ) {
204					$xhtml = strftime('%m',strtotime("+1 month"));
205				} else if ( strcasecmp($cnst,'pmonth') == 0 ) {
206					$xhtml = strftime('%m',strtotime("-1 month"));
207				} else if ( strcasecmp($cnst,'week') == 0 ) {
208					$xhtml = strftime('%W');
209				} else if ( strcasecmp($cnst,'nweek') == 0 ) {
210					$xhtml = strftime('%W',strtotime("+1 week"));
211				} else if ( strcasecmp($cnst,'pweek') == 0 ) {
212					$xhtml = strftime('%W',strtotime("-1 week"));
213				} else if ( strcasecmp($cnst,'dayofmonth') == 0 ) {
214					$xhtml = strftime('%d');
215				} else if ( strcasecmp($cnst,'dayofmonth2') == 0 ) {
216					$xhtml = strftime('%e');
217				} else if ( strcasecmp($cnst,'dayofyear') == 0 ) {
218					$xhtml = strftime('%j');
219				} else if ( strcasecmp($cnst,'weekday') == 0 ) {
220					$xhtml = strftime('%w');
221				} else if ( strcasecmp($cnst,'time') == 0 ) {
222					$xhtml = strftime('%T');
223				} else {
224					// for unknown match render original
225                    $xhtml = "{date={$cnst}}";
226				}
227            }
228
229            // unset cache, so that the page is always up to date
230            $renderer->info['cache'] = false;
231            // print out the date
232            $renderer->doc .= $xhtml;
233
234            // set locale LC_TIME setting to stored settings
235            if (isset($locale_key)) {
236                setlocale(LC_TIME,$localestore);
237            }
238
239            return true;
240        }
241        return false;
242    }
243
244
245    /**
246     * Handles the key=value array
247     */
248    function _GetKeyValues($replacers)
249    {
250            $r = array();
251            if (is_null($replacers)) {
252                $r['keys'] = null;
253                $r['vals'] = null;
254            } else if (is_string($replacers)) {
255                    list ($k, $v) = explode('=', $replacers, 2);
256                    // $r['keys'] = BEGIN_REPLACE_DELIMITER.trim($k).END_REPLACE_DELIMITER;
257                    $r['keys'] = trim($k);
258                    $r['vals'] = trim(str_replace('\|','|',$v));
259            } else if (is_array($replacers)) {
260                    foreach($replacers as $rep) {
261                            list ($k, $v) = explode('=', $rep, 2);
262                            // $r['keys'][] = BEGIN_REPLACE_DELIMITER.trim($k).END_REPLACE_DELIMITER;
263                            $r['keys'][] = trim($k);
264                            $r['vals'][] = trim(str_replace('\|','|',$v));
265                    }
266            } else {
267                    // This is an assertion failure. We should NEVER get here.
268                    //die("FATAL ERROR!  Unknown type passed to syntax_plugin_templater::massageReplaceMentArray() can't massage syntax_plugin_templater::\$replacers!  Type is:".gettype($r)." Value is:".$r);
269                $r['keys'] = null;
270                $r['vals'] = null;
271            }
272            return $r;
273    }
274 }
275?>
276