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