16fbb086dSAndreas Boehler<?php 26fbb086dSAndreas Boehler/** 36fbb086dSAndreas Boehler * DokuWiki Plugin DAVCal (Table Syntax Component) 46fbb086dSAndreas Boehler * 56fbb086dSAndreas Boehler * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 66fbb086dSAndreas Boehler * @author Andreas Böhler <dev@aboehler.at> 76fbb086dSAndreas Boehler */ 86fbb086dSAndreas Boehler 96fbb086dSAndreas Boehler// must be run within Dokuwiki 106fbb086dSAndreas Boehlerif(!defined('DOKU_INC')) die(); 116fbb086dSAndreas Boehler 126fbb086dSAndreas Boehlerif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 136fbb086dSAndreas Boehlerrequire_once(DOKU_PLUGIN.'syntax.php'); 146fbb086dSAndreas Boehler 156fbb086dSAndreas Boehlerclass syntax_plugin_davcal_table extends DokuWiki_Syntax_Plugin { 166fbb086dSAndreas Boehler 176fbb086dSAndreas Boehler protected $hlp = null; 186fbb086dSAndreas Boehler 196fbb086dSAndreas Boehler // Load the helper plugin 206fbb086dSAndreas Boehler public function syntax_plugin_davcal_table() { 216fbb086dSAndreas Boehler $this->hlp =& plugin_load('helper', 'davcal'); 226fbb086dSAndreas Boehler } 236fbb086dSAndreas Boehler 246fbb086dSAndreas Boehler 256fbb086dSAndreas Boehler /** 266fbb086dSAndreas Boehler * What kind of syntax are we? 276fbb086dSAndreas Boehler */ 286fbb086dSAndreas Boehler function getType(){ 296fbb086dSAndreas Boehler return 'substition'; 306fbb086dSAndreas Boehler } 316fbb086dSAndreas Boehler 326fbb086dSAndreas Boehler /** 336fbb086dSAndreas Boehler * What about paragraphs? 346fbb086dSAndreas Boehler */ 356fbb086dSAndreas Boehler function getPType(){ 366fbb086dSAndreas Boehler return 'normal'; 376fbb086dSAndreas Boehler } 386fbb086dSAndreas Boehler 396fbb086dSAndreas Boehler /** 406fbb086dSAndreas Boehler * Where to sort in? 416fbb086dSAndreas Boehler */ 426fbb086dSAndreas Boehler function getSort(){ 436fbb086dSAndreas Boehler return 165; 446fbb086dSAndreas Boehler } 456fbb086dSAndreas Boehler 466fbb086dSAndreas Boehler /** 476fbb086dSAndreas Boehler * Connect pattern to lexer 486fbb086dSAndreas Boehler */ 496fbb086dSAndreas Boehler function connectTo($mode) { 506fbb086dSAndreas Boehler $this->Lexer->addSpecialPattern('\{\{davcaltable>[^}]*\}\}',$mode,'plugin_davcal_table'); 516fbb086dSAndreas Boehler } 526fbb086dSAndreas Boehler 536fbb086dSAndreas Boehler /** 546fbb086dSAndreas Boehler * Handle the match 556fbb086dSAndreas Boehler */ 560b57b6d7SAndreas Boehler function handle($match, $state, $pos, Doku_Handler $handler){ 576fbb086dSAndreas Boehler global $ID; 586fbb086dSAndreas Boehler $options = trim(substr($match,14,-2)); 596fbb086dSAndreas Boehler $options = explode(',', $options); 606fbb086dSAndreas Boehler 616fbb086dSAndreas Boehler $data = array('id' => array(), 626fbb086dSAndreas Boehler 'startdate' => 'today', 636fbb086dSAndreas Boehler 'numdays' => 30, 64a469597cSAndreas Boehler 'startisend' => false, 656fbb086dSAndreas Boehler 'dateformat' => 'Y-m-d H:i', 667bbaf436SAndreas Boehler 'alldayformat' => 'Y-m-d', 676fbb086dSAndreas Boehler 'onlystart' => false, 68d0b117dfSAndreas Boehler 'location' => true, 69*b8265976SAndreas Boehler 'calname' => false, 7082a48dfbSAndreas Boehler 'sort' => 'desc', 7182a48dfbSAndreas Boehler 'timezone' => 'local' 726fbb086dSAndreas Boehler ); 736fbb086dSAndreas Boehler $lastid = $ID; 746fbb086dSAndreas Boehler 756fbb086dSAndreas Boehler foreach($options as $option) 766fbb086dSAndreas Boehler { 776fbb086dSAndreas Boehler list($key, $val) = explode('=', $option); 786fbb086dSAndreas Boehler $key = strtolower(trim($key)); 796fbb086dSAndreas Boehler $val = trim($val); 806fbb086dSAndreas Boehler switch($key) 816fbb086dSAndreas Boehler { 826fbb086dSAndreas Boehler case 'id': 836fbb086dSAndreas Boehler $lastid = $val; 846fbb086dSAndreas Boehler if(!in_array($val, $data['id'])) 856fbb086dSAndreas Boehler $data['id'][$val] = '#3a87ad'; 866fbb086dSAndreas Boehler break; 876fbb086dSAndreas Boehler case 'onlystart': 886fbb086dSAndreas Boehler if(($val === 'on') || ($val === 'true')) 896fbb086dSAndreas Boehler $data['onlystart'] = true; 906fbb086dSAndreas Boehler break; 91a469597cSAndreas Boehler case 'startisend': 92a469597cSAndreas Boehler if(($val === 'on') || ($val === 'true')) 93a469597cSAndreas Boehler $data['startisend'] = true; 94a469597cSAndreas Boehler break; 9582a48dfbSAndreas Boehler case 'timezone': 9682a48dfbSAndreas Boehler $tzlist = \DateTimeZone::listIdentifiers(DateTimeZone::ALL); 9782a48dfbSAndreas Boehler if(in_array($val, $tzlist) || $val === 'no') 9882a48dfbSAndreas Boehler $data['timezone'] = $val; 9982a48dfbSAndreas Boehler else 10082a48dfbSAndreas Boehler msg($this->getLang('error_timezone_not_in_list'), -1); 10182a48dfbSAndreas Boehler break; 102d0b117dfSAndreas Boehler case 'nolocation': 103d0b117dfSAndreas Boehler $data['location'] = false; 104d0b117dfSAndreas Boehler break; 105*b8265976SAndreas Boehler case 'calname': 106*b8265976SAndreas Boehler $data['calname'] = true; 107*b8265976SAndreas Boehler break; 1086fbb086dSAndreas Boehler default: 1096fbb086dSAndreas Boehler $data[$key] = $val; 1106fbb086dSAndreas Boehler } 1116fbb086dSAndreas Boehler } 1126fbb086dSAndreas Boehler 1136fbb086dSAndreas Boehler // Handle the default case when the user didn't enter a different ID 1146fbb086dSAndreas Boehler if(empty($data['id'])) 1156fbb086dSAndreas Boehler { 1166fbb086dSAndreas Boehler $data['id'] = array($ID => '#3a87ad'); 1176fbb086dSAndreas Boehler } 1186fbb086dSAndreas Boehler 1196fbb086dSAndreas Boehler return $data; 1206fbb086dSAndreas Boehler } 1216fbb086dSAndreas Boehler 1226fbb086dSAndreas Boehler private static function sort_events_asc($a, $b) 1236fbb086dSAndreas Boehler { 1246fbb086dSAndreas Boehler $from1 = new \DateTime($a['start']); 1256fbb086dSAndreas Boehler $from2 = new \DateTime($b['start']); 1266fbb086dSAndreas Boehler return $from2 < $from1; 1276fbb086dSAndreas Boehler } 1286fbb086dSAndreas Boehler 1296fbb086dSAndreas Boehler private static function sort_events_desc($a, $b) 1306fbb086dSAndreas Boehler { 1316fbb086dSAndreas Boehler $from1 = new \DateTime($a['start']); 1326fbb086dSAndreas Boehler $from2 = new \DateTime($b['start']); 1336fbb086dSAndreas Boehler return $from1 < $from2; 1346fbb086dSAndreas Boehler } 1356fbb086dSAndreas Boehler 1366fbb086dSAndreas Boehler /** 1376fbb086dSAndreas Boehler * Create output 1386fbb086dSAndreas Boehler */ 1390b57b6d7SAndreas Boehler function render($format, Doku_Renderer $R, $data) { 1406fbb086dSAndreas Boehler if($format == 'metadata') 1416fbb086dSAndreas Boehler { 1426fbb086dSAndreas Boehler $R->meta['plugin_davcal']['table'] = true; 1436fbb086dSAndreas Boehler return true; 1446fbb086dSAndreas Boehler } 1456fbb086dSAndreas Boehler if(($format != 'xhtml') && ($format != 'odt')) return false; 1466fbb086dSAndreas Boehler global $ID; 1476fbb086dSAndreas Boehler 1486fbb086dSAndreas Boehler $events = array(); 1496fbb086dSAndreas Boehler $from = $data['startdate']; 150a469597cSAndreas Boehler $toStr = null; 151a469597cSAndreas Boehler 152a469597cSAndreas Boehler // Handle the various options to 'startDate' 1536fbb086dSAndreas Boehler if($from === 'today') 1547bbaf436SAndreas Boehler { 1556fbb086dSAndreas Boehler $from = new \DateTime(); 1567bbaf436SAndreas Boehler } 1577bbaf436SAndreas Boehler elseif(strpos($from, 'today-') === 0) 1587bbaf436SAndreas Boehler { 159a469597cSAndreas Boehler $days = intval(str_replace('today-', '', $from)); 1607bbaf436SAndreas Boehler $from = new \DateTime(); 1617bbaf436SAndreas Boehler $from->sub(new \DateInterval('P'.$days.'D')); 1627bbaf436SAndreas Boehler } 163a469597cSAndreas Boehler elseif(strpos($from, 'today+') === 0) 164a469597cSAndreas Boehler { 165a469597cSAndreas Boehler $days = intval(str_replace('today+', '', $from)); 166a469597cSAndreas Boehler $from = new \DateTime(); 167a469597cSAndreas Boehler $from->add(new \DateInterval('P'.$days.'D')); 168a469597cSAndreas Boehler } 1696fbb086dSAndreas Boehler else 1707bbaf436SAndreas Boehler { 1716fbb086dSAndreas Boehler $from = new \DateTime($from); 1727bbaf436SAndreas Boehler } 173a469597cSAndreas Boehler 174a469597cSAndreas Boehler // Handle the option 'startisend' 175a469597cSAndreas Boehler if($data['startisend'] === true) 176a469597cSAndreas Boehler { 177a469597cSAndreas Boehler if($data['numdays'] > 0) 178a469597cSAndreas Boehler { 179a469597cSAndreas Boehler $to = clone $from; 180a469597cSAndreas Boehler $to->sub(new \DateInterval('P'.$data['numdays'].'D')); 181a469597cSAndreas Boehler $fromStr = $to->format('Y-m-d'); 182a469597cSAndreas Boehler } 183a469597cSAndreas Boehler else 184a469597cSAndreas Boehler { 185a469597cSAndreas Boehler $fromStr = null; 186a469597cSAndreas Boehler } 187a469597cSAndreas Boehler $toStr = $from->format('Y-m-d'); 188a469597cSAndreas Boehler } 189a469597cSAndreas Boehler else 190a469597cSAndreas Boehler { 191a469597cSAndreas Boehler if($data['numdays'] > 0) 192a469597cSAndreas Boehler { 1936fbb086dSAndreas Boehler $to = clone $from; 1946fbb086dSAndreas Boehler $to->add(new \DateInterval('P'.$data['numdays'].'D')); 195a469597cSAndreas Boehler $toStr = $to->format('Y-m-d'); 196a469597cSAndreas Boehler } 197a469597cSAndreas Boehler else 198a469597cSAndreas Boehler { 199a469597cSAndreas Boehler $toStr = null; 200a469597cSAndreas Boehler } 201a469597cSAndreas Boehler $fromStr = $from->format('Y-m-d'); 202a469597cSAndreas Boehler } 203a469597cSAndreas Boehler 204a469597cSAndreas Boehler // Support for timezone 20582a48dfbSAndreas Boehler $timezone = $data['timezone']; 206a469597cSAndreas Boehler 20780e1ddf7SAndreas Boehler // Filter events by user permissions 20880e1ddf7SAndreas Boehler $userEvents = $this->hlp->filterCalendarPagesByUserPermission($data['id']); 20980e1ddf7SAndreas Boehler 210a469597cSAndreas Boehler // Fetch the events 21180e1ddf7SAndreas Boehler foreach($userEvents as $calPage => $color) 2126fbb086dSAndreas Boehler { 2136fbb086dSAndreas Boehler $events = array_merge($events, $this->hlp->getEventsWithinDateRange($calPage, 214a469597cSAndreas Boehler $user, $fromStr, $toStr, $timezone)); 2156fbb086dSAndreas Boehler } 216*b8265976SAndreas Boehler 217a469597cSAndreas Boehler // Sort the events 2186fbb086dSAndreas Boehler if($data['sort'] === 'desc') 2196fbb086dSAndreas Boehler usort($events, array("syntax_plugin_davcal_table", "sort_events_desc")); 2206fbb086dSAndreas Boehler else 2216fbb086dSAndreas Boehler usort($events, array("syntax_plugin_davcal_table", "sort_events_asc")); 2226fbb086dSAndreas Boehler 223a469597cSAndreas Boehler // Create tabular output 2246fbb086dSAndreas Boehler $R->table_open(); 2256fbb086dSAndreas Boehler $R->tablethead_open(); 2266fbb086dSAndreas Boehler $R->tableheader_open(); 227f6f0bafeSAndreas Boehler $R->doc .= $data['onlystart'] ? hsc($this->getLang('at')) : hsc($this->getLang('from')); 2286fbb086dSAndreas Boehler $R->tableheader_close(); 2296fbb086dSAndreas Boehler if(!$data['onlystart']) 2306fbb086dSAndreas Boehler { 2316fbb086dSAndreas Boehler $R->tableheader_open(); 232f6f0bafeSAndreas Boehler $R->doc .= hsc($this->getLang('to')); 2336fbb086dSAndreas Boehler $R->tableheader_close(); 2346fbb086dSAndreas Boehler } 2356fbb086dSAndreas Boehler $R->tableheader_open(); 236f6f0bafeSAndreas Boehler $R->doc .= hsc($this->getLang('title')); 2376fbb086dSAndreas Boehler $R->tableheader_close(); 238d0b117dfSAndreas Boehler if($data['location']) 239d0b117dfSAndreas Boehler { 240d0b117dfSAndreas Boehler $R->tableheader_open(); 241d0b117dfSAndreas Boehler $R->doc .= hsc($this->getLang('location')); 242d0b117dfSAndreas Boehler $R->tableheader_close(); 243d0b117dfSAndreas Boehler } 244*b8265976SAndreas Boehler if($data['calname']) 245*b8265976SAndreas Boehler { 246*b8265976SAndreas Boehler $R->tableheader_open(); 247*b8265976SAndreas Boehler $R->doc .= hsc($this->getLang('calendar')); 248*b8265976SAndreas Boehler $R->tableheader_close(); 249*b8265976SAndreas Boehler } 2506fbb086dSAndreas Boehler $R->tableheader_open(); 251f6f0bafeSAndreas Boehler $R->doc .= hsc($this->getLang('description')); 2526fbb086dSAndreas Boehler $R->tableheader_close(); 2536fbb086dSAndreas Boehler $R->tablethead_close(); 2546fbb086dSAndreas Boehler foreach($events as $event) 2556fbb086dSAndreas Boehler { 2566fbb086dSAndreas Boehler $R->tablerow_open(); 2576fbb086dSAndreas Boehler $R->tablecell_open(); 2586fbb086dSAndreas Boehler $from = new \DateTime($event['start']); 25932cad826SAndreas Boehler if($timezone !== 'local') 26032cad826SAndreas Boehler { 261c841370aSAndreas Boehler $from->setTimezone(new \DateTimeZone($timezone)); 262c841370aSAndreas Boehler $to->setTimezone(new \DateTimeZone($timezone)); 26332cad826SAndreas Boehler } 2647bbaf436SAndreas Boehler if($event['allDay'] === true) 2657bbaf436SAndreas Boehler $R->doc .= $from->format($data['alldayformat']); 2667bbaf436SAndreas Boehler else 2676fbb086dSAndreas Boehler $R->doc .= $from->format($data['dateformat']); 2686fbb086dSAndreas Boehler $R->tablecell_close(); 2696fbb086dSAndreas Boehler if(!$data['onlystart']) 2706fbb086dSAndreas Boehler { 27106f3ffd9SAndreas Boehler $to = new \DateTime($event['end']); 27206f3ffd9SAndreas Boehler // Fixup all day events, which have one day in excess 27306f3ffd9SAndreas Boehler if($event['allDay'] === true) 27406f3ffd9SAndreas Boehler { 27506f3ffd9SAndreas Boehler $to->sub(new \DateInterval('P1D')); 27606f3ffd9SAndreas Boehler } 2776fbb086dSAndreas Boehler $R->tablecell_open(); 2787bbaf436SAndreas Boehler if($event['allDay'] === true) 2797bbaf436SAndreas Boehler $R->doc .= $to->format($data['alldayformat']); 2807bbaf436SAndreas Boehler else 2816fbb086dSAndreas Boehler $R->doc .= $to->format($data['dateformat']); 2826fbb086dSAndreas Boehler $R->tablecell_close(); 2836fbb086dSAndreas Boehler } 2846fbb086dSAndreas Boehler $R->tablecell_open(); 285f6f0bafeSAndreas Boehler $R->doc .= hsc($event['title']); 2866fbb086dSAndreas Boehler $R->tablecell_close(); 287d0b117dfSAndreas Boehler if($data['location']) 288d0b117dfSAndreas Boehler { 289d0b117dfSAndreas Boehler $R->tablecell_open(); 290d0b117dfSAndreas Boehler $R->doc .= hsc($event['location']); 291d0b117dfSAndreas Boehler $R->tablecell_close(); 292d0b117dfSAndreas Boehler } 293*b8265976SAndreas Boehler if($data['calname']) 294*b8265976SAndreas Boehler { 295*b8265976SAndreas Boehler $R->tablecell_open(); 296*b8265976SAndreas Boehler $R->doc .= hsc($event['calendarname']); 297*b8265976SAndreas Boehler $R->tablecell_close(); 298*b8265976SAndreas Boehler } 2996fbb086dSAndreas Boehler $R->tablecell_open(); 300f6f0bafeSAndreas Boehler $R->doc .= hsc($event['description']); 3016fbb086dSAndreas Boehler $R->tablecell_close(); 3026fbb086dSAndreas Boehler $R->tablerow_close(); 3036fbb086dSAndreas Boehler } 3046fbb086dSAndreas Boehler $R->table_close(); 3056fbb086dSAndreas Boehler } 3066fbb086dSAndreas Boehler 3076fbb086dSAndreas Boehler 3086fbb086dSAndreas Boehler 3096fbb086dSAndreas Boehler} 3106fbb086dSAndreas Boehler 3116fbb086dSAndreas Boehler// vim:ts=4:sw=4:et:enc=utf-8: 312