1a1a3b679SAndreas Boehler<?php 2a1a3b679SAndreas Boehler/** 3cb71a62aSAndreas Boehler * Helper Class for the DAVCal plugin 4a1a3b679SAndreas Boehler * This helper does the actual work. 5a1a3b679SAndreas Boehler * 6a1a3b679SAndreas Boehler */ 7a1a3b679SAndreas Boehler 8a1a3b679SAndreas Boehler// must be run within Dokuwiki 9a1a3b679SAndreas Boehlerif(!defined('DOKU_INC')) die(); 10a1a3b679SAndreas Boehler 11a1a3b679SAndreas Boehlerclass helper_plugin_davcal extends DokuWiki_Plugin { 12a1a3b679SAndreas Boehler 13a1a3b679SAndreas Boehler protected $sqlite = null; 14185e2535SAndreas Boehler protected $cachedValues = array(); 15a1a3b679SAndreas Boehler 16a1a3b679SAndreas Boehler /** 17cb71a62aSAndreas Boehler * Constructor to load the configuration and the SQLite plugin 18a1a3b679SAndreas Boehler */ 19a1a3b679SAndreas Boehler public function helper_plugin_davcal() { 20a1a3b679SAndreas Boehler $this->sqlite =& plugin_load('helper', 'sqlite'); 2121d04f73SAndreas Boehler global $conf; 2221d04f73SAndreas Boehler if($conf['allowdebug']) 2321d04f73SAndreas Boehler dbglog('---- DAVCAL helper.php init'); 24a1a3b679SAndreas Boehler if(!$this->sqlite) 25a1a3b679SAndreas Boehler { 2621d04f73SAndreas Boehler if($conf['allowdebug']) 2721d04f73SAndreas Boehler dbglog('This plugin requires the sqlite plugin. Please install it.'); 28a1a3b679SAndreas Boehler msg('This plugin requires the sqlite plugin. Please install it.'); 29a1a3b679SAndreas Boehler return; 30a1a3b679SAndreas Boehler } 31a1a3b679SAndreas Boehler 32a1a3b679SAndreas Boehler if(!$this->sqlite->init('davcal', DOKU_PLUGIN.'davcal/db/')) 33a1a3b679SAndreas Boehler { 3421d04f73SAndreas Boehler if($conf['allowdebug']) 3521d04f73SAndreas Boehler dbglog('Error initialising the SQLite DB for DAVCal'); 36a1a3b679SAndreas Boehler return; 37a1a3b679SAndreas Boehler } 38a1a3b679SAndreas Boehler } 39a1a3b679SAndreas Boehler 40cb71a62aSAndreas Boehler /** 41185e2535SAndreas Boehler * Retrieve meta data for a given page 42185e2535SAndreas Boehler * 43185e2535SAndreas Boehler * @param string $id optional The page ID 44185e2535SAndreas Boehler * @return array The metadata 45185e2535SAndreas Boehler */ 46185e2535SAndreas Boehler private function getMeta($id = null) { 47185e2535SAndreas Boehler global $ID; 48185e2535SAndreas Boehler global $INFO; 49185e2535SAndreas Boehler 50185e2535SAndreas Boehler if ($id === null) $id = $ID; 51185e2535SAndreas Boehler 52185e2535SAndreas Boehler if($ID === $id && $INFO['meta']) { 53185e2535SAndreas Boehler $meta = $INFO['meta']; 54185e2535SAndreas Boehler } else { 55185e2535SAndreas Boehler $meta = p_get_metadata($id); 56185e2535SAndreas Boehler } 57185e2535SAndreas Boehler 58185e2535SAndreas Boehler return $meta; 59185e2535SAndreas Boehler } 60185e2535SAndreas Boehler 61185e2535SAndreas Boehler /** 62185e2535SAndreas Boehler * Retrieve the meta data for a given page 63185e2535SAndreas Boehler * 64185e2535SAndreas Boehler * @param string $id optional The page ID 65185e2535SAndreas Boehler * @return array with meta data 66185e2535SAndreas Boehler */ 67185e2535SAndreas Boehler public function getCalendarMetaForPage($id = null) 68185e2535SAndreas Boehler { 69185e2535SAndreas Boehler if(is_null($id)) 70185e2535SAndreas Boehler { 71185e2535SAndreas Boehler global $ID; 72185e2535SAndreas Boehler $id = $ID; 73185e2535SAndreas Boehler } 74185e2535SAndreas Boehler 75185e2535SAndreas Boehler $meta = $this->getMeta($id); 76185e2535SAndreas Boehler if(isset($meta['plugin_davcal'])) 77185e2535SAndreas Boehler return $meta['plugin_davcal']; 78185e2535SAndreas Boehler else 79185e2535SAndreas Boehler return array(); 80185e2535SAndreas Boehler } 81185e2535SAndreas Boehler 82185e2535SAndreas Boehler /** 8380e1ddf7SAndreas Boehler * Filter calendar pages and return only those where the current 8480e1ddf7SAndreas Boehler * user has at least read permission. 8580e1ddf7SAndreas Boehler * 8680e1ddf7SAndreas Boehler * @param array $calendarPages Array with calendar pages to check 8780e1ddf7SAndreas Boehler * @return array with filtered calendar pages 8880e1ddf7SAndreas Boehler */ 8980e1ddf7SAndreas Boehler public function filterCalendarPagesByUserPermission($calendarPages) 9080e1ddf7SAndreas Boehler { 9180e1ddf7SAndreas Boehler $retList = array(); 9280e1ddf7SAndreas Boehler foreach($calendarPages as $page => $data) 9380e1ddf7SAndreas Boehler { 9480e1ddf7SAndreas Boehler if(auth_quickaclcheck($page) >= AUTH_READ) 9580e1ddf7SAndreas Boehler { 9680e1ddf7SAndreas Boehler $retList[$page] = $data; 9780e1ddf7SAndreas Boehler } 9880e1ddf7SAndreas Boehler } 9980e1ddf7SAndreas Boehler return $retList; 10080e1ddf7SAndreas Boehler } 10180e1ddf7SAndreas Boehler 10280e1ddf7SAndreas Boehler /** 103185e2535SAndreas Boehler * Get all calendar pages used by a given page 104185e2535SAndreas Boehler * based on the stored metadata 105185e2535SAndreas Boehler * 106185e2535SAndreas Boehler * @param string $id optional The page id 107185e2535SAndreas Boehler * @return mixed The pages as array or false 108185e2535SAndreas Boehler */ 109185e2535SAndreas Boehler public function getCalendarPagesByMeta($id = null) 110185e2535SAndreas Boehler { 111185e2535SAndreas Boehler if(is_null($id)) 112185e2535SAndreas Boehler { 113185e2535SAndreas Boehler global $ID; 114185e2535SAndreas Boehler $id = $ID; 115185e2535SAndreas Boehler } 116185e2535SAndreas Boehler 117185e2535SAndreas Boehler $meta = $this->getCalendarMetaForPage($id); 118185e2535SAndreas Boehler if(isset($meta['id'])) 119ed764890SAndreas Boehler { 120ed764890SAndreas Boehler // Filter the list of pages by permission 12180e1ddf7SAndreas Boehler $pages = $this->filterCalendarPagesByUserPermission($meta['id']); 12280e1ddf7SAndreas Boehler if(empty($pages)) 123ed764890SAndreas Boehler return false; 12480e1ddf7SAndreas Boehler return $pages; 125ed764890SAndreas Boehler } 126185e2535SAndreas Boehler return false; 127185e2535SAndreas Boehler } 128185e2535SAndreas Boehler 129185e2535SAndreas Boehler /** 130185e2535SAndreas Boehler * Get a list of calendar names/pages/ids/colors 131185e2535SAndreas Boehler * for an array of page ids 132185e2535SAndreas Boehler * 133185e2535SAndreas Boehler * @param array $calendarPages The calendar pages to retrieve 134185e2535SAndreas Boehler * @return array The list 135185e2535SAndreas Boehler */ 136185e2535SAndreas Boehler public function getCalendarMapForIDs($calendarPages) 137185e2535SAndreas Boehler { 138185e2535SAndreas Boehler $data = array(); 139*4a2bf5eeSAndreas Boehler foreach($calendarPages as $page => $color) 140185e2535SAndreas Boehler { 141185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($page); 142185e2535SAndreas Boehler if($calid !== false) 143185e2535SAndreas Boehler { 144185e2535SAndreas Boehler $settings = $this->getCalendarSettings($calid); 145185e2535SAndreas Boehler $name = $settings['displayname']; 146ed764890SAndreas Boehler $write = (auth_quickaclcheck($page) > AUTH_READ); 147185e2535SAndreas Boehler $data[] = array('name' => $name, 'page' => $page, 'calid' => $calid, 148ed764890SAndreas Boehler 'color' => $color, 'write' => $write); 149185e2535SAndreas Boehler } 150185e2535SAndreas Boehler } 151185e2535SAndreas Boehler return $data; 152185e2535SAndreas Boehler } 153185e2535SAndreas Boehler 154185e2535SAndreas Boehler /** 155185e2535SAndreas Boehler * Get the saved calendar color for a given page. 156185e2535SAndreas Boehler * 157185e2535SAndreas Boehler * @param string $id optional The page ID 158185e2535SAndreas Boehler * @return mixed The color on success, otherwise false 159185e2535SAndreas Boehler */ 160185e2535SAndreas Boehler public function getCalendarColorForPage($id = null) 161185e2535SAndreas Boehler { 162185e2535SAndreas Boehler if(is_null($id)) 163185e2535SAndreas Boehler { 164185e2535SAndreas Boehler global $ID; 165185e2535SAndreas Boehler $id = $ID; 166185e2535SAndreas Boehler } 167185e2535SAndreas Boehler 168185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 169185e2535SAndreas Boehler if($calid === false) 170185e2535SAndreas Boehler return false; 171185e2535SAndreas Boehler 172185e2535SAndreas Boehler return $this->getCalendarColorForCalendar($calid); 173185e2535SAndreas Boehler } 174185e2535SAndreas Boehler 175185e2535SAndreas Boehler /** 176185e2535SAndreas Boehler * Get the saved calendar color for a given calendar ID. 177185e2535SAndreas Boehler * 178185e2535SAndreas Boehler * @param string $id optional The calendar ID 179185e2535SAndreas Boehler * @return mixed The color on success, otherwise false 180185e2535SAndreas Boehler */ 181185e2535SAndreas Boehler public function getCalendarColorForCalendar($calid) 182185e2535SAndreas Boehler { 183185e2535SAndreas Boehler if(isset($this->cachedValues['calendarcolor'][$calid])) 184185e2535SAndreas Boehler return $this->cachedValues['calendarcolor'][$calid]; 185185e2535SAndreas Boehler 186185e2535SAndreas Boehler $row = $this->getCalendarSettings($calid); 187185e2535SAndreas Boehler 188185e2535SAndreas Boehler if(!isset($row['calendarcolor'])) 189185e2535SAndreas Boehler return false; 190185e2535SAndreas Boehler 191185e2535SAndreas Boehler $color = $row['calendarcolor']; 192185e2535SAndreas Boehler $this->cachedValues['calendarcolor'][$calid] = $color; 193185e2535SAndreas Boehler return $color; 194185e2535SAndreas Boehler } 195185e2535SAndreas Boehler 196185e2535SAndreas Boehler /** 197e86c8dd3SAndreas Boehler * Get the user's principal URL for iOS sync 198e86c8dd3SAndreas Boehler * @param string $user the user name 199e86c8dd3SAndreas Boehler * @return the URL to the principal sync 200e86c8dd3SAndreas Boehler */ 201e86c8dd3SAndreas Boehler public function getPrincipalUrlForUser($user) 202e86c8dd3SAndreas Boehler { 203e86c8dd3SAndreas Boehler if(is_null($user)) 204e86c8dd3SAndreas Boehler return false; 205e86c8dd3SAndreas Boehler $url = DOKU_URL.'lib/plugins/davcal/calendarserver.php/principals/'.$user; 206e86c8dd3SAndreas Boehler return $url; 207e86c8dd3SAndreas Boehler } 208e86c8dd3SAndreas Boehler 209e86c8dd3SAndreas Boehler /** 210185e2535SAndreas Boehler * Set the calendar color for a given page. 211185e2535SAndreas Boehler * 212185e2535SAndreas Boehler * @param string $color The color definition 213185e2535SAndreas Boehler * @param string $id optional The page ID 214185e2535SAndreas Boehler * @return boolean True on success, otherwise false 215185e2535SAndreas Boehler */ 216185e2535SAndreas Boehler public function setCalendarColorForPage($color, $id = null) 217185e2535SAndreas Boehler { 218185e2535SAndreas Boehler if(is_null($id)) 219185e2535SAndreas Boehler { 220185e2535SAndreas Boehler global $ID; 221185e2535SAndreas Boehler $id = $ID; 222185e2535SAndreas Boehler } 223185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 224185e2535SAndreas Boehler if($calid === false) 225185e2535SAndreas Boehler return false; 226185e2535SAndreas Boehler 22751f4febbSAndreas Boehler $query = "UPDATE calendars SET calendarcolor = ? ". 22851f4febbSAndreas Boehler " WHERE id = ?"; 22951f4febbSAndreas Boehler $res = $this->sqlite->query($query, $color, $calid); 230185e2535SAndreas Boehler if($res !== false) 231185e2535SAndreas Boehler { 232185e2535SAndreas Boehler $this->cachedValues['calendarcolor'][$calid] = $color; 233185e2535SAndreas Boehler return true; 234185e2535SAndreas Boehler } 235185e2535SAndreas Boehler return false; 236185e2535SAndreas Boehler } 237185e2535SAndreas Boehler 238185e2535SAndreas Boehler /** 239cb71a62aSAndreas Boehler * Set the calendar name and description for a given page with a given 240cb71a62aSAndreas Boehler * page id. 241cb71a62aSAndreas Boehler * If the calendar doesn't exist, the calendar is created! 242cb71a62aSAndreas Boehler * 243cb71a62aSAndreas Boehler * @param string $name The name of the new calendar 244cb71a62aSAndreas Boehler * @param string $description The description of the new calendar 245cb71a62aSAndreas Boehler * @param string $id (optional) The ID of the page 246cb71a62aSAndreas Boehler * @param string $userid The userid of the creating user 247cb71a62aSAndreas Boehler * 248cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false. 249cb71a62aSAndreas Boehler */ 250a1a3b679SAndreas Boehler public function setCalendarNameForPage($name, $description, $id = null, $userid = null) 251a1a3b679SAndreas Boehler { 252a1a3b679SAndreas Boehler if(is_null($id)) 253a1a3b679SAndreas Boehler { 254a1a3b679SAndreas Boehler global $ID; 255a1a3b679SAndreas Boehler $id = $ID; 256a1a3b679SAndreas Boehler } 257a1a3b679SAndreas Boehler if(is_null($userid)) 25834a47953SAndreas Boehler { 25934a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 26034a47953SAndreas Boehler { 261a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 26234a47953SAndreas Boehler } 26334a47953SAndreas Boehler else 26434a47953SAndreas Boehler { 26534a47953SAndreas Boehler $userid = uniqid('davcal-'); 26634a47953SAndreas Boehler } 26734a47953SAndreas Boehler } 268a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 269a1a3b679SAndreas Boehler if($calid === false) 270a1a3b679SAndreas Boehler return $this->createCalendarForPage($name, $description, $id, $userid); 271a1a3b679SAndreas Boehler 27251f4febbSAndreas Boehler $query = "UPDATE calendars SET displayname = ?, description = ? WHERE id = ?"; 27351f4febbSAndreas Boehler $res = $this->sqlite->query($query, $name, $description, $calid); 274b269830cSAndreas Boehler if($res !== false) 275b269830cSAndreas Boehler return true; 276b269830cSAndreas Boehler return false; 277a1a3b679SAndreas Boehler } 278a1a3b679SAndreas Boehler 279cb71a62aSAndreas Boehler /** 280cb71a62aSAndreas Boehler * Save the personal settings to the SQLite database 'calendarsettings'. 281cb71a62aSAndreas Boehler * 282cb71a62aSAndreas Boehler * @param array $settings The settings array to store 283cb71a62aSAndreas Boehler * @param string $userid (optional) The userid to store 284cb71a62aSAndreas Boehler * 285cb71a62aSAndreas Boehler * @param boolean True on success, otherwise false 286cb71a62aSAndreas Boehler */ 287a495d34cSAndreas Boehler public function savePersonalSettings($settings, $userid = null) 288a495d34cSAndreas Boehler { 289a495d34cSAndreas Boehler if(is_null($userid)) 29034a47953SAndreas Boehler { 29134a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 29234a47953SAndreas Boehler { 293a495d34cSAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 29434a47953SAndreas Boehler } 29534a47953SAndreas Boehler else 29634a47953SAndreas Boehler { 29734a47953SAndreas Boehler return false; 29834a47953SAndreas Boehler } 29934a47953SAndreas Boehler } 300a495d34cSAndreas Boehler $this->sqlite->query("BEGIN TRANSACTION"); 301a495d34cSAndreas Boehler 30251f4febbSAndreas Boehler $query = "DELETE FROM calendarsettings WHERE userid = ?"; 30351f4febbSAndreas Boehler $this->sqlite->query($query, $userid); 304bd883736SAndreas Boehler 305a495d34cSAndreas Boehler foreach($settings as $key => $value) 306a495d34cSAndreas Boehler { 30751f4febbSAndreas Boehler $query = "INSERT INTO calendarsettings (userid, key, value) VALUES (?, ?, ?)"; 30851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $userid, $key, $value); 309a495d34cSAndreas Boehler if($res === false) 310a495d34cSAndreas Boehler return false; 311a495d34cSAndreas Boehler } 312a495d34cSAndreas Boehler $this->sqlite->query("COMMIT TRANSACTION"); 313185e2535SAndreas Boehler $this->cachedValues['settings'][$userid] = $settings; 314a495d34cSAndreas Boehler return true; 315a495d34cSAndreas Boehler } 316a495d34cSAndreas Boehler 317cb71a62aSAndreas Boehler /** 318cb71a62aSAndreas Boehler * Retrieve the settings array for a given user id. 319cb71a62aSAndreas Boehler * Some sane defaults are returned, currently: 320cb71a62aSAndreas Boehler * 321cb71a62aSAndreas Boehler * timezone => local 322cb71a62aSAndreas Boehler * weeknumbers => 0 323cb71a62aSAndreas Boehler * workweek => 0 324cb71a62aSAndreas Boehler * 325cb71a62aSAndreas Boehler * @param string $userid (optional) The user id to retrieve 326cb71a62aSAndreas Boehler * 327cb71a62aSAndreas Boehler * @return array The settings array 328cb71a62aSAndreas Boehler */ 329a495d34cSAndreas Boehler public function getPersonalSettings($userid = null) 330a495d34cSAndreas Boehler { 331bd883736SAndreas Boehler // Some sane default settings 332bd883736SAndreas Boehler $settings = array( 333fb813b30SAndreas Boehler 'timezone' => $this->getConf('timezone'), 334fb813b30SAndreas Boehler 'weeknumbers' => $this->getConf('weeknumbers'), 335fb813b30SAndreas Boehler 'workweek' => $this->getConf('workweek'), 3361d5bdcd0SAndreas Boehler 'monday' => $this->getConf('monday'), 3371d5bdcd0SAndreas Boehler 'timeformat' => $this->getConf('timeformat') 338bd883736SAndreas Boehler ); 33934a47953SAndreas Boehler if(is_null($userid)) 34034a47953SAndreas Boehler { 34134a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 34234a47953SAndreas Boehler { 34334a47953SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 34434a47953SAndreas Boehler } 34534a47953SAndreas Boehler else 34634a47953SAndreas Boehler { 34734a47953SAndreas Boehler return $settings; 34834a47953SAndreas Boehler } 34934a47953SAndreas Boehler } 35034a47953SAndreas Boehler 35134a47953SAndreas Boehler if(isset($this->cachedValues['settings'][$userid])) 35234a47953SAndreas Boehler return $this->cachedValues['settings'][$userid]; 35351f4febbSAndreas Boehler $query = "SELECT key, value FROM calendarsettings WHERE userid = ?"; 35451f4febbSAndreas Boehler $res = $this->sqlite->query($query, $userid); 355a495d34cSAndreas Boehler $arr = $this->sqlite->res2arr($res); 356a495d34cSAndreas Boehler foreach($arr as $row) 357a495d34cSAndreas Boehler { 358a495d34cSAndreas Boehler $settings[$row['key']] = $row['value']; 359a495d34cSAndreas Boehler } 360185e2535SAndreas Boehler $this->cachedValues['settings'][$userid] = $settings; 361a495d34cSAndreas Boehler return $settings; 362a495d34cSAndreas Boehler } 363a495d34cSAndreas Boehler 364cb71a62aSAndreas Boehler /** 365cb71a62aSAndreas Boehler * Retrieve the calendar ID based on a page ID from the SQLite table 366cb71a62aSAndreas Boehler * 'pagetocalendarmapping'. 367cb71a62aSAndreas Boehler * 368cb71a62aSAndreas Boehler * @param string $id (optional) The page ID to retrieve the corresponding calendar 369cb71a62aSAndreas Boehler * 370cb71a62aSAndreas Boehler * @return mixed the ID on success, otherwise false 371cb71a62aSAndreas Boehler */ 372a1a3b679SAndreas Boehler public function getCalendarIdForPage($id = null) 373a1a3b679SAndreas Boehler { 374a1a3b679SAndreas Boehler if(is_null($id)) 375a1a3b679SAndreas Boehler { 376a1a3b679SAndreas Boehler global $ID; 377a1a3b679SAndreas Boehler $id = $ID; 378a1a3b679SAndreas Boehler } 379a1a3b679SAndreas Boehler 380185e2535SAndreas Boehler if(isset($this->cachedValues['calid'][$id])) 381185e2535SAndreas Boehler return $this->cachedValues['calid'][$id]; 382185e2535SAndreas Boehler 38351f4febbSAndreas Boehler $query = "SELECT calid FROM pagetocalendarmapping WHERE page = ?"; 38451f4febbSAndreas Boehler $res = $this->sqlite->query($query, $id); 385a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 386a1a3b679SAndreas Boehler if(isset($row['calid'])) 387185e2535SAndreas Boehler { 388185e2535SAndreas Boehler $calid = $row['calid']; 389185e2535SAndreas Boehler $this->cachedValues['calid'] = $calid; 390185e2535SAndreas Boehler return $calid; 391185e2535SAndreas Boehler } 392a1a3b679SAndreas Boehler return false; 393a1a3b679SAndreas Boehler } 394a1a3b679SAndreas Boehler 395cb71a62aSAndreas Boehler /** 396cb71a62aSAndreas Boehler * Retrieve the complete calendar id to page mapping. 397cb71a62aSAndreas Boehler * This is necessary to be able to retrieve a list of 398cb71a62aSAndreas Boehler * calendars for a given user and check the access rights. 399cb71a62aSAndreas Boehler * 400cb71a62aSAndreas Boehler * @return array The mapping array 401cb71a62aSAndreas Boehler */ 402a1a3b679SAndreas Boehler public function getCalendarIdToPageMapping() 403a1a3b679SAndreas Boehler { 404a1a3b679SAndreas Boehler $query = "SELECT calid, page FROM pagetocalendarmapping"; 405a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 406a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 407a1a3b679SAndreas Boehler return $arr; 408a1a3b679SAndreas Boehler } 409a1a3b679SAndreas Boehler 410cb71a62aSAndreas Boehler /** 411cb71a62aSAndreas Boehler * Retrieve all calendar IDs a given user has access to. 412cb71a62aSAndreas Boehler * The user is specified by the principalUri, so the 413cb71a62aSAndreas Boehler * user name is actually split from the URI component. 414cb71a62aSAndreas Boehler * 415cb71a62aSAndreas Boehler * Access rights are checked against DokuWiki's ACL 416cb71a62aSAndreas Boehler * and applied accordingly. 417cb71a62aSAndreas Boehler * 418cb71a62aSAndreas Boehler * @param string $principalUri The principal URI to work on 419cb71a62aSAndreas Boehler * 420cb71a62aSAndreas Boehler * @return array An associative array of calendar IDs 421cb71a62aSAndreas Boehler */ 422a1a3b679SAndreas Boehler public function getCalendarIdsForUser($principalUri) 423a1a3b679SAndreas Boehler { 42434a47953SAndreas Boehler global $auth; 425a1a3b679SAndreas Boehler $user = explode('/', $principalUri); 426a1a3b679SAndreas Boehler $user = end($user); 427a1a3b679SAndreas Boehler $mapping = $this->getCalendarIdToPageMapping(); 428a1a3b679SAndreas Boehler $calids = array(); 42934a47953SAndreas Boehler $ud = $auth->getUserData($user); 43034a47953SAndreas Boehler $groups = $ud['grps']; 431a1a3b679SAndreas Boehler foreach($mapping as $row) 432a1a3b679SAndreas Boehler { 433a1a3b679SAndreas Boehler $id = $row['calid']; 434a1a3b679SAndreas Boehler $page = $row['page']; 43534a47953SAndreas Boehler $acl = auth_aclcheck($page, $user, $groups); 436a1a3b679SAndreas Boehler if($acl >= AUTH_READ) 437a1a3b679SAndreas Boehler { 438a1a3b679SAndreas Boehler $write = $acl > AUTH_READ; 439a1a3b679SAndreas Boehler $calids[$id] = array('readonly' => !$write); 440a1a3b679SAndreas Boehler } 441a1a3b679SAndreas Boehler } 442a1a3b679SAndreas Boehler return $calids; 443a1a3b679SAndreas Boehler } 444a1a3b679SAndreas Boehler 445cb71a62aSAndreas Boehler /** 446cb71a62aSAndreas Boehler * Create a new calendar for a given page ID and set name and description 447cb71a62aSAndreas Boehler * accordingly. Also update the pagetocalendarmapping table on success. 448cb71a62aSAndreas Boehler * 449cb71a62aSAndreas Boehler * @param string $name The calendar's name 450cb71a62aSAndreas Boehler * @param string $description The calendar's description 451cb71a62aSAndreas Boehler * @param string $id (optional) The page ID to work on 452cb71a62aSAndreas Boehler * @param string $userid (optional) The user ID that created the calendar 453cb71a62aSAndreas Boehler * 454cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 455cb71a62aSAndreas Boehler */ 456a1a3b679SAndreas Boehler public function createCalendarForPage($name, $description, $id = null, $userid = null) 457a1a3b679SAndreas Boehler { 458a1a3b679SAndreas Boehler if(is_null($id)) 459a1a3b679SAndreas Boehler { 460a1a3b679SAndreas Boehler global $ID; 461a1a3b679SAndreas Boehler $id = $ID; 462a1a3b679SAndreas Boehler } 463a1a3b679SAndreas Boehler if(is_null($userid)) 46434a47953SAndreas Boehler { 46534a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 46634a47953SAndreas Boehler { 467a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 46834a47953SAndreas Boehler } 46934a47953SAndreas Boehler else 47034a47953SAndreas Boehler { 47134a47953SAndreas Boehler $userid = uniqid('davcal-'); 47234a47953SAndreas Boehler } 47334a47953SAndreas Boehler } 474a1a3b679SAndreas Boehler $values = array('principals/'.$userid, 475a1a3b679SAndreas Boehler $name, 476a1a3b679SAndreas Boehler str_replace(array('/', ' ', ':'), '_', $id), 477a1a3b679SAndreas Boehler $description, 478a1a3b679SAndreas Boehler 'VEVENT,VTODO', 47955a741c0SAndreas Boehler 0, 48055a741c0SAndreas Boehler 1); 48151f4febbSAndreas Boehler $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) ". 48251f4febbSAndreas Boehler "VALUES (?, ?, ?, ?, ?, ?, ?)"; 48351f4febbSAndreas Boehler $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3], $values[4], $values[5], $values[6]); 48455a741c0SAndreas Boehler if($res === false) 48555a741c0SAndreas Boehler return false; 486cb71a62aSAndreas Boehler 487cb71a62aSAndreas Boehler // Get the new calendar ID 48851f4febbSAndreas Boehler $query = "SELECT id FROM calendars WHERE principaluri = ? AND displayname = ? AND ". 48951f4febbSAndreas Boehler "uri = ? AND description = ?"; 49051f4febbSAndreas Boehler $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3]); 491a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 492cb71a62aSAndreas Boehler 493cb71a62aSAndreas Boehler // Update the pagetocalendarmapping table with the new calendar ID 494a1a3b679SAndreas Boehler if(isset($row['id'])) 495a1a3b679SAndreas Boehler { 49651f4febbSAndreas Boehler $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (?, ?)"; 49751f4febbSAndreas Boehler $res = $this->sqlite->query($query, $id, $row['id']); 49855a741c0SAndreas Boehler return ($res !== false); 499a1a3b679SAndreas Boehler } 500a1a3b679SAndreas Boehler 501a1a3b679SAndreas Boehler return false; 502a1a3b679SAndreas Boehler } 503a1a3b679SAndreas Boehler 504cb71a62aSAndreas Boehler /** 505cb71a62aSAndreas Boehler * Add a new iCal entry for a given page, i.e. a given calendar. 506cb71a62aSAndreas Boehler * 507cb71a62aSAndreas Boehler * The parameter array needs to contain 508cb71a62aSAndreas Boehler * detectedtz => The timezone as detected by the browser 50982a48dfbSAndreas Boehler * currenttz => The timezone in use by the calendar 510cb71a62aSAndreas Boehler * eventfrom => The event's start date 511cb71a62aSAndreas Boehler * eventfromtime => The event's start time 512cb71a62aSAndreas Boehler * eventto => The event's end date 513cb71a62aSAndreas Boehler * eventtotime => The event's end time 514cb71a62aSAndreas Boehler * eventname => The event's name 515cb71a62aSAndreas Boehler * eventdescription => The event's description 516cb71a62aSAndreas Boehler * 517cb71a62aSAndreas Boehler * @param string $id The page ID to work on 518cb71a62aSAndreas Boehler * @param string $user The user who created the calendar 519cb71a62aSAndreas Boehler * @param string $params A parameter array with values to create 520cb71a62aSAndreas Boehler * 521cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 522cb71a62aSAndreas Boehler */ 523a1a3b679SAndreas Boehler public function addCalendarEntryToCalendarForPage($id, $user, $params) 524a1a3b679SAndreas Boehler { 52582a48dfbSAndreas Boehler if($params['currenttz'] !== '' && $params['currenttz'] !== 'local') 52682a48dfbSAndreas Boehler $timezone = new \DateTimeZone($params['currenttz']); 52782a48dfbSAndreas Boehler elseif($params['currenttz'] === 'local') 528a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 529bd883736SAndreas Boehler else 530bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 531cb71a62aSAndreas Boehler 532cb71a62aSAndreas Boehler // Retrieve dates from settings 533b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 534b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 535b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 536b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 537cb71a62aSAndreas Boehler 538cb71a62aSAndreas Boehler // Load SabreDAV 5399bef4ad8SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 540a1a3b679SAndreas Boehler $vcalendar = new \Sabre\VObject\Component\VCalendar(); 541cb71a62aSAndreas Boehler 542cb71a62aSAndreas Boehler // Add VCalendar, UID and Event Name 543a1a3b679SAndreas Boehler $event = $vcalendar->add('VEVENT'); 544b269830cSAndreas Boehler $uuid = \Sabre\VObject\UUIDUtil::getUUID(); 545b269830cSAndreas Boehler $event->add('UID', $uuid); 546a1a3b679SAndreas Boehler $event->summary = $params['eventname']; 547cb71a62aSAndreas Boehler 548cb71a62aSAndreas Boehler // Add a description if requested 5490eebc909SAndreas Boehler $description = $params['eventdescription']; 5500eebc909SAndreas Boehler if($description !== '') 5510eebc909SAndreas Boehler $event->add('DESCRIPTION', $description); 552cb71a62aSAndreas Boehler 5534ecb526cSAndreas Boehler // Add attachments 5544ecb526cSAndreas Boehler $attachments = $params['attachments']; 55582a48dfbSAndreas Boehler if(!is_null($attachments)) 5564ecb526cSAndreas Boehler foreach($attachments as $attachment) 5574ecb526cSAndreas Boehler $event->add('ATTACH', $attachment); 5584ecb526cSAndreas Boehler 559cb71a62aSAndreas Boehler // Create a timestamp for last modified, created and dtstamp values in UTC 560b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 561b269830cSAndreas Boehler $event->add('DTSTAMP', $dtStamp); 562b269830cSAndreas Boehler $event->add('CREATED', $dtStamp); 563b269830cSAndreas Boehler $event->add('LAST-MODIFIED', $dtStamp); 564cb71a62aSAndreas Boehler 565cb71a62aSAndreas Boehler // Adjust the start date, based on the given timezone information 566b269830cSAndreas Boehler $dtStart = new \DateTime(); 567a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 568b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 569cb71a62aSAndreas Boehler 570cb71a62aSAndreas Boehler // Only add the time values if it's not an allday event 571b269830cSAndreas Boehler if($params['allday'] != '1') 572b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 573cb71a62aSAndreas Boehler 574cb71a62aSAndreas Boehler // Adjust the end date, based on the given timezone information 575b269830cSAndreas Boehler $dtEnd = new \DateTime(); 576a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 577b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 578cb71a62aSAndreas Boehler 579cb71a62aSAndreas Boehler // Only add the time values if it's not an allday event 580b269830cSAndreas Boehler if($params['allday'] != '1') 581b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 582cb71a62aSAndreas Boehler 583b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 584b269830cSAndreas Boehler if($params['allday'] == '1') 585b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 586cb71a62aSAndreas Boehler 587cb71a62aSAndreas Boehler // Really add Start and End events 588b269830cSAndreas Boehler $dtStartEv = $event->add('DTSTART', $dtStart); 589b269830cSAndreas Boehler $dtEndEv = $event->add('DTEND', $dtEnd); 590cb71a62aSAndreas Boehler 591cb71a62aSAndreas Boehler // Adjust the DATE format for allday events 592b269830cSAndreas Boehler if($params['allday'] == '1') 593b269830cSAndreas Boehler { 594b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 595b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 596b269830cSAndreas Boehler } 597cb71a62aSAndreas Boehler 598cb71a62aSAndreas Boehler // Actually add the values to the database 599a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 600a1a3b679SAndreas Boehler $uri = uniqid('dokuwiki-').'.ics'; 601a1a3b679SAndreas Boehler $now = new DateTime(); 602a1a3b679SAndreas Boehler $eventStr = $vcalendar->serialize(); 603a1a3b679SAndreas Boehler 60451f4febbSAndreas Boehler $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 60551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid, $uri, $eventStr, $now->getTimestamp(), 'VEVENT', 60651f4febbSAndreas Boehler $event->DTSTART->getDateTime()->getTimeStamp(), $event->DTEND->getDateTime()->getTimeStamp(), 60751f4febbSAndreas Boehler strlen($eventStr), md5($eventStr), $uuid); 608cb71a62aSAndreas Boehler 609cb71a62aSAndreas Boehler // If successfully, update the sync token database 61055a741c0SAndreas Boehler if($res !== false) 61155a741c0SAndreas Boehler { 61255a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'added'); 613a1a3b679SAndreas Boehler return true; 614a1a3b679SAndreas Boehler } 61555a741c0SAndreas Boehler return false; 61655a741c0SAndreas Boehler } 617a1a3b679SAndreas Boehler 618cb71a62aSAndreas Boehler /** 619cb71a62aSAndreas Boehler * Retrieve the calendar settings of a given calendar id 620cb71a62aSAndreas Boehler * 621cb71a62aSAndreas Boehler * @param string $calid The calendar ID 622cb71a62aSAndreas Boehler * 623cb71a62aSAndreas Boehler * @return array The calendar settings array 624cb71a62aSAndreas Boehler */ 625b269830cSAndreas Boehler public function getCalendarSettings($calid) 626b269830cSAndreas Boehler { 62751f4febbSAndreas Boehler $query = "SELECT principaluri, calendarcolor, displayname, uri, description, components, transparent, synctoken FROM calendars WHERE id= ? "; 62851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 629b269830cSAndreas Boehler $row = $this->sqlite->res2row($res); 630b269830cSAndreas Boehler return $row; 631b269830cSAndreas Boehler } 632b269830cSAndreas Boehler 633cb71a62aSAndreas Boehler /** 634cb71a62aSAndreas Boehler * Retrieve all events that are within a given date range, 635cb71a62aSAndreas Boehler * based on the timezone setting. 636cb71a62aSAndreas Boehler * 637cb71a62aSAndreas Boehler * There is also support for retrieving recurring events, 638cb71a62aSAndreas Boehler * using Sabre's VObject Iterator. Recurring events are represented 639cb71a62aSAndreas Boehler * as individual calendar entries with the same UID. 640cb71a62aSAndreas Boehler * 641cb71a62aSAndreas Boehler * @param string $id The page ID to work with 642cb71a62aSAndreas Boehler * @param string $user The user ID to work with 643cb71a62aSAndreas Boehler * @param string $startDate The start date as a string 644cb71a62aSAndreas Boehler * @param string $endDate The end date as a string 645*4a2bf5eeSAndreas Boehler * @param string $color (optional) The calendar's color 646cb71a62aSAndreas Boehler * 647cb71a62aSAndreas Boehler * @return array An array containing the calendar entries. 648cb71a62aSAndreas Boehler */ 649*4a2bf5eeSAndreas Boehler public function getEventsWithinDateRange($id, $user, $startDate, $endDate, $timezone, $color = null) 650a1a3b679SAndreas Boehler { 65182a48dfbSAndreas Boehler if($timezone !== '' && $timezone !== 'local') 65282a48dfbSAndreas Boehler $timezone = new \DateTimeZone($timezone); 653bd883736SAndreas Boehler else 654bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 655a1a3b679SAndreas Boehler $data = array(); 656cb71a62aSAndreas Boehler 657cb71a62aSAndreas Boehler // Load SabreDAV 6589bef4ad8SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 659a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 660*4a2bf5eeSAndreas Boehler if(is_null($color)) 661185e2535SAndreas Boehler $color = $this->getCalendarColorForCalendar($calid); 662a469597cSAndreas Boehler $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid = ?"; 663a469597cSAndreas Boehler $startTs = null; 664a469597cSAndreas Boehler $endTs = null; 665a469597cSAndreas Boehler if($startDate !== null) 666a469597cSAndreas Boehler { 667a1a3b679SAndreas Boehler $startTs = new \DateTime($startDate); 668a469597cSAndreas Boehler $query .= " AND lastoccurence > ".$this->sqlite->quote_string($startTs->getTimestamp()); 669a469597cSAndreas Boehler } 670a469597cSAndreas Boehler if($endDate !== null) 671a469597cSAndreas Boehler { 672a1a3b679SAndreas Boehler $endTs = new \DateTime($endDate); 673a469597cSAndreas Boehler $query .= " AND firstoccurence < ".$this->sqlite->quote_string($endTs->getTimestamp()); 674a469597cSAndreas Boehler } 675cb71a62aSAndreas Boehler 676cb71a62aSAndreas Boehler // Retrieve matching calendar objects 677a469597cSAndreas Boehler $res = $this->sqlite->query($query, $calid); 678a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 679cb71a62aSAndreas Boehler 680cb71a62aSAndreas Boehler // Parse individual calendar entries 681a1a3b679SAndreas Boehler foreach($arr as $row) 682a1a3b679SAndreas Boehler { 683a1a3b679SAndreas Boehler if(isset($row['calendardata'])) 684a1a3b679SAndreas Boehler { 685b269830cSAndreas Boehler $entry = array(); 686a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($row['calendardata']); 687ebc4eb57SAndreas Boehler $recurrence = $vcal->VEVENT->RRULE; 688cb71a62aSAndreas Boehler // If it is a recurring event, pass it through Sabre's EventIterator 689ebc4eb57SAndreas Boehler if($recurrence != null) 690ebc4eb57SAndreas Boehler { 691ebc4eb57SAndreas Boehler $rEvents = new \Sabre\VObject\Recur\EventIterator(array($vcal->VEVENT)); 692ebc4eb57SAndreas Boehler $rEvents->rewind(); 693e9b7d302SAndreas Boehler while($rEvents->valid()) 694ebc4eb57SAndreas Boehler { 695ebc4eb57SAndreas Boehler $event = $rEvents->getEventObject(); 696cb71a62aSAndreas Boehler // If we are after the given time range, exit 697a469597cSAndreas Boehler if(($endTs !== null) && ($rEvents->getDtStart()->getTimestamp() > $endTs->getTimestamp())) 698e9b7d302SAndreas Boehler break; 699cb71a62aSAndreas Boehler 700cb71a62aSAndreas Boehler // If we are before the given time range, continue 701a469597cSAndreas Boehler if(($startTs != null) && ($rEvents->getDtEnd()->getTimestamp() < $startTs->getTimestamp())) 702ebc4eb57SAndreas Boehler { 703ebc4eb57SAndreas Boehler $rEvents->next(); 704ebc4eb57SAndreas Boehler continue; 705ebc4eb57SAndreas Boehler } 706cb71a62aSAndreas Boehler 707cb71a62aSAndreas Boehler // If we are within the given time range, parse the event 708185e2535SAndreas Boehler $data[] = $this->convertIcalDataToEntry($event, $id, $timezone, $row['uid'], $color, true); 709ebc4eb57SAndreas Boehler $rEvents->next(); 710ebc4eb57SAndreas Boehler } 711ebc4eb57SAndreas Boehler } 712ebc4eb57SAndreas Boehler else 713185e2535SAndreas Boehler $data[] = $this->convertIcalDataToEntry($vcal->VEVENT, $id, $timezone, $row['uid'], $color); 714ebc4eb57SAndreas Boehler } 715ebc4eb57SAndreas Boehler } 716ebc4eb57SAndreas Boehler return $data; 717ebc4eb57SAndreas Boehler } 718ebc4eb57SAndreas Boehler 719cb71a62aSAndreas Boehler /** 720cb71a62aSAndreas Boehler * Helper function that parses the iCal data of a VEVENT to a calendar entry. 721cb71a62aSAndreas Boehler * 722cb71a62aSAndreas Boehler * @param \Sabre\VObject\VEvent $event The event to parse 723cb71a62aSAndreas Boehler * @param \DateTimeZone $timezone The timezone object 724cb71a62aSAndreas Boehler * @param string $uid The entry's UID 7253c86dda8SAndreas Boehler * @param boolean $recurring (optional) Set to true to define a recurring event 726cb71a62aSAndreas Boehler * 727cb71a62aSAndreas Boehler * @return array The parse calendar entry 728cb71a62aSAndreas Boehler */ 729185e2535SAndreas Boehler private function convertIcalDataToEntry($event, $page, $timezone, $uid, $color, $recurring = false) 730ebc4eb57SAndreas Boehler { 731ebc4eb57SAndreas Boehler $entry = array(); 732ebc4eb57SAndreas Boehler $start = $event->DTSTART; 733cb71a62aSAndreas Boehler // Parse only if the start date/time is present 734b269830cSAndreas Boehler if($start !== null) 735b269830cSAndreas Boehler { 736b269830cSAndreas Boehler $dtStart = $start->getDateTime(); 737b269830cSAndreas Boehler $dtStart->setTimezone($timezone); 738bf0ad2b4SAndreas Boehler 739bf0ad2b4SAndreas Boehler // moment.js doesn't like times be given even if 740bf0ad2b4SAndreas Boehler // allDay is set to true 741bf0ad2b4SAndreas Boehler // This should fix T23 742b269830cSAndreas Boehler if($start['VALUE'] == 'DATE') 743bf0ad2b4SAndreas Boehler { 744b269830cSAndreas Boehler $entry['allDay'] = true; 745bf0ad2b4SAndreas Boehler $entry['start'] = $dtStart->format("Y-m-d"); 746bf0ad2b4SAndreas Boehler } 747b269830cSAndreas Boehler else 748bf0ad2b4SAndreas Boehler { 749b269830cSAndreas Boehler $entry['allDay'] = false; 750bf0ad2b4SAndreas Boehler $entry['start'] = $dtStart->format(\DateTime::ATOM); 751bf0ad2b4SAndreas Boehler } 752b269830cSAndreas Boehler } 753ebc4eb57SAndreas Boehler $end = $event->DTEND; 754bf0ad2b4SAndreas Boehler // Parse only if the end date/time is present 755b269830cSAndreas Boehler if($end !== null) 756b269830cSAndreas Boehler { 757b269830cSAndreas Boehler $dtEnd = $end->getDateTime(); 758b269830cSAndreas Boehler $dtEnd->setTimezone($timezone); 759bf0ad2b4SAndreas Boehler if($end['VALUE'] == 'DATE') 760bf0ad2b4SAndreas Boehler $entry['end'] = $dtEnd->format("Y-m-d"); 761bf0ad2b4SAndreas Boehler else 762b269830cSAndreas Boehler $entry['end'] = $dtEnd->format(\DateTime::ATOM); 763b269830cSAndreas Boehler } 764ebc4eb57SAndreas Boehler $description = $event->DESCRIPTION; 7650eebc909SAndreas Boehler if($description !== null) 7660eebc909SAndreas Boehler $entry['description'] = (string)$description; 7670eebc909SAndreas Boehler else 7680eebc909SAndreas Boehler $entry['description'] = ''; 7694ecb526cSAndreas Boehler $attachments = $event->ATTACH; 7704ecb526cSAndreas Boehler if($attachments !== null) 7714ecb526cSAndreas Boehler { 7724ecb526cSAndreas Boehler $entry['attachments'] = array(); 7734ecb526cSAndreas Boehler foreach($attachments as $attachment) 7744ecb526cSAndreas Boehler $entry['attachments'][] = (string)$attachment; 7754ecb526cSAndreas Boehler } 776ebc4eb57SAndreas Boehler $entry['title'] = (string)$event->summary; 777ebc4eb57SAndreas Boehler $entry['id'] = $uid; 778185e2535SAndreas Boehler $entry['page'] = $page; 779185e2535SAndreas Boehler $entry['color'] = $color; 7803c86dda8SAndreas Boehler $entry['recurring'] = $recurring; 781185e2535SAndreas Boehler 782ebc4eb57SAndreas Boehler return $entry; 783a1a3b679SAndreas Boehler } 784a1a3b679SAndreas Boehler 785cb71a62aSAndreas Boehler /** 786cb71a62aSAndreas Boehler * Retrieve an event by its UID 787cb71a62aSAndreas Boehler * 788cb71a62aSAndreas Boehler * @param string $uid The event's UID 789cb71a62aSAndreas Boehler * 790cb71a62aSAndreas Boehler * @return mixed The table row with the given event 791cb71a62aSAndreas Boehler */ 792a1a3b679SAndreas Boehler public function getEventWithUid($uid) 793a1a3b679SAndreas Boehler { 79451f4febbSAndreas Boehler $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid = ?"; 79551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uid); 796a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 797a1a3b679SAndreas Boehler return $row; 798a1a3b679SAndreas Boehler } 799a1a3b679SAndreas Boehler 800cb71a62aSAndreas Boehler /** 801cb71a62aSAndreas Boehler * Retrieve all calendar events for a given calendar ID 802cb71a62aSAndreas Boehler * 803cb71a62aSAndreas Boehler * @param string $calid The calendar's ID 804cb71a62aSAndreas Boehler * 805cb71a62aSAndreas Boehler * @return array An array containing all calendar data 806cb71a62aSAndreas Boehler */ 807f69bb449SAndreas Boehler public function getAllCalendarEvents($calid) 808f69bb449SAndreas Boehler { 8097e0b8590SAndreas Boehler $query = "SELECT calendardata, uid, componenttype, uri FROM calendarobjects WHERE calendarid = ?"; 81051f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 811f69bb449SAndreas Boehler $arr = $this->sqlite->res2arr($res); 812f69bb449SAndreas Boehler return $arr; 813f69bb449SAndreas Boehler } 814f69bb449SAndreas Boehler 815cb71a62aSAndreas Boehler /** 816cb71a62aSAndreas Boehler * Edit a calendar entry for a page, given by its parameters. 817cb71a62aSAndreas Boehler * The params array has the same format as @see addCalendarEntryForPage 818cb71a62aSAndreas Boehler * 819cb71a62aSAndreas Boehler * @param string $id The page's ID to work on 820cb71a62aSAndreas Boehler * @param string $user The user's ID to work on 821cb71a62aSAndreas Boehler * @param array $params The parameter array for the edited calendar event 822cb71a62aSAndreas Boehler * 823cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 824cb71a62aSAndreas Boehler */ 825a1a3b679SAndreas Boehler public function editCalendarEntryForPage($id, $user, $params) 826a1a3b679SAndreas Boehler { 82782a48dfbSAndreas Boehler if($params['currenttz'] !== '' && $params['currenttz'] !== 'local') 82882a48dfbSAndreas Boehler $timezone = new \DateTimeZone($params['currenttz']); 82982a48dfbSAndreas Boehler elseif($params['currenttz'] === 'local') 830a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 831bd883736SAndreas Boehler else 832bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 833cb71a62aSAndreas Boehler 834cb71a62aSAndreas Boehler // Parse dates 835b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 836b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 837b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 838b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 839cb71a62aSAndreas Boehler 840cb71a62aSAndreas Boehler // Retrieve the existing event based on the UID 84155a741c0SAndreas Boehler $uid = $params['uid']; 84255a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 843cb71a62aSAndreas Boehler 844cb71a62aSAndreas Boehler // Load SabreDAV 8459bef4ad8SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 846a1a3b679SAndreas Boehler if(!isset($event['calendardata'])) 847a1a3b679SAndreas Boehler return false; 84855a741c0SAndreas Boehler $uri = $event['uri']; 84955a741c0SAndreas Boehler $calid = $event['calendarid']; 850cb71a62aSAndreas Boehler 851cb71a62aSAndreas Boehler // Parse the existing event 852a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 853b269830cSAndreas Boehler $vevent = $vcal->VEVENT; 854cb71a62aSAndreas Boehler 855cb71a62aSAndreas Boehler // Set the new event values 856b269830cSAndreas Boehler $vevent->summary = $params['eventname']; 857b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 8580eebc909SAndreas Boehler $description = $params['eventdescription']; 859cb71a62aSAndreas Boehler 860cb71a62aSAndreas Boehler // Remove existing timestamps to overwrite them 8610eebc909SAndreas Boehler $vevent->remove('DESCRIPTION'); 862b269830cSAndreas Boehler $vevent->remove('DTSTAMP'); 863b269830cSAndreas Boehler $vevent->remove('LAST-MODIFIED'); 8644ecb526cSAndreas Boehler $vevent->remove('ATTACH'); 865cb71a62aSAndreas Boehler 866cb71a62aSAndreas Boehler // Add new time stamps and description 867b269830cSAndreas Boehler $vevent->add('DTSTAMP', $dtStamp); 868b269830cSAndreas Boehler $vevent->add('LAST-MODIFIED', $dtStamp); 8690eebc909SAndreas Boehler if($description !== '') 8700eebc909SAndreas Boehler $vevent->add('DESCRIPTION', $description); 871cb71a62aSAndreas Boehler 8724ecb526cSAndreas Boehler // Add attachments 8734ecb526cSAndreas Boehler $attachments = $params['attachments']; 87482a48dfbSAndreas Boehler if(!is_null($attachments)) 8754ecb526cSAndreas Boehler foreach($attachments as $attachment) 8764ecb526cSAndreas Boehler $vevent->add('ATTACH', $attachment); 8774ecb526cSAndreas Boehler 878cb71a62aSAndreas Boehler // Setup DTSTART 879b269830cSAndreas Boehler $dtStart = new \DateTime(); 880a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 881b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 882b269830cSAndreas Boehler if($params['allday'] != '1') 883b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 884cb71a62aSAndreas Boehler 8854ecb526cSAndreas Boehler // Setup DTEND 886b269830cSAndreas Boehler $dtEnd = new \DateTime(); 887a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 888b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 889b269830cSAndreas Boehler if($params['allday'] != '1') 890b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 891cb71a62aSAndreas Boehler 892b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 893b269830cSAndreas Boehler if($params['allday'] == '1') 894b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 895b269830cSAndreas Boehler $vevent->remove('DTSTART'); 896b269830cSAndreas Boehler $vevent->remove('DTEND'); 897b269830cSAndreas Boehler $dtStartEv = $vevent->add('DTSTART', $dtStart); 898b269830cSAndreas Boehler $dtEndEv = $vevent->add('DTEND', $dtEnd); 899cb71a62aSAndreas Boehler 900cb71a62aSAndreas Boehler // Remove the time for allday events 901b269830cSAndreas Boehler if($params['allday'] == '1') 902b269830cSAndreas Boehler { 903b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 904b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 905b269830cSAndreas Boehler } 906a1a3b679SAndreas Boehler $now = new DateTime(); 907a1a3b679SAndreas Boehler $eventStr = $vcal->serialize(); 908cb71a62aSAndreas Boehler // Actually write to the database 90951f4febbSAndreas Boehler $query = "UPDATE calendarobjects SET calendardata = ?, lastmodified = ?, ". 91051f4febbSAndreas Boehler "firstoccurence = ?, lastoccurence = ?, size = ?, etag = ? WHERE uid = ?"; 91151f4febbSAndreas Boehler $res = $this->sqlite->query($query, $eventStr, $now->getTimestamp(), $dtStart->getTimestamp(), 91251f4febbSAndreas Boehler $dtEnd->getTimestamp(), strlen($eventStr), md5($eventStr), $uid); 91355a741c0SAndreas Boehler if($res !== false) 91455a741c0SAndreas Boehler { 91555a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'modified'); 916a1a3b679SAndreas Boehler return true; 917a1a3b679SAndreas Boehler } 91855a741c0SAndreas Boehler return false; 91955a741c0SAndreas Boehler } 920a1a3b679SAndreas Boehler 921cb71a62aSAndreas Boehler /** 922cb71a62aSAndreas Boehler * Delete a calendar entry for a given page. Actually, the event is removed 923cb71a62aSAndreas Boehler * based on the entry's UID, so that page ID is no used. 924cb71a62aSAndreas Boehler * 925cb71a62aSAndreas Boehler * @param string $id The page's ID (unused) 926cb71a62aSAndreas Boehler * @param array $params The parameter array to work with 927cb71a62aSAndreas Boehler * 928cb71a62aSAndreas Boehler * @return boolean True 929cb71a62aSAndreas Boehler */ 930a1a3b679SAndreas Boehler public function deleteCalendarEntryForPage($id, $params) 931a1a3b679SAndreas Boehler { 932a1a3b679SAndreas Boehler $uid = $params['uid']; 93355a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 9342c14b82bSAndreas Boehler $calid = $event['calendarid']; 93555a741c0SAndreas Boehler $uri = $event['uri']; 93651f4febbSAndreas Boehler $query = "DELETE FROM calendarobjects WHERE uid = ?"; 93751f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uid); 93855a741c0SAndreas Boehler if($res !== false) 93955a741c0SAndreas Boehler { 94055a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'deleted'); 94155a741c0SAndreas Boehler } 942a1a3b679SAndreas Boehler return true; 943a1a3b679SAndreas Boehler } 944a1a3b679SAndreas Boehler 945cb71a62aSAndreas Boehler /** 946cb71a62aSAndreas Boehler * Retrieve the current sync token for a calendar 947cb71a62aSAndreas Boehler * 948cb71a62aSAndreas Boehler * @param string $calid The calendar id 949cb71a62aSAndreas Boehler * 950cb71a62aSAndreas Boehler * @return mixed The synctoken or false 951cb71a62aSAndreas Boehler */ 95255a741c0SAndreas Boehler public function getSyncTokenForCalendar($calid) 95355a741c0SAndreas Boehler { 954b269830cSAndreas Boehler $row = $this->getCalendarSettings($calid); 95555a741c0SAndreas Boehler if(isset($row['synctoken'])) 95655a741c0SAndreas Boehler return $row['synctoken']; 95755a741c0SAndreas Boehler return false; 95855a741c0SAndreas Boehler } 95955a741c0SAndreas Boehler 960cb71a62aSAndreas Boehler /** 961cb71a62aSAndreas Boehler * Helper function to convert the operation name to 962cb71a62aSAndreas Boehler * an operation code as stored in the database 963cb71a62aSAndreas Boehler * 964cb71a62aSAndreas Boehler * @param string $operationName The operation name 965cb71a62aSAndreas Boehler * 966cb71a62aSAndreas Boehler * @return mixed The operation code or false 967cb71a62aSAndreas Boehler */ 96855a741c0SAndreas Boehler public function operationNameToOperation($operationName) 96955a741c0SAndreas Boehler { 97055a741c0SAndreas Boehler switch($operationName) 97155a741c0SAndreas Boehler { 97255a741c0SAndreas Boehler case 'added': 97355a741c0SAndreas Boehler return 1; 97455a741c0SAndreas Boehler break; 97555a741c0SAndreas Boehler case 'modified': 97655a741c0SAndreas Boehler return 2; 97755a741c0SAndreas Boehler break; 97855a741c0SAndreas Boehler case 'deleted': 97955a741c0SAndreas Boehler return 3; 98055a741c0SAndreas Boehler break; 98155a741c0SAndreas Boehler } 98255a741c0SAndreas Boehler return false; 98355a741c0SAndreas Boehler } 98455a741c0SAndreas Boehler 985cb71a62aSAndreas Boehler /** 986cb71a62aSAndreas Boehler * Update the sync token log based on the calendar id and the 987cb71a62aSAndreas Boehler * operation that was performed. 988cb71a62aSAndreas Boehler * 989cb71a62aSAndreas Boehler * @param string $calid The calendar ID that was modified 990cb71a62aSAndreas Boehler * @param string $uri The calendar URI that was modified 991cb71a62aSAndreas Boehler * @param string $operation The operation that was performed 992cb71a62aSAndreas Boehler * 993cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 994cb71a62aSAndreas Boehler */ 99555a741c0SAndreas Boehler private function updateSyncTokenLog($calid, $uri, $operation) 99655a741c0SAndreas Boehler { 99755a741c0SAndreas Boehler $currentToken = $this->getSyncTokenForCalendar($calid); 99855a741c0SAndreas Boehler $operationCode = $this->operationNameToOperation($operation); 99955a741c0SAndreas Boehler if(($operationCode === false) || ($currentToken === false)) 100055a741c0SAndreas Boehler return false; 100155a741c0SAndreas Boehler $values = array($uri, 100255a741c0SAndreas Boehler $currentToken, 100355a741c0SAndreas Boehler $calid, 100455a741c0SAndreas Boehler $operationCode 100555a741c0SAndreas Boehler ); 100651f4febbSAndreas Boehler $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(?, ?, ?, ?)"; 100751f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uri, $currentToken, $calid, $operationCode); 100855a741c0SAndreas Boehler if($res === false) 100955a741c0SAndreas Boehler return false; 101055a741c0SAndreas Boehler $currentToken++; 101151f4febbSAndreas Boehler $query = "UPDATE calendars SET synctoken = ? WHERE id = ?"; 101251f4febbSAndreas Boehler $res = $this->sqlite->query($query, $currentToken, $calid); 101355a741c0SAndreas Boehler return ($res !== false); 101455a741c0SAndreas Boehler } 101555a741c0SAndreas Boehler 1016cb71a62aSAndreas Boehler /** 1017cb71a62aSAndreas Boehler * Return the sync URL for a given Page, i.e. a calendar 1018cb71a62aSAndreas Boehler * 1019cb71a62aSAndreas Boehler * @param string $id The page's ID 1020cb71a62aSAndreas Boehler * @param string $user (optional) The user's ID 1021cb71a62aSAndreas Boehler * 1022cb71a62aSAndreas Boehler * @return mixed The sync url or false 1023cb71a62aSAndreas Boehler */ 1024b269830cSAndreas Boehler public function getSyncUrlForPage($id, $user = null) 1025b269830cSAndreas Boehler { 102634a47953SAndreas Boehler if(is_null($userid)) 102734a47953SAndreas Boehler { 102834a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 102934a47953SAndreas Boehler { 103034a47953SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 103134a47953SAndreas Boehler } 103234a47953SAndreas Boehler else 103334a47953SAndreas Boehler { 103434a47953SAndreas Boehler return false; 103534a47953SAndreas Boehler } 103634a47953SAndreas Boehler } 1037b269830cSAndreas Boehler 1038b269830cSAndreas Boehler $calid = $this->getCalendarIdForPage($id); 1039b269830cSAndreas Boehler if($calid === false) 1040b269830cSAndreas Boehler return false; 1041b269830cSAndreas Boehler 1042b269830cSAndreas Boehler $calsettings = $this->getCalendarSettings($calid); 1043b269830cSAndreas Boehler if(!isset($calsettings['uri'])) 1044b269830cSAndreas Boehler return false; 1045b269830cSAndreas Boehler 1046b269830cSAndreas Boehler $syncurl = DOKU_URL.'lib/plugins/davcal/calendarserver.php/calendars/'.$user.'/'.$calsettings['uri']; 1047b269830cSAndreas Boehler return $syncurl; 1048b269830cSAndreas Boehler } 1049b269830cSAndreas Boehler 1050cb71a62aSAndreas Boehler /** 1051cb71a62aSAndreas Boehler * Return the private calendar's URL for a given page 1052cb71a62aSAndreas Boehler * 1053cb71a62aSAndreas Boehler * @param string $id the page ID 1054cb71a62aSAndreas Boehler * 1055cb71a62aSAndreas Boehler * @return mixed The private URL or false 1056cb71a62aSAndreas Boehler */ 1057f69bb449SAndreas Boehler public function getPrivateURLForPage($id) 1058f69bb449SAndreas Boehler { 1059f69bb449SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 1060f69bb449SAndreas Boehler if($calid === false) 1061f69bb449SAndreas Boehler return false; 1062f69bb449SAndreas Boehler 1063f69bb449SAndreas Boehler return $this->getPrivateURLForCalendar($calid); 1064f69bb449SAndreas Boehler } 1065f69bb449SAndreas Boehler 1066cb71a62aSAndreas Boehler /** 1067cb71a62aSAndreas Boehler * Return the private calendar's URL for a given calendar ID 1068cb71a62aSAndreas Boehler * 1069cb71a62aSAndreas Boehler * @param string $calid The calendar's ID 1070cb71a62aSAndreas Boehler * 1071cb71a62aSAndreas Boehler * @return mixed The private URL or false 1072cb71a62aSAndreas Boehler */ 1073f69bb449SAndreas Boehler public function getPrivateURLForCalendar($calid) 1074f69bb449SAndreas Boehler { 1075185e2535SAndreas Boehler if(isset($this->cachedValues['privateurl'][$calid])) 1076185e2535SAndreas Boehler return $this->cachedValues['privateurl'][$calid]; 107751f4febbSAndreas Boehler $query = "SELECT url FROM calendartoprivateurlmapping WHERE calid = ?"; 107851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 1079f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 1080f69bb449SAndreas Boehler if(!isset($row['url'])) 1081f69bb449SAndreas Boehler { 1082f69bb449SAndreas Boehler $url = uniqid("dokuwiki-").".ics"; 108351f4febbSAndreas Boehler $query = "INSERT INTO calendartoprivateurlmapping (url, calid) VALUES(?, ?)"; 108451f4febbSAndreas Boehler $res = $this->sqlite->query($query, $url, $calid); 1085f69bb449SAndreas Boehler if($res === false) 1086f69bb449SAndreas Boehler return false; 1087f69bb449SAndreas Boehler } 1088f69bb449SAndreas Boehler else 1089f69bb449SAndreas Boehler { 1090f69bb449SAndreas Boehler $url = $row['url']; 1091f69bb449SAndreas Boehler } 1092185e2535SAndreas Boehler 1093185e2535SAndreas Boehler $url = DOKU_URL.'lib/plugins/davcal/ics.php/'.$url; 1094185e2535SAndreas Boehler $this->cachedValues['privateurl'][$calid] = $url; 1095185e2535SAndreas Boehler return $url; 1096f69bb449SAndreas Boehler } 1097f69bb449SAndreas Boehler 1098cb71a62aSAndreas Boehler /** 1099cb71a62aSAndreas Boehler * Retrieve the calendar ID for a given private calendar URL 1100cb71a62aSAndreas Boehler * 1101cb71a62aSAndreas Boehler * @param string $url The private URL 1102cb71a62aSAndreas Boehler * 1103cb71a62aSAndreas Boehler * @return mixed The calendar ID or false 1104cb71a62aSAndreas Boehler */ 1105f69bb449SAndreas Boehler public function getCalendarForPrivateURL($url) 1106f69bb449SAndreas Boehler { 110751f4febbSAndreas Boehler $query = "SELECT calid FROM calendartoprivateurlmapping WHERE url = ?"; 110851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $url); 1109f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 1110f69bb449SAndreas Boehler if(!isset($row['calid'])) 1111f69bb449SAndreas Boehler return false; 1112f69bb449SAndreas Boehler return $row['calid']; 1113f69bb449SAndreas Boehler } 1114f69bb449SAndreas Boehler 1115cb71a62aSAndreas Boehler /** 1116cb71a62aSAndreas Boehler * Return a given calendar as ICS feed, i.e. all events in one ICS file. 1117cb71a62aSAndreas Boehler * 11187e0b8590SAndreas Boehler * @param string $calid The calendar ID to retrieve 1119cb71a62aSAndreas Boehler * 1120cb71a62aSAndreas Boehler * @return mixed The calendar events as string or false 1121cb71a62aSAndreas Boehler */ 1122f69bb449SAndreas Boehler public function getCalendarAsICSFeed($calid) 1123f69bb449SAndreas Boehler { 1124f69bb449SAndreas Boehler $calSettings = $this->getCalendarSettings($calid); 1125f69bb449SAndreas Boehler if($calSettings === false) 1126f69bb449SAndreas Boehler return false; 1127f69bb449SAndreas Boehler $events = $this->getAllCalendarEvents($calid); 1128f69bb449SAndreas Boehler if($events === false) 1129f69bb449SAndreas Boehler return false; 1130f69bb449SAndreas Boehler 11317e0b8590SAndreas Boehler // Load SabreDAV 11327e0b8590SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 11337e0b8590SAndreas Boehler $out = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//DAVCal//DAVCal for DokuWiki//EN\r\nCALSCALE:GREGORIAN\r\nX-WR-CALNAME:"; 11347e0b8590SAndreas Boehler $out .= $calSettings['displayname']."\r\n"; 1135f69bb449SAndreas Boehler foreach($events as $event) 1136f69bb449SAndreas Boehler { 11377e0b8590SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 11387e0b8590SAndreas Boehler $evt = $vcal->VEVENT; 11397e0b8590SAndreas Boehler $out .= $evt->serialize(); 1140f69bb449SAndreas Boehler } 11417e0b8590SAndreas Boehler $out .= "END:VCALENDAR\r\n"; 1142f69bb449SAndreas Boehler return $out; 1143f69bb449SAndreas Boehler } 1144f69bb449SAndreas Boehler 11457c7c6b0bSAndreas Boehler /** 11467c7c6b0bSAndreas Boehler * Retrieve a configuration option for the plugin 11477c7c6b0bSAndreas Boehler * 11487c7c6b0bSAndreas Boehler * @param string $key The key to query 114921d04f73SAndreas Boehler * @return mixed The option set, null if not found 11507c7c6b0bSAndreas Boehler */ 11517c7c6b0bSAndreas Boehler public function getConfig($key) 11527c7c6b0bSAndreas Boehler { 11537c7c6b0bSAndreas Boehler return $this->getConf($key); 11547c7c6b0bSAndreas Boehler } 11557c7c6b0bSAndreas Boehler 1156a1a3b679SAndreas Boehler} 1157