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