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 { 940b805092SAndreas Boehler // WebDAV Connections are always readable 950b805092SAndreas Boehler if(strpos($page, 'webdav://') === 0) 960b805092SAndreas Boehler { 970b805092SAndreas Boehler $retList[$page] = $data; 980b805092SAndreas Boehler } 990b805092SAndreas Boehler elseif(auth_quickaclcheck($page) >= AUTH_READ) 10080e1ddf7SAndreas Boehler { 10180e1ddf7SAndreas Boehler $retList[$page] = $data; 10280e1ddf7SAndreas Boehler } 10380e1ddf7SAndreas Boehler } 10480e1ddf7SAndreas Boehler return $retList; 10580e1ddf7SAndreas Boehler } 10680e1ddf7SAndreas Boehler 10780e1ddf7SAndreas Boehler /** 108185e2535SAndreas Boehler * Get all calendar pages used by a given page 109185e2535SAndreas Boehler * based on the stored metadata 110185e2535SAndreas Boehler * 111185e2535SAndreas Boehler * @param string $id optional The page id 112185e2535SAndreas Boehler * @return mixed The pages as array or false 113185e2535SAndreas Boehler */ 114185e2535SAndreas Boehler public function getCalendarPagesByMeta($id = null) 115185e2535SAndreas Boehler { 116185e2535SAndreas Boehler if(is_null($id)) 117185e2535SAndreas Boehler { 118185e2535SAndreas Boehler global $ID; 119185e2535SAndreas Boehler $id = $ID; 120185e2535SAndreas Boehler } 121185e2535SAndreas Boehler 122185e2535SAndreas Boehler $meta = $this->getCalendarMetaForPage($id); 1230b805092SAndreas Boehler 124185e2535SAndreas Boehler if(isset($meta['id'])) 125ed764890SAndreas Boehler { 126ed764890SAndreas Boehler // Filter the list of pages by permission 12780e1ddf7SAndreas Boehler $pages = $this->filterCalendarPagesByUserPermission($meta['id']); 12880e1ddf7SAndreas Boehler if(empty($pages)) 129ed764890SAndreas Boehler return false; 13080e1ddf7SAndreas Boehler return $pages; 131ed764890SAndreas Boehler } 132185e2535SAndreas Boehler return false; 133185e2535SAndreas Boehler } 134185e2535SAndreas Boehler 135185e2535SAndreas Boehler /** 136185e2535SAndreas Boehler * Get a list of calendar names/pages/ids/colors 137185e2535SAndreas Boehler * for an array of page ids 138185e2535SAndreas Boehler * 139185e2535SAndreas Boehler * @param array $calendarPages The calendar pages to retrieve 140185e2535SAndreas Boehler * @return array The list 141185e2535SAndreas Boehler */ 142185e2535SAndreas Boehler public function getCalendarMapForIDs($calendarPages) 143185e2535SAndreas Boehler { 144185e2535SAndreas Boehler $data = array(); 1454a2bf5eeSAndreas Boehler foreach($calendarPages as $page => $color) 146185e2535SAndreas Boehler { 1470b805092SAndreas Boehler if(strpos($page, 'webdav://') === 0) 1480b805092SAndreas Boehler { 1490b805092SAndreas Boehler $wdc =& plugin_load('helper', 'webdavclient'); 1500b805092SAndreas Boehler if(is_null($wdc)) 1510b805092SAndreas Boehler continue; 1520b805092SAndreas Boehler $connectionId = str_replace('webdav://', '', $page); 1530b805092SAndreas Boehler $settings = $wdc->getConnection($connectionId); 1540b805092SAndreas Boehler $name = $settings['displayname']; 155*809cb0faSAndreas Boehler $write = $settings['write']; 1560b805092SAndreas Boehler $calid = $connectionId; 1570b805092SAndreas Boehler } 1580b805092SAndreas Boehler else 1590b805092SAndreas Boehler { 160185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($page); 161185e2535SAndreas Boehler if($calid !== false) 162185e2535SAndreas Boehler { 163185e2535SAndreas Boehler $settings = $this->getCalendarSettings($calid); 164185e2535SAndreas Boehler $name = $settings['displayname']; 1650b805092SAndreas Boehler //$color = $settings['calendarcolor']; 166ed764890SAndreas Boehler $write = (auth_quickaclcheck($page) > AUTH_READ); 1670b805092SAndreas Boehler } 1680b805092SAndreas Boehler else 1690b805092SAndreas Boehler { 1700b805092SAndreas Boehler continue; 1710b805092SAndreas Boehler } 1720b805092SAndreas Boehler } 173185e2535SAndreas Boehler $data[] = array('name' => $name, 'page' => $page, 'calid' => $calid, 174ed764890SAndreas Boehler 'color' => $color, 'write' => $write); 175185e2535SAndreas Boehler } 176185e2535SAndreas Boehler return $data; 177185e2535SAndreas Boehler } 178185e2535SAndreas Boehler 179185e2535SAndreas Boehler /** 180185e2535SAndreas Boehler * Get the saved calendar color for a given page. 181185e2535SAndreas Boehler * 182185e2535SAndreas Boehler * @param string $id optional The page ID 183185e2535SAndreas Boehler * @return mixed The color on success, otherwise false 184185e2535SAndreas Boehler */ 185185e2535SAndreas Boehler public function getCalendarColorForPage($id = null) 186185e2535SAndreas Boehler { 187185e2535SAndreas Boehler if(is_null($id)) 188185e2535SAndreas Boehler { 189185e2535SAndreas Boehler global $ID; 190185e2535SAndreas Boehler $id = $ID; 191185e2535SAndreas Boehler } 192185e2535SAndreas Boehler 193185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 194185e2535SAndreas Boehler if($calid === false) 195185e2535SAndreas Boehler return false; 196185e2535SAndreas Boehler 197185e2535SAndreas Boehler return $this->getCalendarColorForCalendar($calid); 198185e2535SAndreas Boehler } 199185e2535SAndreas Boehler 200185e2535SAndreas Boehler /** 201185e2535SAndreas Boehler * Get the saved calendar color for a given calendar ID. 202185e2535SAndreas Boehler * 203185e2535SAndreas Boehler * @param string $id optional The calendar ID 204185e2535SAndreas Boehler * @return mixed The color on success, otherwise false 205185e2535SAndreas Boehler */ 206185e2535SAndreas Boehler public function getCalendarColorForCalendar($calid) 207185e2535SAndreas Boehler { 208185e2535SAndreas Boehler if(isset($this->cachedValues['calendarcolor'][$calid])) 209185e2535SAndreas Boehler return $this->cachedValues['calendarcolor'][$calid]; 210185e2535SAndreas Boehler 211185e2535SAndreas Boehler $row = $this->getCalendarSettings($calid); 212185e2535SAndreas Boehler 213185e2535SAndreas Boehler if(!isset($row['calendarcolor'])) 214185e2535SAndreas Boehler return false; 215185e2535SAndreas Boehler 216185e2535SAndreas Boehler $color = $row['calendarcolor']; 217185e2535SAndreas Boehler $this->cachedValues['calendarcolor'][$calid] = $color; 218185e2535SAndreas Boehler return $color; 219185e2535SAndreas Boehler } 220185e2535SAndreas Boehler 221185e2535SAndreas Boehler /** 222e86c8dd3SAndreas Boehler * Get the user's principal URL for iOS sync 223e86c8dd3SAndreas Boehler * @param string $user the user name 224e86c8dd3SAndreas Boehler * @return the URL to the principal sync 225e86c8dd3SAndreas Boehler */ 226e86c8dd3SAndreas Boehler public function getPrincipalUrlForUser($user) 227e86c8dd3SAndreas Boehler { 228e86c8dd3SAndreas Boehler if(is_null($user)) 229e86c8dd3SAndreas Boehler return false; 230e86c8dd3SAndreas Boehler $url = DOKU_URL.'lib/plugins/davcal/calendarserver.php/principals/'.$user; 231e86c8dd3SAndreas Boehler return $url; 232e86c8dd3SAndreas Boehler } 233e86c8dd3SAndreas Boehler 234e86c8dd3SAndreas Boehler /** 235185e2535SAndreas Boehler * Set the calendar color for a given page. 236185e2535SAndreas Boehler * 237185e2535SAndreas Boehler * @param string $color The color definition 238185e2535SAndreas Boehler * @param string $id optional The page ID 239185e2535SAndreas Boehler * @return boolean True on success, otherwise false 240185e2535SAndreas Boehler */ 241185e2535SAndreas Boehler public function setCalendarColorForPage($color, $id = null) 242185e2535SAndreas Boehler { 243185e2535SAndreas Boehler if(is_null($id)) 244185e2535SAndreas Boehler { 245185e2535SAndreas Boehler global $ID; 246185e2535SAndreas Boehler $id = $ID; 247185e2535SAndreas Boehler } 248185e2535SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 249185e2535SAndreas Boehler if($calid === false) 250185e2535SAndreas Boehler return false; 251185e2535SAndreas Boehler 25251f4febbSAndreas Boehler $query = "UPDATE calendars SET calendarcolor = ? ". 25351f4febbSAndreas Boehler " WHERE id = ?"; 25451f4febbSAndreas Boehler $res = $this->sqlite->query($query, $color, $calid); 255185e2535SAndreas Boehler if($res !== false) 256185e2535SAndreas Boehler { 257185e2535SAndreas Boehler $this->cachedValues['calendarcolor'][$calid] = $color; 258185e2535SAndreas Boehler return true; 259185e2535SAndreas Boehler } 260185e2535SAndreas Boehler return false; 261185e2535SAndreas Boehler } 262185e2535SAndreas Boehler 263185e2535SAndreas Boehler /** 264cb71a62aSAndreas Boehler * Set the calendar name and description for a given page with a given 265cb71a62aSAndreas Boehler * page id. 266cb71a62aSAndreas Boehler * If the calendar doesn't exist, the calendar is created! 267cb71a62aSAndreas Boehler * 268cb71a62aSAndreas Boehler * @param string $name The name of the new calendar 269cb71a62aSAndreas Boehler * @param string $description The description of the new calendar 270cb71a62aSAndreas Boehler * @param string $id (optional) The ID of the page 271cb71a62aSAndreas Boehler * @param string $userid The userid of the creating user 272cb71a62aSAndreas Boehler * 273cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false. 274cb71a62aSAndreas Boehler */ 275a1a3b679SAndreas Boehler public function setCalendarNameForPage($name, $description, $id = null, $userid = null) 276a1a3b679SAndreas Boehler { 277a1a3b679SAndreas Boehler if(is_null($id)) 278a1a3b679SAndreas Boehler { 279a1a3b679SAndreas Boehler global $ID; 280a1a3b679SAndreas Boehler $id = $ID; 281a1a3b679SAndreas Boehler } 282a1a3b679SAndreas Boehler if(is_null($userid)) 28334a47953SAndreas Boehler { 28434a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 28534a47953SAndreas Boehler { 286a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 28734a47953SAndreas Boehler } 28834a47953SAndreas Boehler else 28934a47953SAndreas Boehler { 29034a47953SAndreas Boehler $userid = uniqid('davcal-'); 29134a47953SAndreas Boehler } 29234a47953SAndreas Boehler } 293a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 294a1a3b679SAndreas Boehler if($calid === false) 295a1a3b679SAndreas Boehler return $this->createCalendarForPage($name, $description, $id, $userid); 296a1a3b679SAndreas Boehler 29751f4febbSAndreas Boehler $query = "UPDATE calendars SET displayname = ?, description = ? WHERE id = ?"; 29851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $name, $description, $calid); 299b269830cSAndreas Boehler if($res !== false) 300b269830cSAndreas Boehler return true; 301b269830cSAndreas Boehler return false; 302a1a3b679SAndreas Boehler } 303a1a3b679SAndreas Boehler 304cb71a62aSAndreas Boehler /** 305cb71a62aSAndreas Boehler * Save the personal settings to the SQLite database 'calendarsettings'. 306cb71a62aSAndreas Boehler * 307cb71a62aSAndreas Boehler * @param array $settings The settings array to store 308cb71a62aSAndreas Boehler * @param string $userid (optional) The userid to store 309cb71a62aSAndreas Boehler * 310cb71a62aSAndreas Boehler * @param boolean True on success, otherwise false 311cb71a62aSAndreas Boehler */ 312a495d34cSAndreas Boehler public function savePersonalSettings($settings, $userid = null) 313a495d34cSAndreas Boehler { 314a495d34cSAndreas Boehler if(is_null($userid)) 31534a47953SAndreas Boehler { 31634a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 31734a47953SAndreas Boehler { 318a495d34cSAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 31934a47953SAndreas Boehler } 32034a47953SAndreas Boehler else 32134a47953SAndreas Boehler { 32234a47953SAndreas Boehler return false; 32334a47953SAndreas Boehler } 32434a47953SAndreas Boehler } 325a495d34cSAndreas Boehler $this->sqlite->query("BEGIN TRANSACTION"); 326a495d34cSAndreas Boehler 32751f4febbSAndreas Boehler $query = "DELETE FROM calendarsettings WHERE userid = ?"; 32851f4febbSAndreas Boehler $this->sqlite->query($query, $userid); 329bd883736SAndreas Boehler 330a495d34cSAndreas Boehler foreach($settings as $key => $value) 331a495d34cSAndreas Boehler { 33251f4febbSAndreas Boehler $query = "INSERT INTO calendarsettings (userid, key, value) VALUES (?, ?, ?)"; 33351f4febbSAndreas Boehler $res = $this->sqlite->query($query, $userid, $key, $value); 334a495d34cSAndreas Boehler if($res === false) 335a495d34cSAndreas Boehler return false; 336a495d34cSAndreas Boehler } 337a495d34cSAndreas Boehler $this->sqlite->query("COMMIT TRANSACTION"); 338185e2535SAndreas Boehler $this->cachedValues['settings'][$userid] = $settings; 339a495d34cSAndreas Boehler return true; 340a495d34cSAndreas Boehler } 341a495d34cSAndreas Boehler 342cb71a62aSAndreas Boehler /** 343cb71a62aSAndreas Boehler * Retrieve the settings array for a given user id. 344cb71a62aSAndreas Boehler * Some sane defaults are returned, currently: 345cb71a62aSAndreas Boehler * 346cb71a62aSAndreas Boehler * timezone => local 347cb71a62aSAndreas Boehler * weeknumbers => 0 348cb71a62aSAndreas Boehler * workweek => 0 349cb71a62aSAndreas Boehler * 350cb71a62aSAndreas Boehler * @param string $userid (optional) The user id to retrieve 351cb71a62aSAndreas Boehler * 352cb71a62aSAndreas Boehler * @return array The settings array 353cb71a62aSAndreas Boehler */ 354a495d34cSAndreas Boehler public function getPersonalSettings($userid = null) 355a495d34cSAndreas Boehler { 356bd883736SAndreas Boehler // Some sane default settings 357bd883736SAndreas Boehler $settings = array( 358fb813b30SAndreas Boehler 'timezone' => $this->getConf('timezone'), 359fb813b30SAndreas Boehler 'weeknumbers' => $this->getConf('weeknumbers'), 360fb813b30SAndreas Boehler 'workweek' => $this->getConf('workweek'), 3611d5bdcd0SAndreas Boehler 'monday' => $this->getConf('monday'), 3621d5bdcd0SAndreas Boehler 'timeformat' => $this->getConf('timeformat') 363bd883736SAndreas Boehler ); 36434a47953SAndreas Boehler if(is_null($userid)) 36534a47953SAndreas Boehler { 36634a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 36734a47953SAndreas Boehler { 36834a47953SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 36934a47953SAndreas Boehler } 37034a47953SAndreas Boehler else 37134a47953SAndreas Boehler { 37234a47953SAndreas Boehler return $settings; 37334a47953SAndreas Boehler } 37434a47953SAndreas Boehler } 37534a47953SAndreas Boehler 37634a47953SAndreas Boehler if(isset($this->cachedValues['settings'][$userid])) 37734a47953SAndreas Boehler return $this->cachedValues['settings'][$userid]; 37851f4febbSAndreas Boehler $query = "SELECT key, value FROM calendarsettings WHERE userid = ?"; 37951f4febbSAndreas Boehler $res = $this->sqlite->query($query, $userid); 380a495d34cSAndreas Boehler $arr = $this->sqlite->res2arr($res); 381a495d34cSAndreas Boehler foreach($arr as $row) 382a495d34cSAndreas Boehler { 383a495d34cSAndreas Boehler $settings[$row['key']] = $row['value']; 384a495d34cSAndreas Boehler } 385185e2535SAndreas Boehler $this->cachedValues['settings'][$userid] = $settings; 386a495d34cSAndreas Boehler return $settings; 387a495d34cSAndreas Boehler } 388a495d34cSAndreas Boehler 389cb71a62aSAndreas Boehler /** 390cb71a62aSAndreas Boehler * Retrieve the calendar ID based on a page ID from the SQLite table 391cb71a62aSAndreas Boehler * 'pagetocalendarmapping'. 392cb71a62aSAndreas Boehler * 393cb71a62aSAndreas Boehler * @param string $id (optional) The page ID to retrieve the corresponding calendar 394cb71a62aSAndreas Boehler * 395cb71a62aSAndreas Boehler * @return mixed the ID on success, otherwise false 396cb71a62aSAndreas Boehler */ 397a1a3b679SAndreas Boehler public function getCalendarIdForPage($id = null) 398a1a3b679SAndreas Boehler { 399a1a3b679SAndreas Boehler if(is_null($id)) 400a1a3b679SAndreas Boehler { 401a1a3b679SAndreas Boehler global $ID; 402a1a3b679SAndreas Boehler $id = $ID; 403a1a3b679SAndreas Boehler } 404a1a3b679SAndreas Boehler 405185e2535SAndreas Boehler if(isset($this->cachedValues['calid'][$id])) 406185e2535SAndreas Boehler return $this->cachedValues['calid'][$id]; 407185e2535SAndreas Boehler 40851f4febbSAndreas Boehler $query = "SELECT calid FROM pagetocalendarmapping WHERE page = ?"; 40951f4febbSAndreas Boehler $res = $this->sqlite->query($query, $id); 410a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 411a1a3b679SAndreas Boehler if(isset($row['calid'])) 412185e2535SAndreas Boehler { 413185e2535SAndreas Boehler $calid = $row['calid']; 414185e2535SAndreas Boehler $this->cachedValues['calid'] = $calid; 415185e2535SAndreas Boehler return $calid; 416185e2535SAndreas Boehler } 417a1a3b679SAndreas Boehler return false; 418a1a3b679SAndreas Boehler } 419a1a3b679SAndreas Boehler 420cb71a62aSAndreas Boehler /** 421cb71a62aSAndreas Boehler * Retrieve the complete calendar id to page mapping. 422cb71a62aSAndreas Boehler * This is necessary to be able to retrieve a list of 423cb71a62aSAndreas Boehler * calendars for a given user and check the access rights. 424cb71a62aSAndreas Boehler * 425cb71a62aSAndreas Boehler * @return array The mapping array 426cb71a62aSAndreas Boehler */ 427a1a3b679SAndreas Boehler public function getCalendarIdToPageMapping() 428a1a3b679SAndreas Boehler { 429a1a3b679SAndreas Boehler $query = "SELECT calid, page FROM pagetocalendarmapping"; 430a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 431a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 432a1a3b679SAndreas Boehler return $arr; 433a1a3b679SAndreas Boehler } 434a1a3b679SAndreas Boehler 435cb71a62aSAndreas Boehler /** 436cb71a62aSAndreas Boehler * Retrieve all calendar IDs a given user has access to. 437cb71a62aSAndreas Boehler * The user is specified by the principalUri, so the 438cb71a62aSAndreas Boehler * user name is actually split from the URI component. 439cb71a62aSAndreas Boehler * 440cb71a62aSAndreas Boehler * Access rights are checked against DokuWiki's ACL 441cb71a62aSAndreas Boehler * and applied accordingly. 442cb71a62aSAndreas Boehler * 443cb71a62aSAndreas Boehler * @param string $principalUri The principal URI to work on 444cb71a62aSAndreas Boehler * 445cb71a62aSAndreas Boehler * @return array An associative array of calendar IDs 446cb71a62aSAndreas Boehler */ 447a1a3b679SAndreas Boehler public function getCalendarIdsForUser($principalUri) 448a1a3b679SAndreas Boehler { 44934a47953SAndreas Boehler global $auth; 450a1a3b679SAndreas Boehler $user = explode('/', $principalUri); 451a1a3b679SAndreas Boehler $user = end($user); 452a1a3b679SAndreas Boehler $mapping = $this->getCalendarIdToPageMapping(); 453a1a3b679SAndreas Boehler $calids = array(); 45434a47953SAndreas Boehler $ud = $auth->getUserData($user); 45534a47953SAndreas Boehler $groups = $ud['grps']; 456a1a3b679SAndreas Boehler foreach($mapping as $row) 457a1a3b679SAndreas Boehler { 458a1a3b679SAndreas Boehler $id = $row['calid']; 459a1a3b679SAndreas Boehler $page = $row['page']; 46034a47953SAndreas Boehler $acl = auth_aclcheck($page, $user, $groups); 461a1a3b679SAndreas Boehler if($acl >= AUTH_READ) 462a1a3b679SAndreas Boehler { 463a1a3b679SAndreas Boehler $write = $acl > AUTH_READ; 464a1a3b679SAndreas Boehler $calids[$id] = array('readonly' => !$write); 465a1a3b679SAndreas Boehler } 466a1a3b679SAndreas Boehler } 467a1a3b679SAndreas Boehler return $calids; 468a1a3b679SAndreas Boehler } 469a1a3b679SAndreas Boehler 470cb71a62aSAndreas Boehler /** 471cb71a62aSAndreas Boehler * Create a new calendar for a given page ID and set name and description 472cb71a62aSAndreas Boehler * accordingly. Also update the pagetocalendarmapping table on success. 473cb71a62aSAndreas Boehler * 474cb71a62aSAndreas Boehler * @param string $name The calendar's name 475cb71a62aSAndreas Boehler * @param string $description The calendar's description 476cb71a62aSAndreas Boehler * @param string $id (optional) The page ID to work on 477cb71a62aSAndreas Boehler * @param string $userid (optional) The user ID that created the calendar 478cb71a62aSAndreas Boehler * 479cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 480cb71a62aSAndreas Boehler */ 481a1a3b679SAndreas Boehler public function createCalendarForPage($name, $description, $id = null, $userid = null) 482a1a3b679SAndreas Boehler { 483a1a3b679SAndreas Boehler if(is_null($id)) 484a1a3b679SAndreas Boehler { 485a1a3b679SAndreas Boehler global $ID; 486a1a3b679SAndreas Boehler $id = $ID; 487a1a3b679SAndreas Boehler } 488a1a3b679SAndreas Boehler if(is_null($userid)) 48934a47953SAndreas Boehler { 49034a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 49134a47953SAndreas Boehler { 492a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 49334a47953SAndreas Boehler } 49434a47953SAndreas Boehler else 49534a47953SAndreas Boehler { 49634a47953SAndreas Boehler $userid = uniqid('davcal-'); 49734a47953SAndreas Boehler } 49834a47953SAndreas Boehler } 499a1a3b679SAndreas Boehler $values = array('principals/'.$userid, 500a1a3b679SAndreas Boehler $name, 501a1a3b679SAndreas Boehler str_replace(array('/', ' ', ':'), '_', $id), 502a1a3b679SAndreas Boehler $description, 503a1a3b679SAndreas Boehler 'VEVENT,VTODO', 50455a741c0SAndreas Boehler 0, 50555a741c0SAndreas Boehler 1); 50651f4febbSAndreas Boehler $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) ". 50751f4febbSAndreas Boehler "VALUES (?, ?, ?, ?, ?, ?, ?)"; 50851f4febbSAndreas Boehler $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3], $values[4], $values[5], $values[6]); 50955a741c0SAndreas Boehler if($res === false) 51055a741c0SAndreas Boehler return false; 511cb71a62aSAndreas Boehler 512cb71a62aSAndreas Boehler // Get the new calendar ID 51351f4febbSAndreas Boehler $query = "SELECT id FROM calendars WHERE principaluri = ? AND displayname = ? AND ". 51451f4febbSAndreas Boehler "uri = ? AND description = ?"; 51551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3]); 516a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 517cb71a62aSAndreas Boehler 518cb71a62aSAndreas Boehler // Update the pagetocalendarmapping table with the new calendar ID 519a1a3b679SAndreas Boehler if(isset($row['id'])) 520a1a3b679SAndreas Boehler { 52151f4febbSAndreas Boehler $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (?, ?)"; 52251f4febbSAndreas Boehler $res = $this->sqlite->query($query, $id, $row['id']); 52355a741c0SAndreas Boehler return ($res !== false); 524a1a3b679SAndreas Boehler } 525a1a3b679SAndreas Boehler 526a1a3b679SAndreas Boehler return false; 527a1a3b679SAndreas Boehler } 528a1a3b679SAndreas Boehler 529cb71a62aSAndreas Boehler /** 530cb71a62aSAndreas Boehler * Add a new iCal entry for a given page, i.e. a given calendar. 531cb71a62aSAndreas Boehler * 532cb71a62aSAndreas Boehler * The parameter array needs to contain 533cb71a62aSAndreas Boehler * detectedtz => The timezone as detected by the browser 53482a48dfbSAndreas Boehler * currenttz => The timezone in use by the calendar 535cb71a62aSAndreas Boehler * eventfrom => The event's start date 536cb71a62aSAndreas Boehler * eventfromtime => The event's start time 537cb71a62aSAndreas Boehler * eventto => The event's end date 538cb71a62aSAndreas Boehler * eventtotime => The event's end time 539cb71a62aSAndreas Boehler * eventname => The event's name 540cb71a62aSAndreas Boehler * eventdescription => The event's description 541cb71a62aSAndreas Boehler * 542cb71a62aSAndreas Boehler * @param string $id The page ID to work on 543cb71a62aSAndreas Boehler * @param string $user The user who created the calendar 544cb71a62aSAndreas Boehler * @param string $params A parameter array with values to create 545cb71a62aSAndreas Boehler * 546cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 547cb71a62aSAndreas Boehler */ 548a1a3b679SAndreas Boehler public function addCalendarEntryToCalendarForPage($id, $user, $params) 549a1a3b679SAndreas Boehler { 55082a48dfbSAndreas Boehler if($params['currenttz'] !== '' && $params['currenttz'] !== 'local') 55182a48dfbSAndreas Boehler $timezone = new \DateTimeZone($params['currenttz']); 55282a48dfbSAndreas Boehler elseif($params['currenttz'] === 'local') 553a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 554bd883736SAndreas Boehler else 555bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 556cb71a62aSAndreas Boehler 557cb71a62aSAndreas Boehler // Retrieve dates from settings 558b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 559b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 560b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 561b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 562cb71a62aSAndreas Boehler 563cb71a62aSAndreas Boehler // Load SabreDAV 5649bef4ad8SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 565a1a3b679SAndreas Boehler $vcalendar = new \Sabre\VObject\Component\VCalendar(); 566cb71a62aSAndreas Boehler 567cb71a62aSAndreas Boehler // Add VCalendar, UID and Event Name 568a1a3b679SAndreas Boehler $event = $vcalendar->add('VEVENT'); 569b269830cSAndreas Boehler $uuid = \Sabre\VObject\UUIDUtil::getUUID(); 570b269830cSAndreas Boehler $event->add('UID', $uuid); 571a1a3b679SAndreas Boehler $event->summary = $params['eventname']; 572cb71a62aSAndreas Boehler 573cb71a62aSAndreas Boehler // Add a description if requested 5740eebc909SAndreas Boehler $description = $params['eventdescription']; 5750eebc909SAndreas Boehler if($description !== '') 5760eebc909SAndreas Boehler $event->add('DESCRIPTION', $description); 577cb71a62aSAndreas Boehler 5784ecb526cSAndreas Boehler // Add attachments 5794ecb526cSAndreas Boehler $attachments = $params['attachments']; 58082a48dfbSAndreas Boehler if(!is_null($attachments)) 5814ecb526cSAndreas Boehler foreach($attachments as $attachment) 5824ecb526cSAndreas Boehler $event->add('ATTACH', $attachment); 5834ecb526cSAndreas Boehler 584cb71a62aSAndreas Boehler // Create a timestamp for last modified, created and dtstamp values in UTC 585b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 586b269830cSAndreas Boehler $event->add('DTSTAMP', $dtStamp); 587b269830cSAndreas Boehler $event->add('CREATED', $dtStamp); 588b269830cSAndreas Boehler $event->add('LAST-MODIFIED', $dtStamp); 589cb71a62aSAndreas Boehler 590cb71a62aSAndreas Boehler // Adjust the start date, based on the given timezone information 591b269830cSAndreas Boehler $dtStart = new \DateTime(); 592a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 593b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 594cb71a62aSAndreas Boehler 595cb71a62aSAndreas Boehler // Only add the time values if it's not an allday event 596b269830cSAndreas Boehler if($params['allday'] != '1') 597b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 598cb71a62aSAndreas Boehler 599cb71a62aSAndreas Boehler // Adjust the end date, based on the given timezone information 600b269830cSAndreas Boehler $dtEnd = new \DateTime(); 601a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 602b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 603cb71a62aSAndreas Boehler 604cb71a62aSAndreas Boehler // Only add the time values if it's not an allday event 605b269830cSAndreas Boehler if($params['allday'] != '1') 606b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 607cb71a62aSAndreas Boehler 608b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 609b269830cSAndreas Boehler if($params['allday'] == '1') 610b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 611cb71a62aSAndreas Boehler 612cb71a62aSAndreas Boehler // Really add Start and End events 613b269830cSAndreas Boehler $dtStartEv = $event->add('DTSTART', $dtStart); 614b269830cSAndreas Boehler $dtEndEv = $event->add('DTEND', $dtEnd); 615cb71a62aSAndreas Boehler 616cb71a62aSAndreas Boehler // Adjust the DATE format for allday events 617b269830cSAndreas Boehler if($params['allday'] == '1') 618b269830cSAndreas Boehler { 619b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 620b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 621b269830cSAndreas Boehler } 622cb71a62aSAndreas Boehler 623*809cb0faSAndreas Boehler $eventStr = $vcalendar->serialize(); 624*809cb0faSAndreas Boehler 625*809cb0faSAndreas Boehler if(strpos($id, 'webdav://') === 0) 626*809cb0faSAndreas Boehler { 627*809cb0faSAndreas Boehler $wdc =& plugin_load('helper', 'webdavclient'); 628*809cb0faSAndreas Boehler if(is_null($wdc)) 629*809cb0faSAndreas Boehler return false; 630*809cb0faSAndreas Boehler $connectionId = str_replace('webdav://', '', $id); 631*809cb0faSAndreas Boehler return $wdc->addCalendarEntry($connectionId, $eventStr); 632*809cb0faSAndreas Boehler } 633*809cb0faSAndreas Boehler else 634*809cb0faSAndreas Boehler { 635cb71a62aSAndreas Boehler // Actually add the values to the database 636a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 637a1a3b679SAndreas Boehler $uri = uniqid('dokuwiki-').'.ics'; 638a1a3b679SAndreas Boehler $now = new DateTime(); 639a1a3b679SAndreas Boehler 64051f4febbSAndreas Boehler $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 64151f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid, $uri, $eventStr, $now->getTimestamp(), 'VEVENT', 64251f4febbSAndreas Boehler $event->DTSTART->getDateTime()->getTimeStamp(), $event->DTEND->getDateTime()->getTimeStamp(), 64351f4febbSAndreas Boehler strlen($eventStr), md5($eventStr), $uuid); 644cb71a62aSAndreas Boehler 645cb71a62aSAndreas Boehler // If successfully, update the sync token database 64655a741c0SAndreas Boehler if($res !== false) 64755a741c0SAndreas Boehler { 64855a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'added'); 649a1a3b679SAndreas Boehler return true; 650a1a3b679SAndreas Boehler } 651*809cb0faSAndreas Boehler } 65255a741c0SAndreas Boehler return false; 65355a741c0SAndreas Boehler } 654a1a3b679SAndreas Boehler 655cb71a62aSAndreas Boehler /** 656cb71a62aSAndreas Boehler * Retrieve the calendar settings of a given calendar id 657cb71a62aSAndreas Boehler * 658cb71a62aSAndreas Boehler * @param string $calid The calendar ID 659cb71a62aSAndreas Boehler * 660cb71a62aSAndreas Boehler * @return array The calendar settings array 661cb71a62aSAndreas Boehler */ 662b269830cSAndreas Boehler public function getCalendarSettings($calid) 663b269830cSAndreas Boehler { 66451f4febbSAndreas Boehler $query = "SELECT principaluri, calendarcolor, displayname, uri, description, components, transparent, synctoken FROM calendars WHERE id= ? "; 66551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 666b269830cSAndreas Boehler $row = $this->sqlite->res2row($res); 667b269830cSAndreas Boehler return $row; 668b269830cSAndreas Boehler } 669b269830cSAndreas Boehler 670cb71a62aSAndreas Boehler /** 671cb71a62aSAndreas Boehler * Retrieve all events that are within a given date range, 672cb71a62aSAndreas Boehler * based on the timezone setting. 673cb71a62aSAndreas Boehler * 674cb71a62aSAndreas Boehler * There is also support for retrieving recurring events, 675cb71a62aSAndreas Boehler * using Sabre's VObject Iterator. Recurring events are represented 676cb71a62aSAndreas Boehler * as individual calendar entries with the same UID. 677cb71a62aSAndreas Boehler * 678cb71a62aSAndreas Boehler * @param string $id The page ID to work with 679cb71a62aSAndreas Boehler * @param string $user The user ID to work with 680cb71a62aSAndreas Boehler * @param string $startDate The start date as a string 681cb71a62aSAndreas Boehler * @param string $endDate The end date as a string 6824a2bf5eeSAndreas Boehler * @param string $color (optional) The calendar's color 683cb71a62aSAndreas Boehler * 684cb71a62aSAndreas Boehler * @return array An array containing the calendar entries. 685cb71a62aSAndreas Boehler */ 6864a2bf5eeSAndreas Boehler public function getEventsWithinDateRange($id, $user, $startDate, $endDate, $timezone, $color = null) 687a1a3b679SAndreas Boehler { 68882a48dfbSAndreas Boehler if($timezone !== '' && $timezone !== 'local') 68982a48dfbSAndreas Boehler $timezone = new \DateTimeZone($timezone); 690bd883736SAndreas Boehler else 691bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 692a1a3b679SAndreas Boehler $data = array(); 693cb71a62aSAndreas Boehler 694a469597cSAndreas Boehler $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid = ?"; 695a469597cSAndreas Boehler $startTs = null; 696a469597cSAndreas Boehler $endTs = null; 697a469597cSAndreas Boehler if($startDate !== null) 698a469597cSAndreas Boehler { 699a1a3b679SAndreas Boehler $startTs = new \DateTime($startDate); 700a469597cSAndreas Boehler $query .= " AND lastoccurence > ".$this->sqlite->quote_string($startTs->getTimestamp()); 701a469597cSAndreas Boehler } 702a469597cSAndreas Boehler if($endDate !== null) 703a469597cSAndreas Boehler { 704a1a3b679SAndreas Boehler $endTs = new \DateTime($endDate); 705a469597cSAndreas Boehler $query .= " AND firstoccurence < ".$this->sqlite->quote_string($endTs->getTimestamp()); 706a469597cSAndreas Boehler } 707cb71a62aSAndreas Boehler 7080b805092SAndreas Boehler // Load SabreDAV 7090b805092SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 7100b805092SAndreas Boehler 7110b805092SAndreas Boehler if(strpos($id, 'webdav://') === 0) 7120b805092SAndreas Boehler { 7130b805092SAndreas Boehler $wdc =& plugin_load('helper', 'webdavclient'); 7140b805092SAndreas Boehler if(is_null($wdc)) 7150b805092SAndreas Boehler return $data; 7160b805092SAndreas Boehler $connectionId = str_replace('webdav://', '', $id); 7170b805092SAndreas Boehler $arr = $wdc->getCalendarEntries($connectionId, $startDate, $endDate); 7180b805092SAndreas Boehler } 7190b805092SAndreas Boehler else 7200b805092SAndreas Boehler { 7210b805092SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 7220b805092SAndreas Boehler if(is_null($color)) 7230b805092SAndreas Boehler $color = $this->getCalendarColorForCalendar($calid); 7240b805092SAndreas Boehler 725cb71a62aSAndreas Boehler // Retrieve matching calendar objects 726a469597cSAndreas Boehler $res = $this->sqlite->query($query, $calid); 727a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 7280b805092SAndreas Boehler } 729cb71a62aSAndreas Boehler 730cb71a62aSAndreas Boehler // Parse individual calendar entries 731a1a3b679SAndreas Boehler foreach($arr as $row) 732a1a3b679SAndreas Boehler { 733a1a3b679SAndreas Boehler if(isset($row['calendardata'])) 734a1a3b679SAndreas Boehler { 735b269830cSAndreas Boehler $entry = array(); 736a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($row['calendardata']); 737ebc4eb57SAndreas Boehler $recurrence = $vcal->VEVENT->RRULE; 738cb71a62aSAndreas Boehler // If it is a recurring event, pass it through Sabre's EventIterator 739ebc4eb57SAndreas Boehler if($recurrence != null) 740ebc4eb57SAndreas Boehler { 741ebc4eb57SAndreas Boehler $rEvents = new \Sabre\VObject\Recur\EventIterator(array($vcal->VEVENT)); 742ebc4eb57SAndreas Boehler $rEvents->rewind(); 743e9b7d302SAndreas Boehler while($rEvents->valid()) 744ebc4eb57SAndreas Boehler { 745ebc4eb57SAndreas Boehler $event = $rEvents->getEventObject(); 746cb71a62aSAndreas Boehler // If we are after the given time range, exit 747a469597cSAndreas Boehler if(($endTs !== null) && ($rEvents->getDtStart()->getTimestamp() > $endTs->getTimestamp())) 748e9b7d302SAndreas Boehler break; 749cb71a62aSAndreas Boehler 750cb71a62aSAndreas Boehler // If we are before the given time range, continue 751a469597cSAndreas Boehler if(($startTs != null) && ($rEvents->getDtEnd()->getTimestamp() < $startTs->getTimestamp())) 752ebc4eb57SAndreas Boehler { 753ebc4eb57SAndreas Boehler $rEvents->next(); 754ebc4eb57SAndreas Boehler continue; 755ebc4eb57SAndreas Boehler } 756cb71a62aSAndreas Boehler 757cb71a62aSAndreas Boehler // If we are within the given time range, parse the event 758185e2535SAndreas Boehler $data[] = $this->convertIcalDataToEntry($event, $id, $timezone, $row['uid'], $color, true); 759ebc4eb57SAndreas Boehler $rEvents->next(); 760ebc4eb57SAndreas Boehler } 761ebc4eb57SAndreas Boehler } 762ebc4eb57SAndreas Boehler else 763185e2535SAndreas Boehler $data[] = $this->convertIcalDataToEntry($vcal->VEVENT, $id, $timezone, $row['uid'], $color); 764ebc4eb57SAndreas Boehler } 765ebc4eb57SAndreas Boehler } 766ebc4eb57SAndreas Boehler return $data; 767ebc4eb57SAndreas Boehler } 768ebc4eb57SAndreas Boehler 769cb71a62aSAndreas Boehler /** 770cb71a62aSAndreas Boehler * Helper function that parses the iCal data of a VEVENT to a calendar entry. 771cb71a62aSAndreas Boehler * 772cb71a62aSAndreas Boehler * @param \Sabre\VObject\VEvent $event The event to parse 773cb71a62aSAndreas Boehler * @param \DateTimeZone $timezone The timezone object 774cb71a62aSAndreas Boehler * @param string $uid The entry's UID 7753c86dda8SAndreas Boehler * @param boolean $recurring (optional) Set to true to define a recurring event 776cb71a62aSAndreas Boehler * 777cb71a62aSAndreas Boehler * @return array The parse calendar entry 778cb71a62aSAndreas Boehler */ 779185e2535SAndreas Boehler private function convertIcalDataToEntry($event, $page, $timezone, $uid, $color, $recurring = false) 780ebc4eb57SAndreas Boehler { 781ebc4eb57SAndreas Boehler $entry = array(); 782ebc4eb57SAndreas Boehler $start = $event->DTSTART; 783cb71a62aSAndreas Boehler // Parse only if the start date/time is present 784b269830cSAndreas Boehler if($start !== null) 785b269830cSAndreas Boehler { 786b269830cSAndreas Boehler $dtStart = $start->getDateTime(); 787b269830cSAndreas Boehler $dtStart->setTimezone($timezone); 788bf0ad2b4SAndreas Boehler 789bf0ad2b4SAndreas Boehler // moment.js doesn't like times be given even if 790bf0ad2b4SAndreas Boehler // allDay is set to true 791bf0ad2b4SAndreas Boehler // This should fix T23 792b269830cSAndreas Boehler if($start['VALUE'] == 'DATE') 793bf0ad2b4SAndreas Boehler { 794b269830cSAndreas Boehler $entry['allDay'] = true; 795bf0ad2b4SAndreas Boehler $entry['start'] = $dtStart->format("Y-m-d"); 796bf0ad2b4SAndreas Boehler } 797b269830cSAndreas Boehler else 798bf0ad2b4SAndreas Boehler { 799b269830cSAndreas Boehler $entry['allDay'] = false; 800bf0ad2b4SAndreas Boehler $entry['start'] = $dtStart->format(\DateTime::ATOM); 801bf0ad2b4SAndreas Boehler } 802b269830cSAndreas Boehler } 803ebc4eb57SAndreas Boehler $end = $event->DTEND; 804bf0ad2b4SAndreas Boehler // Parse only if the end date/time is present 805b269830cSAndreas Boehler if($end !== null) 806b269830cSAndreas Boehler { 807b269830cSAndreas Boehler $dtEnd = $end->getDateTime(); 808b269830cSAndreas Boehler $dtEnd->setTimezone($timezone); 809bf0ad2b4SAndreas Boehler if($end['VALUE'] == 'DATE') 810bf0ad2b4SAndreas Boehler $entry['end'] = $dtEnd->format("Y-m-d"); 811bf0ad2b4SAndreas Boehler else 812b269830cSAndreas Boehler $entry['end'] = $dtEnd->format(\DateTime::ATOM); 813b269830cSAndreas Boehler } 814ebc4eb57SAndreas Boehler $description = $event->DESCRIPTION; 8150eebc909SAndreas Boehler if($description !== null) 8160eebc909SAndreas Boehler $entry['description'] = (string)$description; 8170eebc909SAndreas Boehler else 8180eebc909SAndreas Boehler $entry['description'] = ''; 8194ecb526cSAndreas Boehler $attachments = $event->ATTACH; 8204ecb526cSAndreas Boehler if($attachments !== null) 8214ecb526cSAndreas Boehler { 8224ecb526cSAndreas Boehler $entry['attachments'] = array(); 8234ecb526cSAndreas Boehler foreach($attachments as $attachment) 8244ecb526cSAndreas Boehler $entry['attachments'][] = (string)$attachment; 8254ecb526cSAndreas Boehler } 826ebc4eb57SAndreas Boehler $entry['title'] = (string)$event->summary; 827ebc4eb57SAndreas Boehler $entry['id'] = $uid; 828185e2535SAndreas Boehler $entry['page'] = $page; 829185e2535SAndreas Boehler $entry['color'] = $color; 8303c86dda8SAndreas Boehler $entry['recurring'] = $recurring; 831185e2535SAndreas Boehler 832ebc4eb57SAndreas Boehler return $entry; 833a1a3b679SAndreas Boehler } 834a1a3b679SAndreas Boehler 835cb71a62aSAndreas Boehler /** 836cb71a62aSAndreas Boehler * Retrieve an event by its UID 837cb71a62aSAndreas Boehler * 838cb71a62aSAndreas Boehler * @param string $uid The event's UID 839cb71a62aSAndreas Boehler * 840cb71a62aSAndreas Boehler * @return mixed The table row with the given event 841cb71a62aSAndreas Boehler */ 842a1a3b679SAndreas Boehler public function getEventWithUid($uid) 843a1a3b679SAndreas Boehler { 84451f4febbSAndreas Boehler $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid = ?"; 84551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uid); 846a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 847a1a3b679SAndreas Boehler return $row; 848a1a3b679SAndreas Boehler } 849a1a3b679SAndreas Boehler 850cb71a62aSAndreas Boehler /** 851cb71a62aSAndreas Boehler * Retrieve all calendar events for a given calendar ID 852cb71a62aSAndreas Boehler * 853cb71a62aSAndreas Boehler * @param string $calid The calendar's ID 854cb71a62aSAndreas Boehler * 855cb71a62aSAndreas Boehler * @return array An array containing all calendar data 856cb71a62aSAndreas Boehler */ 857f69bb449SAndreas Boehler public function getAllCalendarEvents($calid) 858f69bb449SAndreas Boehler { 8597e0b8590SAndreas Boehler $query = "SELECT calendardata, uid, componenttype, uri FROM calendarobjects WHERE calendarid = ?"; 86051f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 861f69bb449SAndreas Boehler $arr = $this->sqlite->res2arr($res); 862f69bb449SAndreas Boehler return $arr; 863f69bb449SAndreas Boehler } 864f69bb449SAndreas Boehler 865cb71a62aSAndreas Boehler /** 866cb71a62aSAndreas Boehler * Edit a calendar entry for a page, given by its parameters. 867cb71a62aSAndreas Boehler * The params array has the same format as @see addCalendarEntryForPage 868cb71a62aSAndreas Boehler * 869cb71a62aSAndreas Boehler * @param string $id The page's ID to work on 870cb71a62aSAndreas Boehler * @param string $user The user's ID to work on 871cb71a62aSAndreas Boehler * @param array $params The parameter array for the edited calendar event 872cb71a62aSAndreas Boehler * 873cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 874cb71a62aSAndreas Boehler */ 875a1a3b679SAndreas Boehler public function editCalendarEntryForPage($id, $user, $params) 876a1a3b679SAndreas Boehler { 87782a48dfbSAndreas Boehler if($params['currenttz'] !== '' && $params['currenttz'] !== 'local') 87882a48dfbSAndreas Boehler $timezone = new \DateTimeZone($params['currenttz']); 87982a48dfbSAndreas Boehler elseif($params['currenttz'] === 'local') 880a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 881bd883736SAndreas Boehler else 882bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 883cb71a62aSAndreas Boehler 884cb71a62aSAndreas Boehler // Parse dates 885b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 886b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 887b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 888b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 889cb71a62aSAndreas Boehler 890cb71a62aSAndreas Boehler // Retrieve the existing event based on the UID 89155a741c0SAndreas Boehler $uid = $params['uid']; 892*809cb0faSAndreas Boehler 893*809cb0faSAndreas Boehler if(strpos($id, 'webdav://') === 0) 894*809cb0faSAndreas Boehler { 895*809cb0faSAndreas Boehler $wdc =& plugin_load('helper', 'webdavclient'); 896*809cb0faSAndreas Boehler if(is_null($wdc)) 897*809cb0faSAndreas Boehler return false; 898*809cb0faSAndreas Boehler $event = $wdc->getCalendarEntryByUid($uid); 899*809cb0faSAndreas Boehler } 900*809cb0faSAndreas Boehler else 901*809cb0faSAndreas Boehler { 90255a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 903*809cb0faSAndreas Boehler } 904cb71a62aSAndreas Boehler 905cb71a62aSAndreas Boehler // Load SabreDAV 9069bef4ad8SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 907a1a3b679SAndreas Boehler if(!isset($event['calendardata'])) 908a1a3b679SAndreas Boehler return false; 90955a741c0SAndreas Boehler $uri = $event['uri']; 91055a741c0SAndreas Boehler $calid = $event['calendarid']; 911cb71a62aSAndreas Boehler 912cb71a62aSAndreas Boehler // Parse the existing event 913a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 914b269830cSAndreas Boehler $vevent = $vcal->VEVENT; 915cb71a62aSAndreas Boehler 916cb71a62aSAndreas Boehler // Set the new event values 917b269830cSAndreas Boehler $vevent->summary = $params['eventname']; 918b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 9190eebc909SAndreas Boehler $description = $params['eventdescription']; 920cb71a62aSAndreas Boehler 921cb71a62aSAndreas Boehler // Remove existing timestamps to overwrite them 9220eebc909SAndreas Boehler $vevent->remove('DESCRIPTION'); 923b269830cSAndreas Boehler $vevent->remove('DTSTAMP'); 924b269830cSAndreas Boehler $vevent->remove('LAST-MODIFIED'); 9254ecb526cSAndreas Boehler $vevent->remove('ATTACH'); 926cb71a62aSAndreas Boehler 927cb71a62aSAndreas Boehler // Add new time stamps and description 928b269830cSAndreas Boehler $vevent->add('DTSTAMP', $dtStamp); 929b269830cSAndreas Boehler $vevent->add('LAST-MODIFIED', $dtStamp); 9300eebc909SAndreas Boehler if($description !== '') 9310eebc909SAndreas Boehler $vevent->add('DESCRIPTION', $description); 932cb71a62aSAndreas Boehler 9334ecb526cSAndreas Boehler // Add attachments 9344ecb526cSAndreas Boehler $attachments = $params['attachments']; 93582a48dfbSAndreas Boehler if(!is_null($attachments)) 9364ecb526cSAndreas Boehler foreach($attachments as $attachment) 9374ecb526cSAndreas Boehler $vevent->add('ATTACH', $attachment); 9384ecb526cSAndreas Boehler 939cb71a62aSAndreas Boehler // Setup DTSTART 940b269830cSAndreas Boehler $dtStart = new \DateTime(); 941a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 942b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 943b269830cSAndreas Boehler if($params['allday'] != '1') 944b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 945cb71a62aSAndreas Boehler 9464ecb526cSAndreas Boehler // Setup DTEND 947b269830cSAndreas Boehler $dtEnd = new \DateTime(); 948a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 949b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 950b269830cSAndreas Boehler if($params['allday'] != '1') 951b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 952cb71a62aSAndreas Boehler 953b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 954b269830cSAndreas Boehler if($params['allday'] == '1') 955b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 956b269830cSAndreas Boehler $vevent->remove('DTSTART'); 957b269830cSAndreas Boehler $vevent->remove('DTEND'); 958b269830cSAndreas Boehler $dtStartEv = $vevent->add('DTSTART', $dtStart); 959b269830cSAndreas Boehler $dtEndEv = $vevent->add('DTEND', $dtEnd); 960cb71a62aSAndreas Boehler 961cb71a62aSAndreas Boehler // Remove the time for allday events 962b269830cSAndreas Boehler if($params['allday'] == '1') 963b269830cSAndreas Boehler { 964b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 965b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 966b269830cSAndreas Boehler } 967a1a3b679SAndreas Boehler $eventStr = $vcal->serialize(); 968*809cb0faSAndreas Boehler if(strpos($id, 'webdav://') === 0) 969*809cb0faSAndreas Boehler { 970*809cb0faSAndreas Boehler $connectionId = str_replace('webdav://', '', $id); 971*809cb0faSAndreas Boehler return $wdc->editCalendarEntry($connectionId, $uid, $eventStr); 972*809cb0faSAndreas Boehler } 973*809cb0faSAndreas Boehler else 974*809cb0faSAndreas Boehler { 975*809cb0faSAndreas Boehler $now = new DateTime(); 976cb71a62aSAndreas Boehler // Actually write to the database 97751f4febbSAndreas Boehler $query = "UPDATE calendarobjects SET calendardata = ?, lastmodified = ?, ". 97851f4febbSAndreas Boehler "firstoccurence = ?, lastoccurence = ?, size = ?, etag = ? WHERE uid = ?"; 97951f4febbSAndreas Boehler $res = $this->sqlite->query($query, $eventStr, $now->getTimestamp(), $dtStart->getTimestamp(), 98051f4febbSAndreas Boehler $dtEnd->getTimestamp(), strlen($eventStr), md5($eventStr), $uid); 98155a741c0SAndreas Boehler if($res !== false) 98255a741c0SAndreas Boehler { 98355a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'modified'); 984a1a3b679SAndreas Boehler return true; 985a1a3b679SAndreas Boehler } 986*809cb0faSAndreas Boehler } 98755a741c0SAndreas Boehler return false; 98855a741c0SAndreas Boehler } 989a1a3b679SAndreas Boehler 990cb71a62aSAndreas Boehler /** 991cb71a62aSAndreas Boehler * Delete a calendar entry for a given page. Actually, the event is removed 992cb71a62aSAndreas Boehler * based on the entry's UID, so that page ID is no used. 993cb71a62aSAndreas Boehler * 994cb71a62aSAndreas Boehler * @param string $id The page's ID (unused) 995cb71a62aSAndreas Boehler * @param array $params The parameter array to work with 996cb71a62aSAndreas Boehler * 997cb71a62aSAndreas Boehler * @return boolean True 998cb71a62aSAndreas Boehler */ 999a1a3b679SAndreas Boehler public function deleteCalendarEntryForPage($id, $params) 1000a1a3b679SAndreas Boehler { 1001a1a3b679SAndreas Boehler $uid = $params['uid']; 1002*809cb0faSAndreas Boehler if(strpos($id, 'webdav://') === 0) 1003*809cb0faSAndreas Boehler { 1004*809cb0faSAndreas Boehler $wdc =& plugin_load('helper', 'webdavclient'); 1005*809cb0faSAndreas Boehler if(is_null($wdc)) 1006*809cb0faSAndreas Boehler return false; 1007*809cb0faSAndreas Boehler $connectionId = str_replace('webdav://', '', $id); 1008*809cb0faSAndreas Boehler $result = $wdc->deleteCalendarEntry($connectionId, $uid); 1009*809cb0faSAndreas Boehler return $result; 1010*809cb0faSAndreas Boehler } 101155a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 10122c14b82bSAndreas Boehler $calid = $event['calendarid']; 101355a741c0SAndreas Boehler $uri = $event['uri']; 101451f4febbSAndreas Boehler $query = "DELETE FROM calendarobjects WHERE uid = ?"; 101551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uid); 101655a741c0SAndreas Boehler if($res !== false) 101755a741c0SAndreas Boehler { 101855a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'deleted'); 101955a741c0SAndreas Boehler } 1020a1a3b679SAndreas Boehler return true; 1021a1a3b679SAndreas Boehler } 1022a1a3b679SAndreas Boehler 1023cb71a62aSAndreas Boehler /** 1024cb71a62aSAndreas Boehler * Retrieve the current sync token for a calendar 1025cb71a62aSAndreas Boehler * 1026cb71a62aSAndreas Boehler * @param string $calid The calendar id 1027cb71a62aSAndreas Boehler * 1028cb71a62aSAndreas Boehler * @return mixed The synctoken or false 1029cb71a62aSAndreas Boehler */ 103055a741c0SAndreas Boehler public function getSyncTokenForCalendar($calid) 103155a741c0SAndreas Boehler { 1032b269830cSAndreas Boehler $row = $this->getCalendarSettings($calid); 103355a741c0SAndreas Boehler if(isset($row['synctoken'])) 103455a741c0SAndreas Boehler return $row['synctoken']; 103555a741c0SAndreas Boehler return false; 103655a741c0SAndreas Boehler } 103755a741c0SAndreas Boehler 1038cb71a62aSAndreas Boehler /** 1039cb71a62aSAndreas Boehler * Helper function to convert the operation name to 1040cb71a62aSAndreas Boehler * an operation code as stored in the database 1041cb71a62aSAndreas Boehler * 1042cb71a62aSAndreas Boehler * @param string $operationName The operation name 1043cb71a62aSAndreas Boehler * 1044cb71a62aSAndreas Boehler * @return mixed The operation code or false 1045cb71a62aSAndreas Boehler */ 104655a741c0SAndreas Boehler public function operationNameToOperation($operationName) 104755a741c0SAndreas Boehler { 104855a741c0SAndreas Boehler switch($operationName) 104955a741c0SAndreas Boehler { 105055a741c0SAndreas Boehler case 'added': 105155a741c0SAndreas Boehler return 1; 105255a741c0SAndreas Boehler break; 105355a741c0SAndreas Boehler case 'modified': 105455a741c0SAndreas Boehler return 2; 105555a741c0SAndreas Boehler break; 105655a741c0SAndreas Boehler case 'deleted': 105755a741c0SAndreas Boehler return 3; 105855a741c0SAndreas Boehler break; 105955a741c0SAndreas Boehler } 106055a741c0SAndreas Boehler return false; 106155a741c0SAndreas Boehler } 106255a741c0SAndreas Boehler 1063cb71a62aSAndreas Boehler /** 1064cb71a62aSAndreas Boehler * Update the sync token log based on the calendar id and the 1065cb71a62aSAndreas Boehler * operation that was performed. 1066cb71a62aSAndreas Boehler * 1067cb71a62aSAndreas Boehler * @param string $calid The calendar ID that was modified 1068cb71a62aSAndreas Boehler * @param string $uri The calendar URI that was modified 1069cb71a62aSAndreas Boehler * @param string $operation The operation that was performed 1070cb71a62aSAndreas Boehler * 1071cb71a62aSAndreas Boehler * @return boolean True on success, otherwise false 1072cb71a62aSAndreas Boehler */ 107355a741c0SAndreas Boehler private function updateSyncTokenLog($calid, $uri, $operation) 107455a741c0SAndreas Boehler { 107555a741c0SAndreas Boehler $currentToken = $this->getSyncTokenForCalendar($calid); 107655a741c0SAndreas Boehler $operationCode = $this->operationNameToOperation($operation); 107755a741c0SAndreas Boehler if(($operationCode === false) || ($currentToken === false)) 107855a741c0SAndreas Boehler return false; 107955a741c0SAndreas Boehler $values = array($uri, 108055a741c0SAndreas Boehler $currentToken, 108155a741c0SAndreas Boehler $calid, 108255a741c0SAndreas Boehler $operationCode 108355a741c0SAndreas Boehler ); 108451f4febbSAndreas Boehler $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(?, ?, ?, ?)"; 108551f4febbSAndreas Boehler $res = $this->sqlite->query($query, $uri, $currentToken, $calid, $operationCode); 108655a741c0SAndreas Boehler if($res === false) 108755a741c0SAndreas Boehler return false; 108855a741c0SAndreas Boehler $currentToken++; 108951f4febbSAndreas Boehler $query = "UPDATE calendars SET synctoken = ? WHERE id = ?"; 109051f4febbSAndreas Boehler $res = $this->sqlite->query($query, $currentToken, $calid); 109155a741c0SAndreas Boehler return ($res !== false); 109255a741c0SAndreas Boehler } 109355a741c0SAndreas Boehler 1094cb71a62aSAndreas Boehler /** 1095cb71a62aSAndreas Boehler * Return the sync URL for a given Page, i.e. a calendar 1096cb71a62aSAndreas Boehler * 1097cb71a62aSAndreas Boehler * @param string $id The page's ID 1098cb71a62aSAndreas Boehler * @param string $user (optional) The user's ID 1099cb71a62aSAndreas Boehler * 1100cb71a62aSAndreas Boehler * @return mixed The sync url or false 1101cb71a62aSAndreas Boehler */ 1102b269830cSAndreas Boehler public function getSyncUrlForPage($id, $user = null) 1103b269830cSAndreas Boehler { 110434a47953SAndreas Boehler if(is_null($userid)) 110534a47953SAndreas Boehler { 110634a47953SAndreas Boehler if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 110734a47953SAndreas Boehler { 110834a47953SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 110934a47953SAndreas Boehler } 111034a47953SAndreas Boehler else 111134a47953SAndreas Boehler { 111234a47953SAndreas Boehler return false; 111334a47953SAndreas Boehler } 111434a47953SAndreas Boehler } 1115b269830cSAndreas Boehler 1116b269830cSAndreas Boehler $calid = $this->getCalendarIdForPage($id); 1117b269830cSAndreas Boehler if($calid === false) 1118b269830cSAndreas Boehler return false; 1119b269830cSAndreas Boehler 1120b269830cSAndreas Boehler $calsettings = $this->getCalendarSettings($calid); 1121b269830cSAndreas Boehler if(!isset($calsettings['uri'])) 1122b269830cSAndreas Boehler return false; 1123b269830cSAndreas Boehler 1124b269830cSAndreas Boehler $syncurl = DOKU_URL.'lib/plugins/davcal/calendarserver.php/calendars/'.$user.'/'.$calsettings['uri']; 1125b269830cSAndreas Boehler return $syncurl; 1126b269830cSAndreas Boehler } 1127b269830cSAndreas Boehler 1128cb71a62aSAndreas Boehler /** 1129cb71a62aSAndreas Boehler * Return the private calendar's URL for a given page 1130cb71a62aSAndreas Boehler * 1131cb71a62aSAndreas Boehler * @param string $id the page ID 1132cb71a62aSAndreas Boehler * 1133cb71a62aSAndreas Boehler * @return mixed The private URL or false 1134cb71a62aSAndreas Boehler */ 1135f69bb449SAndreas Boehler public function getPrivateURLForPage($id) 1136f69bb449SAndreas Boehler { 1137f69bb449SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 1138f69bb449SAndreas Boehler if($calid === false) 1139f69bb449SAndreas Boehler return false; 1140f69bb449SAndreas Boehler 1141f69bb449SAndreas Boehler return $this->getPrivateURLForCalendar($calid); 1142f69bb449SAndreas Boehler } 1143f69bb449SAndreas Boehler 1144cb71a62aSAndreas Boehler /** 1145cb71a62aSAndreas Boehler * Return the private calendar's URL for a given calendar ID 1146cb71a62aSAndreas Boehler * 1147cb71a62aSAndreas Boehler * @param string $calid The calendar's ID 1148cb71a62aSAndreas Boehler * 1149cb71a62aSAndreas Boehler * @return mixed The private URL or false 1150cb71a62aSAndreas Boehler */ 1151f69bb449SAndreas Boehler public function getPrivateURLForCalendar($calid) 1152f69bb449SAndreas Boehler { 1153185e2535SAndreas Boehler if(isset($this->cachedValues['privateurl'][$calid])) 1154185e2535SAndreas Boehler return $this->cachedValues['privateurl'][$calid]; 115551f4febbSAndreas Boehler $query = "SELECT url FROM calendartoprivateurlmapping WHERE calid = ?"; 115651f4febbSAndreas Boehler $res = $this->sqlite->query($query, $calid); 1157f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 1158f69bb449SAndreas Boehler if(!isset($row['url'])) 1159f69bb449SAndreas Boehler { 1160f69bb449SAndreas Boehler $url = uniqid("dokuwiki-").".ics"; 116151f4febbSAndreas Boehler $query = "INSERT INTO calendartoprivateurlmapping (url, calid) VALUES(?, ?)"; 116251f4febbSAndreas Boehler $res = $this->sqlite->query($query, $url, $calid); 1163f69bb449SAndreas Boehler if($res === false) 1164f69bb449SAndreas Boehler return false; 1165f69bb449SAndreas Boehler } 1166f69bb449SAndreas Boehler else 1167f69bb449SAndreas Boehler { 1168f69bb449SAndreas Boehler $url = $row['url']; 1169f69bb449SAndreas Boehler } 1170185e2535SAndreas Boehler 1171185e2535SAndreas Boehler $url = DOKU_URL.'lib/plugins/davcal/ics.php/'.$url; 1172185e2535SAndreas Boehler $this->cachedValues['privateurl'][$calid] = $url; 1173185e2535SAndreas Boehler return $url; 1174f69bb449SAndreas Boehler } 1175f69bb449SAndreas Boehler 1176cb71a62aSAndreas Boehler /** 1177cb71a62aSAndreas Boehler * Retrieve the calendar ID for a given private calendar URL 1178cb71a62aSAndreas Boehler * 1179cb71a62aSAndreas Boehler * @param string $url The private URL 1180cb71a62aSAndreas Boehler * 1181cb71a62aSAndreas Boehler * @return mixed The calendar ID or false 1182cb71a62aSAndreas Boehler */ 1183f69bb449SAndreas Boehler public function getCalendarForPrivateURL($url) 1184f69bb449SAndreas Boehler { 118551f4febbSAndreas Boehler $query = "SELECT calid FROM calendartoprivateurlmapping WHERE url = ?"; 118651f4febbSAndreas Boehler $res = $this->sqlite->query($query, $url); 1187f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 1188f69bb449SAndreas Boehler if(!isset($row['calid'])) 1189f69bb449SAndreas Boehler return false; 1190f69bb449SAndreas Boehler return $row['calid']; 1191f69bb449SAndreas Boehler } 1192f69bb449SAndreas Boehler 1193cb71a62aSAndreas Boehler /** 1194cb71a62aSAndreas Boehler * Return a given calendar as ICS feed, i.e. all events in one ICS file. 1195cb71a62aSAndreas Boehler * 11967e0b8590SAndreas Boehler * @param string $calid The calendar ID to retrieve 1197cb71a62aSAndreas Boehler * 1198cb71a62aSAndreas Boehler * @return mixed The calendar events as string or false 1199cb71a62aSAndreas Boehler */ 1200f69bb449SAndreas Boehler public function getCalendarAsICSFeed($calid) 1201f69bb449SAndreas Boehler { 1202f69bb449SAndreas Boehler $calSettings = $this->getCalendarSettings($calid); 1203f69bb449SAndreas Boehler if($calSettings === false) 1204f69bb449SAndreas Boehler return false; 1205f69bb449SAndreas Boehler $events = $this->getAllCalendarEvents($calid); 1206f69bb449SAndreas Boehler if($events === false) 1207f69bb449SAndreas Boehler return false; 1208f69bb449SAndreas Boehler 12097e0b8590SAndreas Boehler // Load SabreDAV 12107e0b8590SAndreas Boehler require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php'); 12117e0b8590SAndreas Boehler $out = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//DAVCal//DAVCal for DokuWiki//EN\r\nCALSCALE:GREGORIAN\r\nX-WR-CALNAME:"; 12127e0b8590SAndreas Boehler $out .= $calSettings['displayname']."\r\n"; 1213f69bb449SAndreas Boehler foreach($events as $event) 1214f69bb449SAndreas Boehler { 12157e0b8590SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 12167e0b8590SAndreas Boehler $evt = $vcal->VEVENT; 12177e0b8590SAndreas Boehler $out .= $evt->serialize(); 1218f69bb449SAndreas Boehler } 12197e0b8590SAndreas Boehler $out .= "END:VCALENDAR\r\n"; 1220f69bb449SAndreas Boehler return $out; 1221f69bb449SAndreas Boehler } 1222f69bb449SAndreas Boehler 12237c7c6b0bSAndreas Boehler /** 12247c7c6b0bSAndreas Boehler * Retrieve a configuration option for the plugin 12257c7c6b0bSAndreas Boehler * 12267c7c6b0bSAndreas Boehler * @param string $key The key to query 122721d04f73SAndreas Boehler * @return mixed The option set, null if not found 12287c7c6b0bSAndreas Boehler */ 12297c7c6b0bSAndreas Boehler public function getConfig($key) 12307c7c6b0bSAndreas Boehler { 12317c7c6b0bSAndreas Boehler return $this->getConf($key); 12327c7c6b0bSAndreas Boehler } 12337c7c6b0bSAndreas Boehler 1234a1a3b679SAndreas Boehler} 1235