1<?php 2/** 3 * Plugin monthcal: Display monthly calendar 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Milosz Galazka <milosz@sleeplessbeastie.eu> 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'); 12require_once (DOKU_INC . 'inc/html.php'); 13 14/** 15 * All DokuWiki plugins to extend the parser/rendering mechanism 16 * need to inherit from this class 17 */ 18class syntax_plugin_monthcal extends DokuWiki_Syntax_Plugin { 19 20 /** 21 * Get the type of syntax this plugin defines. 22 * 23 */ 24 function getType(){ 25 return 'substition'; 26 } 27 28 /** 29 * Define how this plugin is handled regarding paragraphs. 30 * 31 */ 32 function getPType(){ 33 return 'block'; 34 } 35 36 /** 37 * Where to sort in? 38 * 39 * Doku_Parser_Mode_html 190 40 * --> execute here <-- 41 * Doku_Parser_Mode_code 200 42 */ 43 function getSort(){ 44 return 199; 45 } 46 47 /** 48 * Connect lookup pattern to lexer. 49 * 50 */ 51 function connectTo($mode) { 52 $this->Lexer->addSpecialPattern('{{monthcal.*?}}',$mode,'plugin_monthcal'); 53 } 54 55 /** 56 * Handler to prepare matched data for the rendering process. 57 * 58 */ 59 function handle($match, $state, $pos, Doku_Handler $handler){ 60 $data = array(); 61 62 // get page info 63 $INFO = pageinfo(); 64 65 // default vaues 66 $data['month'] = date('m'); 67 $data['year'] = date('Y'); 68 $data['namespace'] = $INFO['namespace']; 69 $data['create_links'] = 1; 70 $data['week_start_on'] = 0; 71 $data['display_weeks'] = 0; 72 $data['do_not_create_past_links'] = 0; 73 $data['borders'] = 0; 74 $data['mark_today'] = 1; 75 $data['align'] = 0; 76 $data['create_prev_next_links'] = 0; 77 78 $provided_data = substr($match, 11, -2); 79 $arguments = explode (',', $provided_data); 80 foreach ($arguments as $argument) { 81 list($key, $value) = explode('=', $argument); 82 switch($key) { 83 case 'year': 84 $data['year'] = $value; 85 break; 86 case 'month': 87 $data['month'] = $value; 88 break; 89 case 'namespace': 90 $data['namespace'] = (strpos($value, ':') === false) ? ':' . $value : $value; 91 break; 92 case 'create_links': 93 switch(strtolower($value)) { 94 case 'no': 95 $data['create_links'] = 0; 96 break; 97 case 'local': 98 $data['create_links'] = 2; 99 break; 100 default: 101 $data['create_links'] = 1; 102 break; 103 } 104 break; 105 case 'week_start_on': 106 if (strtolower($value) == "sunday") 107 $data['week_start_on'] = 1; 108 else 109 $data['week_start_on'] = 0; 110 break; 111 case 'display_weeks': 112 switch(strtolower($value)) { 113 case 'no': 114 $data['display_weeks'] = 0; 115 break; 116 default: 117 $data['display_weeks'] = 1; 118 break; 119 } 120 break; 121 case 'do_not_create_past_links': 122 switch(strtolower($value)) { 123 case 'no': 124 $data['do_not_create_past_links'] = 0; 125 break; 126 default: 127 $data['do_not_create_past_links'] = 1; 128 break; 129 } 130 break; 131 case 'create_prev_next_links': 132 switch(strtolower($value)) { 133 case 'no': 134 $data['create_prev_next_links'] = 0; 135 break; 136 default: 137 $data['create_prev_next_links'] = 1; 138 break; 139 } 140 break; 141 case 'borders': 142 switch(strtolower($value)) { 143 case 'all': 144 $data['borders'] = 1; 145 break; 146 case 'table': 147 $data['borders'] = 2; 148 break; 149 default: 150 $data['borders'] = 0; 151 break; 152 } 153 break; 154 case 'mark_today': 155 switch(strtolower($value)) { 156 case 'no': 157 $data['mark_today'] = 0; 158 break; 159 default: 160 $data['mark_today'] = 1; 161 break; 162 } 163 break; 164 case 'align': 165 switch(strtolower($value)) { 166 case 'left': 167 $data['align'] = 1; 168 break; 169 case 'right': 170 $data['align'] = 2; 171 break; 172 default: 173 $data['align'] = 0; 174 break; 175 } 176 break; 177 } 178 } 179 return $data; 180 } 181 182 /** 183 * Handle the actual output creation. 184 * 185 */ 186 function render($mode, Doku_Renderer $renderer, $data) { 187 if ($mode == 'xhtml'){ 188 $renderer->doc .= $this->create_calendar($data); 189 return true; 190 } 191 return false; 192 } 193 194 /** 195 * Create calendar 196 * 197 */ 198 function create_calendar($data) { 199 // date today 200 $date_today = new DateTime(); 201 202 // date yesterday 203 $date_yesterday = (new DateTime($date_today->format('Y-m-d')))->modify('-1 day'); 204 205 206 // date: from -> to 207 $date_from = new DateTime($data['year'] . "-" . $data['month'] . "-01"); 208 $date_to = (new DateTime($date_from->format('Y-m-d')))->modify('+1 month'); 209 210 // date prev/next month 211 $date_prev_month = (new DateTime($date_from->format('Y-m-d')))->modify('-1 month'); 212 $date_next_month = $date_to; //(new DateTime($date_to->format('Y-m-d')))->modify('+1 month'); 213 214 $date_interval = new DateInterval('P1D'); 215 $date_range = new DatePeriod($date_from, $date_interval, $date_to); 216 217 // first day in on ... 218 $date_from_on_weekday = $date_from->format('N'); 219 220 // language specific 221 $weekdays = $this->getLang('monthcal_weekdays_short'); 222 $months = $this->getLang('monthcal_months'); 223 224 // weekday variable which is used inside each loop 225 $wday = 1; 226 227 // move by one element to the right if week starts at Sunday 228 if ($data['week_start_on'] == 1) { 229 if ($date_from_on_weekday <= 6) 230 $date_from_on_weekday += 1; 231 else 232 $date_from_on_weekday = 1; 233 } 234 235 // border css 236 switch($data['align']) { 237 case 1: 238 $css_align = 'left'; 239 break; 240 case 2: 241 $css_align = 'right'; 242 break; 243 default: 244 $css_align = ''; 245 break; 246 } 247 248 // border css 249 switch($data['borders']) { 250 case 1: 251 $css_table_border = 'withborder'; 252 $css_td_border = 'withborder'; 253 break; 254 case 2: 255 $css_table_border = 'withborder'; 256 $css_td_border = 'borderless'; 257 break; 258 case 0: 259 $css_table_border = 'borderless'; 260 $css_td_border = 'borderless'; 261 break; 262 } 263 264 // html code 265 $html = '<table class="monthcal ' . $css_table_border . ' ' . $css_align . '">'; 266 267 // colspan for month/year 268 $colspan_month = 4; 269 if ($data['display_weeks'] == '1') { 270 $colspan_year= 4; 271 } else { 272 $colspan_year= 3; 273 } 274 275 // header 276 $html .= '<tr class="description">'; 277 $html .= '<td class="month ' . $css_td_border . '" colspan="' . $colspan_month . '">' . $months[$date_from->format('m')-1] . ' '; 278 if ($data['create_prev_next_links']){ 279 $html .= html_wikilink($data['namespace'] . ':' . $date_prev_month->format('Y') . ':' . $date_prev_month->format('m') . ':', '<<'); 280 $html .= html_wikilink($data['namespace'] . ':' . $date_next_month->format('Y') . ':' . $date_next_month->format('m') . ':', '>>'); 281 } 282 $html .= '</td>'; 283 $html .= '<td class="year" colspan="' . $colspan_year . '">' . $date_from->format('Y') . '</td></tr>'; 284 285 // swap weekdays if week starts at Sunday 286 if ($data['week_start_on'] == 1) { $weekdays=array($weekdays[6],$weekdays[0],$weekdays[1],$weekdays[2],$weekdays[3],$weekdays[4],$weekdays[5]);} 287 288 // append empty header for week numbers 289 if ($data['display_weeks'] == '1') { 290 array_unshift($weekdays,""); 291 } 292 293 // weekdays 294 $html .= '<tr>'; 295 foreach($weekdays as $weekday) { 296 $html .= '<th class="' . $css_td_border . '">' . $weekday . '</th>'; 297 } 298 $html .= '</tr>'; 299 $html .= '<tr>'; 300 301 // initial week number 302 if ($data['display_weeks'] == '1') { 303 $html .= '<td class="' . $css_td_border . '">' . $date_from->format("W") . '</td>'; 304 } 305 306 // first empty days 307 if ($date_from_on_weekday > 1) { 308 for($wday;$wday < $date_from_on_weekday;$wday++) { 309 $html .= '<td class="' . $css_td_border . '"></td>'; 310 } 311 } 312 313 // month days 314 foreach($date_range as $date) { 315 if ($wday > 7) { 316 $wday = 1; 317 $html .= "</tr>"; 318 $html .= "<tr>"; 319 320 if ($data['display_weeks'] == '1') { 321 $html .= '<td class="' . $css_td_border . '">' . $date->format("W") . '</td>'; 322 } 323 } 324 325 if ($date->format('Ymd') == $date_today->format('Ymd') and $data['mark_today'] == 1) 326 $css_today='today'; 327 else 328 $css_today=''; 329 330 if ($data['create_links'] == '1' ) { 331 $id = $data['namespace'] . ':' . $date->format('Y') . ':' . $date->format('m') . ':' . $date->format('d'); 332 if (($data['do_not_create_past_links'] == '1') and ($date->format('Ymd') < $date_today->format('Ymd'))) { 333 $page_exists = null; 334 resolve_pageid($data['namespace'] . ':' . $date->format('Y') . ':' . $date->format('m'), $date->format('d'), $page_exists); 335 if ($page_exists) { 336 $html_day = html_wikilink($id, $date->format('d')); 337 } else { 338 $html_day = $date->format('d'); 339 } 340 } else { 341 $html_day = html_wikilink($id, $date->format('d')); 342 } 343 } else if ($data['create_links'] == '2' ) { 344 $html_day = '<a href="#section' . $date->format('d') . '">' . $date->format('d') . '</a>'; 345 } else { 346 $html_day = $date->format('d'); 347 } 348 349 $html .= '<td class="' . $css_td_border . ' ' . $css_today . '">' . $html_day . '</td>'; 350 $wday++; 351 } 352 353 // last empty days 354 if ($wday < 8) { 355 for($wday;$wday<8;$wday++) { 356 $html .= '<td class="' . $css_td_border . '"></td>'; 357 } 358 } 359 360 // close table 361 $html .= '</table>'; 362 363 // return table 364 return $html; 365 } 366} 367 368//Setup VIM: ex: et ts=4 enc=utf-8 : 369?> 370