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