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 9class syntax_plugin_davcal_table extends DokuWiki_Syntax_Plugin { 10 11 protected $hlp = null; 12 13 // Load the helper plugin 14 public function __construct() { 15 $this->hlp =& plugin_load('helper', 'davcal'); 16 } 17 18 19 /** 20 * What kind of syntax are we? 21 */ 22 function getType(){ 23 return 'substition'; 24 } 25 26 /** 27 * What about paragraphs? 28 */ 29 function getPType(){ 30 return 'normal'; 31 } 32 33 /** 34 * Where to sort in? 35 */ 36 function getSort(){ 37 return 165; 38 } 39 40 /** 41 * Connect pattern to lexer 42 */ 43 function connectTo($mode) { 44 $this->Lexer->addSpecialPattern('\{\{davcaltable>[^}]*\}\}',$mode,'plugin_davcal_table'); 45 } 46 47 /** 48 * Handle the match 49 */ 50 function handle($match, $state, $pos, Doku_Handler $handler){ 51 global $ID; 52 $options = trim(substr($match,14,-2)); 53 $options = explode(',', $options); 54 55 $data = array('id' => array(), 56 'startdate' => 'today', 57 'numdays' => 30, 58 'startisend' => false, 59 'dateformat' => 'Y-m-d H:i', 60 'alldayformat' => 'Y-m-d', 61 'onlystart' => false, 62 'location' => true, 63 'calname' => false, 64 'sort' => 'desc', 65 'timezone' => 'local' 66 ); 67 $lastid = $ID; 68 69 foreach($options as $option) 70 { 71 list($key, $val) = explode('=', $option); 72 $key = strtolower(trim($key)); 73 $val = trim($val); 74 switch($key) 75 { 76 case 'id': 77 $lastid = $val; 78 if(!in_array($val, $data['id'])) 79 $data['id'][$val] = '#3a87ad'; 80 break; 81 case 'onlystart': 82 if(($val === 'on') || ($val === 'true')) 83 $data['onlystart'] = true; 84 break; 85 case 'startisend': 86 if(($val === 'on') || ($val === 'true')) 87 $data['startisend'] = true; 88 break; 89 case 'timezone': 90 $tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL); 91 if(in_array($val, $tzlist) || $val === 'no') 92 $data['timezone'] = $val; 93 else 94 msg($this->getLang('error_timezone_not_in_list'), -1); 95 break; 96 case 'nolocation': 97 $data['location'] = false; 98 break; 99 case 'calname': 100 if(($val === 'on') || ($val === 'true')) 101 $data['calname'] = true; 102 break; 103 default: 104 $data[$key] = $val; 105 } 106 } 107 108 // Handle the default case when the user didn't enter a different ID 109 if(empty($data['id'])) 110 { 111 $data['id'] = array($ID => '#3a87ad'); 112 } 113 114 return $data; 115 } 116 117 private static function sort_events_asc($a, $b) 118 { 119 $from1 = new \DateTime($a['start']); 120 $from2 = new \DateTime($b['start']); 121 return $from2 < $from1; 122 } 123 124 private static function sort_events_desc($a, $b) 125 { 126 $from1 = new \DateTime($a['start']); 127 $from2 = new \DateTime($b['start']); 128 return $from1 < $from2; 129 } 130 131 /** 132 * Create output 133 */ 134 function render($format, Doku_Renderer $R, $data) { 135 if($format == 'metadata') 136 { 137 $R->meta['plugin_davcal']['table'] = true; 138 return true; 139 } 140 if(($format != 'xhtml') && ($format != 'odt')) return false; 141 global $ID; 142 143 $events = array(); 144 $from = $data['startdate']; 145 $toStr = null; 146 147 // Handle the various options to 'startDate' 148 if($from === 'today') 149 { 150 $from = new \DateTime(); 151 } 152 elseif(strpos($from, 'today-') === 0) 153 { 154 $days = intval(str_replace('today-', '', $from)); 155 $from = new \DateTime(); 156 $from->sub(new \DateInterval('P'.$days.'D')); 157 } 158 elseif(strpos($from, 'today+') === 0) 159 { 160 $days = intval(str_replace('today+', '', $from)); 161 $from = new \DateTime(); 162 $from->add(new \DateInterval('P'.$days.'D')); 163 } 164 else 165 { 166 $from = new \DateTime($from); 167 } 168 169 // Handle the option 'startisend' 170 if($data['startisend'] === true) 171 { 172 if($data['numdays'] > 0) 173 { 174 $to = clone $from; 175 $to->sub(new \DateInterval('P'.$data['numdays'].'D')); 176 $fromStr = $to->format('Y-m-d'); 177 } 178 else 179 { 180 $fromStr = null; 181 } 182 $toStr = $from->format('Y-m-d'); 183 } 184 else 185 { 186 if($data['numdays'] > 0) 187 { 188 $to = clone $from; 189 $to->add(new \DateInterval('P'.$data['numdays'].'D')); 190 $toStr = $to->format('Y-m-d'); 191 } 192 else 193 { 194 $toStr = null; 195 } 196 $fromStr = $from->format('Y-m-d'); 197 } 198 199 // Support for timezone 200 $timezone = $data['timezone']; 201 202 // Filter events by user permissions 203 $userEvents = $this->hlp->filterCalendarPagesByUserPermission($data['id']); 204 205 // Fetch the events 206 foreach($userEvents as $calPage => $color) 207 { 208 $events = array_merge($events, $this->hlp->getEventsWithinDateRange($calPage, 209 $user, $fromStr, $toStr, $timezone)); 210 } 211 212 // Sort the events 213 if($data['sort'] === 'desc') 214 usort($events, array("syntax_plugin_davcal_table", "sort_events_desc")); 215 else 216 usort($events, array("syntax_plugin_davcal_table", "sort_events_asc")); 217 218 // Create tabular output 219 $R->table_open(); 220 $R->tablethead_open(); 221 $R->tableheader_open(); 222 $R->doc .= $data['onlystart'] ? hsc($this->getLang('at')) : hsc($this->getLang('from')); 223 $R->tableheader_close(); 224 if(!$data['onlystart']) 225 { 226 $R->tableheader_open(); 227 $R->doc .= hsc($this->getLang('to')); 228 $R->tableheader_close(); 229 } 230 $R->tableheader_open(); 231 $R->doc .= hsc($this->getLang('title')); 232 $R->tableheader_close(); 233 if($data['location']) 234 { 235 $R->tableheader_open(); 236 $R->doc .= hsc($this->getLang('location')); 237 $R->tableheader_close(); 238 } 239 if($data['calname']) 240 { 241 $R->tableheader_open(); 242 $R->doc .= hsc($this->getLang('calendar')); 243 $R->tableheader_close(); 244 } 245 $R->tableheader_open(); 246 $R->doc .= hsc($this->getLang('description')); 247 $R->tableheader_close(); 248 $R->tablethead_close(); 249 foreach($events as $event) 250 { 251 $R->tablerow_open(); 252 $R->tablecell_open(); 253 $from = new \DateTime($event['start']); 254 if($timezone !== 'local') 255 { 256 $from->setTimezone(new \DateTimeZone($timezone)); 257 $to->setTimezone(new \DateTimeZone($timezone)); 258 } 259 if($event['allDay'] === true) 260 $R->doc .= $from->format($data['alldayformat']); 261 else 262 $R->doc .= $from->format($data['dateformat']); 263 $R->tablecell_close(); 264 if(!$data['onlystart']) 265 { 266 $to = new \DateTime($event['end']); 267 // Fixup all day events, which have one day in excess 268 if($event['allDay'] === true) 269 { 270 $to->sub(new \DateInterval('P1D')); 271 } 272 $R->tablecell_open(); 273 if($event['allDay'] === true) 274 $R->doc .= $to->format($data['alldayformat']); 275 else 276 $R->doc .= $to->format($data['dateformat']); 277 $R->tablecell_close(); 278 } 279 $R->tablecell_open(); 280 $R->doc .= hsc($event['title']); 281 $R->tablecell_close(); 282 if($data['location']) 283 { 284 $R->tablecell_open(); 285 $R->doc .= hsc($event['location']); 286 $R->tablecell_close(); 287 } 288 if($data['calname']) 289 { 290 $R->tablecell_open(); 291 $R->doc .= hsc($event['calendarname']); 292 $R->tablecell_close(); 293 } 294 $R->tablecell_open(); 295 $R->doc .= hsc($event['description']); 296 $R->tablecell_close(); 297 $R->tablerow_close(); 298 } 299 $R->table_close(); 300 } 301 302 303 304} 305 306// vim:ts=4:sw=4:et:enc=utf-8: 307