1a1a3b679SAndreas Boehler<?php 2a1a3b679SAndreas Boehler/** 3a1a3b679SAndreas Boehler * Helper Class for the tagrevisions plugin 4a1a3b679SAndreas Boehler * This helper does the actual work. 5a1a3b679SAndreas Boehler * 6a1a3b679SAndreas Boehler * Configurable in DokuWiki's configuration 7a1a3b679SAndreas Boehler */ 8a1a3b679SAndreas Boehler 9a1a3b679SAndreas Boehler// must be run within Dokuwiki 10a1a3b679SAndreas Boehlerif(!defined('DOKU_INC')) die(); 11a1a3b679SAndreas Boehler 12a1a3b679SAndreas Boehlerclass helper_plugin_davcal extends DokuWiki_Plugin { 13a1a3b679SAndreas Boehler 14a1a3b679SAndreas Boehler protected $sqlite = null; 15a1a3b679SAndreas Boehler 16a1a3b679SAndreas Boehler /** 17a1a3b679SAndreas Boehler * Constructor to load the configuration 18a1a3b679SAndreas Boehler */ 19a1a3b679SAndreas Boehler public function helper_plugin_davcal() { 20a1a3b679SAndreas Boehler $this->sqlite =& plugin_load('helper', 'sqlite'); 21a1a3b679SAndreas Boehler if(!$this->sqlite) 22a1a3b679SAndreas Boehler { 23a1a3b679SAndreas Boehler msg('This plugin requires the sqlite plugin. Please install it.'); 24a1a3b679SAndreas Boehler return; 25a1a3b679SAndreas Boehler } 26a1a3b679SAndreas Boehler 27a1a3b679SAndreas Boehler if(!$this->sqlite->init('davcal', DOKU_PLUGIN.'davcal/db/')) 28a1a3b679SAndreas Boehler { 29a1a3b679SAndreas Boehler return; 30a1a3b679SAndreas Boehler } 31a1a3b679SAndreas Boehler } 32a1a3b679SAndreas Boehler 33a1a3b679SAndreas Boehler public function setCalendarNameForPage($name, $description, $id = null, $userid = null) 34a1a3b679SAndreas Boehler { 35a1a3b679SAndreas Boehler if(is_null($id)) 36a1a3b679SAndreas Boehler { 37a1a3b679SAndreas Boehler global $ID; 38a1a3b679SAndreas Boehler $id = $ID; 39a1a3b679SAndreas Boehler } 40a1a3b679SAndreas Boehler if(is_null($userid)) 41a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 42a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 43a1a3b679SAndreas Boehler if($calid === false) 44a1a3b679SAndreas Boehler return $this->createCalendarForPage($name, $description, $id, $userid); 45a1a3b679SAndreas Boehler 46b269830cSAndreas Boehler $query = "UPDATE calendars SET displayname=".$this->sqlite->quote_string($name).", ". 47b269830cSAndreas Boehler "description=".$this->sqlite->quote_string($description)." WHERE ". 48b269830cSAndreas Boehler "id=".$this->sqlite->quote_string($calid); 49b269830cSAndreas Boehler $res = $this->sqlite->query($query); 50b269830cSAndreas Boehler if($res !== false) 51b269830cSAndreas Boehler return true; 52b269830cSAndreas Boehler return false; 53a1a3b679SAndreas Boehler } 54a1a3b679SAndreas Boehler 55a495d34cSAndreas Boehler public function savePersonalSettings($settings, $userid = null) 56a495d34cSAndreas Boehler { 57a495d34cSAndreas Boehler if(is_null($userid)) 58a495d34cSAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 59a495d34cSAndreas Boehler $this->sqlite->query("BEGIN TRANSACTION"); 60a495d34cSAndreas Boehler 61bd883736SAndreas Boehler $query = "DELETE FROM calendarsettings WHERE userid=".$this->sqlite->quote_string($userid); 62bd883736SAndreas Boehler $this->sqlite->query($query); 63bd883736SAndreas Boehler 64a495d34cSAndreas Boehler foreach($settings as $key => $value) 65a495d34cSAndreas Boehler { 66bd883736SAndreas Boehler $query = "INSERT INTO calendarsettings (userid, key, value) VALUES (". 67a495d34cSAndreas Boehler $this->sqlite->quote_string($userid).", ". 68a495d34cSAndreas Boehler $this->sqlite->quote_string($key).", ". 69a495d34cSAndreas Boehler $this->sqlite->quote_string($value).")"; 70a495d34cSAndreas Boehler $res = $this->sqlite->query($query); 71a495d34cSAndreas Boehler if($res === false) 72a495d34cSAndreas Boehler return false; 73a495d34cSAndreas Boehler } 74a495d34cSAndreas Boehler $this->sqlite->query("COMMIT TRANSACTION"); 75a495d34cSAndreas Boehler return true; 76a495d34cSAndreas Boehler } 77a495d34cSAndreas Boehler 78a495d34cSAndreas Boehler public function getPersonalSettings($userid = null) 79a495d34cSAndreas Boehler { 80a495d34cSAndreas Boehler if(is_null($userid)) 81a495d34cSAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 82bd883736SAndreas Boehler // Some sane default settings 83bd883736SAndreas Boehler $settings = array( 84bd883736SAndreas Boehler 'timezone' => 'local', 85bd883736SAndreas Boehler 'weeknumbers' => '0', 86bd883736SAndreas Boehler 'workweek' => '0' 87bd883736SAndreas Boehler ); 88a495d34cSAndreas Boehler $query = "SELECT key, value FROM calendarsettings WHERE userid=".$this->sqlite->quote_string($userid); 89a495d34cSAndreas Boehler $res = $this->sqlite->query($query); 90a495d34cSAndreas Boehler $arr = $this->sqlite->res2arr($res); 91a495d34cSAndreas Boehler foreach($arr as $row) 92a495d34cSAndreas Boehler { 93a495d34cSAndreas Boehler $settings[$row['key']] = $row['value']; 94a495d34cSAndreas Boehler } 95a495d34cSAndreas Boehler return $settings; 96a495d34cSAndreas Boehler } 97a495d34cSAndreas Boehler 98a1a3b679SAndreas Boehler public function getCalendarIdForPage($id = null) 99a1a3b679SAndreas Boehler { 100a1a3b679SAndreas Boehler if(is_null($id)) 101a1a3b679SAndreas Boehler { 102a1a3b679SAndreas Boehler global $ID; 103a1a3b679SAndreas Boehler $id = $ID; 104a1a3b679SAndreas Boehler } 105a1a3b679SAndreas Boehler 106a1a3b679SAndreas Boehler $query = "SELECT calid FROM pagetocalendarmapping WHERE page=".$this->sqlite->quote_string($id); 107a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 108a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 109a1a3b679SAndreas Boehler if(isset($row['calid'])) 110a1a3b679SAndreas Boehler return $row['calid']; 111a1a3b679SAndreas Boehler else 112a1a3b679SAndreas Boehler return false; 113a1a3b679SAndreas Boehler } 114a1a3b679SAndreas Boehler 115a1a3b679SAndreas Boehler public function getCalendarIdToPageMapping() 116a1a3b679SAndreas Boehler { 117a1a3b679SAndreas Boehler $query = "SELECT calid, page FROM pagetocalendarmapping"; 118a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 119a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 120a1a3b679SAndreas Boehler return $arr; 121a1a3b679SAndreas Boehler } 122a1a3b679SAndreas Boehler 123a1a3b679SAndreas Boehler public function getCalendarIdsForUser($principalUri) 124a1a3b679SAndreas Boehler { 125a1a3b679SAndreas Boehler $user = explode('/', $principalUri); 126a1a3b679SAndreas Boehler $user = end($user); 127a1a3b679SAndreas Boehler $mapping = $this->getCalendarIdToPageMapping(); 128a1a3b679SAndreas Boehler $calids = array(); 129a1a3b679SAndreas Boehler foreach($mapping as $row) 130a1a3b679SAndreas Boehler { 131a1a3b679SAndreas Boehler $id = $row['calid']; 132a1a3b679SAndreas Boehler $page = $row['page']; 133a1a3b679SAndreas Boehler $acl = auth_quickaclcheck($page); 134a1a3b679SAndreas Boehler if($acl >= AUTH_READ) 135a1a3b679SAndreas Boehler { 136a1a3b679SAndreas Boehler $write = $acl > AUTH_READ; 137a1a3b679SAndreas Boehler $calids[$id] = array('readonly' => !$write); 138a1a3b679SAndreas Boehler } 139a1a3b679SAndreas Boehler } 140a1a3b679SAndreas Boehler return $calids; 141a1a3b679SAndreas Boehler } 142a1a3b679SAndreas Boehler 143a1a3b679SAndreas Boehler public function createCalendarForPage($name, $description, $id = null, $userid = null) 144a1a3b679SAndreas Boehler { 145a1a3b679SAndreas Boehler if(is_null($id)) 146a1a3b679SAndreas Boehler { 147a1a3b679SAndreas Boehler global $ID; 148a1a3b679SAndreas Boehler $id = $ID; 149a1a3b679SAndreas Boehler } 150a1a3b679SAndreas Boehler if(is_null($userid)) 151a1a3b679SAndreas Boehler $userid = $_SERVER['REMOTE_USER']; 152a1a3b679SAndreas Boehler $values = array('principals/'.$userid, 153a1a3b679SAndreas Boehler $name, 154a1a3b679SAndreas Boehler str_replace(array('/', ' ', ':'), '_', $id), 155a1a3b679SAndreas Boehler $description, 156a1a3b679SAndreas Boehler 'VEVENT,VTODO', 15755a741c0SAndreas Boehler 0, 15855a741c0SAndreas Boehler 1); 15955a741c0SAndreas Boehler $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) VALUES (".$this->sqlite->quote_and_join($values, ',').");"; 160a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 16155a741c0SAndreas Boehler if($res === false) 16255a741c0SAndreas Boehler return false; 163a1a3b679SAndreas Boehler $query = "SELECT id FROM calendars WHERE principaluri=".$this->sqlite->quote_string($values[0])." AND ". 164a1a3b679SAndreas Boehler "displayname=".$this->sqlite->quote_string($values[1])." AND ". 165a1a3b679SAndreas Boehler "uri=".$this->sqlite->quote_string($values[2])." AND ". 166a1a3b679SAndreas Boehler "description=".$this->sqlite->quote_string($values[3]); 167a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 168a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 169a1a3b679SAndreas Boehler if(isset($row['id'])) 170a1a3b679SAndreas Boehler { 171a1a3b679SAndreas Boehler $values = array($id, $row['id']); 172a1a3b679SAndreas Boehler $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 173a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 17455a741c0SAndreas Boehler return ($res !== false); 175a1a3b679SAndreas Boehler } 176a1a3b679SAndreas Boehler 177a1a3b679SAndreas Boehler return false; 178a1a3b679SAndreas Boehler } 179a1a3b679SAndreas Boehler 180a1a3b679SAndreas Boehler public function addCalendarEntryToCalendarForPage($id, $user, $params) 181a1a3b679SAndreas Boehler { 182bd883736SAndreas Boehler $settings = $this->getPersonalSettings($user); 183bd883736SAndreas Boehler if($settings['timezone'] !== '' && $settings['timezone'] !== 'local') 184bd883736SAndreas Boehler $timezone = new \DateTimeZone($settings['timezone']); 185a25c89eaSAndreas Boehler elseif($settings['timezone'] === 'local') 186a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 187bd883736SAndreas Boehler else 188bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 189b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 190b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 191b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 192b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 193a1a3b679SAndreas Boehler require_once('vendor/autoload.php'); 194a1a3b679SAndreas Boehler $vcalendar = new \Sabre\VObject\Component\VCalendar(); 195a1a3b679SAndreas Boehler $event = $vcalendar->add('VEVENT'); 196b269830cSAndreas Boehler $uuid = \Sabre\VObject\UUIDUtil::getUUID(); 197b269830cSAndreas Boehler $event->add('UID', $uuid); 198a1a3b679SAndreas Boehler $event->summary = $params['eventname']; 1990eebc909SAndreas Boehler $description = $params['eventdescription']; 2000eebc909SAndreas Boehler if($description !== '') 2010eebc909SAndreas Boehler $event->add('DESCRIPTION', $description); 202b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 203b269830cSAndreas Boehler $event->add('DTSTAMP', $dtStamp); 204b269830cSAndreas Boehler $event->add('CREATED', $dtStamp); 205b269830cSAndreas Boehler $event->add('LAST-MODIFIED', $dtStamp); 206b269830cSAndreas Boehler $dtStart = new \DateTime(); 207a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 208b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 209b269830cSAndreas Boehler if($params['allday'] != '1') 210b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 211b269830cSAndreas Boehler $dtEnd = new \DateTime(); 212a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 213b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 214b269830cSAndreas Boehler if($params['allday'] != '1') 215b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 216b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 217b269830cSAndreas Boehler if($params['allday'] == '1') 218b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 219b269830cSAndreas Boehler $dtStartEv = $event->add('DTSTART', $dtStart); 220b269830cSAndreas Boehler $dtEndEv = $event->add('DTEND', $dtEnd); 221b269830cSAndreas Boehler if($params['allday'] == '1') 222b269830cSAndreas Boehler { 223b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 224b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 225b269830cSAndreas Boehler } 226a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 227a1a3b679SAndreas Boehler $uri = uniqid('dokuwiki-').'.ics'; 228a1a3b679SAndreas Boehler $now = new DateTime(); 229a1a3b679SAndreas Boehler $eventStr = $vcalendar->serialize(); 230a1a3b679SAndreas Boehler 231a1a3b679SAndreas Boehler $values = array($calid, 232a1a3b679SAndreas Boehler $uri, 233a1a3b679SAndreas Boehler $eventStr, 234a1a3b679SAndreas Boehler $now->getTimestamp(), 235a1a3b679SAndreas Boehler 'VEVENT', 236a1a3b679SAndreas Boehler $event->DTSTART->getDateTime()->getTimeStamp(), 237a1a3b679SAndreas Boehler $event->DTEND->getDateTime()->getTimeStamp(), 238a1a3b679SAndreas Boehler strlen($eventStr), 239a1a3b679SAndreas Boehler md5($eventStr), 240a1a3b679SAndreas Boehler uniqid() 241a1a3b679SAndreas Boehler ); 242a1a3b679SAndreas Boehler 243a1a3b679SAndreas Boehler $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 244a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 24555a741c0SAndreas Boehler if($res !== false) 24655a741c0SAndreas Boehler { 24755a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'added'); 248a1a3b679SAndreas Boehler return true; 249a1a3b679SAndreas Boehler } 25055a741c0SAndreas Boehler return false; 25155a741c0SAndreas Boehler } 252a1a3b679SAndreas Boehler 253b269830cSAndreas Boehler public function getCalendarSettings($calid) 254b269830cSAndreas Boehler { 255b269830cSAndreas Boehler $query = "SELECT principaluri, displayname, uri, description, components, transparent, synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid); 256b269830cSAndreas Boehler $res = $this->sqlite->query($query); 257b269830cSAndreas Boehler $row = $this->sqlite->res2row($res); 258b269830cSAndreas Boehler return $row; 259b269830cSAndreas Boehler } 260b269830cSAndreas Boehler 261a1a3b679SAndreas Boehler public function getEventsWithinDateRange($id, $user, $startDate, $endDate) 262a1a3b679SAndreas Boehler { 263bd883736SAndreas Boehler $settings = $this->getPersonalSettings($user); 264bd883736SAndreas Boehler if($settings['timezone'] !== '' && $settings['timezone'] !== 'local') 265bd883736SAndreas Boehler $timezone = new \DateTimeZone($settings['timezone']); 266bd883736SAndreas Boehler else 267bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 268a1a3b679SAndreas Boehler $data = array(); 269a1a3b679SAndreas Boehler require_once('vendor/autoload.php'); 270a1a3b679SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 271a1a3b679SAndreas Boehler $startTs = new \DateTime($startDate); 272a1a3b679SAndreas Boehler $endTs = new \DateTime($endDate); 273*ebc4eb57SAndreas Boehler $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid=". 274*ebc4eb57SAndreas Boehler $this->sqlite->quote_string($calid)." AND firstoccurence < ". 275*ebc4eb57SAndreas Boehler $this->sqlite->quote_string($endTs->getTimestamp())." AND lastoccurence > ". 276*ebc4eb57SAndreas Boehler $this->sqlite->quote_string($startTs->getTimestamp()); 277a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 278a1a3b679SAndreas Boehler $arr = $this->sqlite->res2arr($res); 279a1a3b679SAndreas Boehler foreach($arr as $row) 280a1a3b679SAndreas Boehler { 281a1a3b679SAndreas Boehler if(isset($row['calendardata'])) 282a1a3b679SAndreas Boehler { 283b269830cSAndreas Boehler $entry = array(); 284a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($row['calendardata']); 285*ebc4eb57SAndreas Boehler $recurrence = $vcal->VEVENT->RRULE; 286*ebc4eb57SAndreas Boehler if($recurrence != null) 287*ebc4eb57SAndreas Boehler { 288*ebc4eb57SAndreas Boehler $rEvents = new \Sabre\VObject\Recur\EventIterator(array($vcal->VEVENT)); 289*ebc4eb57SAndreas Boehler $rEvents->rewind(); 290*ebc4eb57SAndreas Boehler $done = false; 291*ebc4eb57SAndreas Boehler while($rEvents->valid() && !$done) 292*ebc4eb57SAndreas Boehler { 293*ebc4eb57SAndreas Boehler $event = $rEvents->getEventObject(); 294*ebc4eb57SAndreas Boehler if(($rEvents->getDtStart()->getTimestamp() > $endTs->getTimestamp()) && 295*ebc4eb57SAndreas Boehler ($rEvents->getDtEnd()->getTimestamp() > $endTs->getTimestamp())) 296*ebc4eb57SAndreas Boehler $done = true; 297*ebc4eb57SAndreas Boehler if($rEvents->getDtEnd()->getTimestamp() < $startTs->getTimestamp()) 298*ebc4eb57SAndreas Boehler { 299*ebc4eb57SAndreas Boehler $rEvents->next(); 300*ebc4eb57SAndreas Boehler continue; 301*ebc4eb57SAndreas Boehler } 302*ebc4eb57SAndreas Boehler $data[] = $this->convertIcalDataToEntry($event, $timezone, $row['uid']); 303*ebc4eb57SAndreas Boehler $rEvents->next(); 304*ebc4eb57SAndreas Boehler } 305*ebc4eb57SAndreas Boehler } 306*ebc4eb57SAndreas Boehler else 307*ebc4eb57SAndreas Boehler $data[] = $this->convertIcalDataToEntry($vcal->VEVENT, $timezone, $row['uid']); 308*ebc4eb57SAndreas Boehler } 309*ebc4eb57SAndreas Boehler } 310*ebc4eb57SAndreas Boehler return $data; 311*ebc4eb57SAndreas Boehler } 312*ebc4eb57SAndreas Boehler 313*ebc4eb57SAndreas Boehler private function convertIcalDataToEntry($event, $timezone, $uid) 314*ebc4eb57SAndreas Boehler { 315*ebc4eb57SAndreas Boehler $entry = array(); 316*ebc4eb57SAndreas Boehler $start = $event->DTSTART; 317b269830cSAndreas Boehler if($start !== null) 318b269830cSAndreas Boehler { 319b269830cSAndreas Boehler $dtStart = $start->getDateTime(); 320b269830cSAndreas Boehler $dtStart->setTimezone($timezone); 321b269830cSAndreas Boehler $entry['start'] = $dtStart->format(\DateTime::ATOM); 322b269830cSAndreas Boehler if($start['VALUE'] == 'DATE') 323b269830cSAndreas Boehler $entry['allDay'] = true; 324b269830cSAndreas Boehler else 325b269830cSAndreas Boehler $entry['allDay'] = false; 326b269830cSAndreas Boehler } 327*ebc4eb57SAndreas Boehler $end = $event->DTEND; 328b269830cSAndreas Boehler if($end !== null) 329b269830cSAndreas Boehler { 330b269830cSAndreas Boehler $dtEnd = $end->getDateTime(); 331b269830cSAndreas Boehler $dtEnd->setTimezone($timezone); 332b269830cSAndreas Boehler $entry['end'] = $dtEnd->format(\DateTime::ATOM); 333b269830cSAndreas Boehler } 334*ebc4eb57SAndreas Boehler $description = $event->DESCRIPTION; 3350eebc909SAndreas Boehler if($description !== null) 3360eebc909SAndreas Boehler $entry['description'] = (string)$description; 3370eebc909SAndreas Boehler else 3380eebc909SAndreas Boehler $entry['description'] = ''; 339*ebc4eb57SAndreas Boehler $entry['title'] = (string)$event->summary; 340*ebc4eb57SAndreas Boehler $entry['id'] = $uid; 341*ebc4eb57SAndreas Boehler return $entry; 342a1a3b679SAndreas Boehler } 343a1a3b679SAndreas Boehler 344a1a3b679SAndreas Boehler public function getEventWithUid($uid) 345a1a3b679SAndreas Boehler { 34655a741c0SAndreas Boehler $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid=". 347a1a3b679SAndreas Boehler $this->sqlite->quote_string($uid); 348a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 349a1a3b679SAndreas Boehler $row = $this->sqlite->res2row($res); 350a1a3b679SAndreas Boehler return $row; 351a1a3b679SAndreas Boehler } 352a1a3b679SAndreas Boehler 353f69bb449SAndreas Boehler public function getAllCalendarEvents($calid) 354f69bb449SAndreas Boehler { 355f69bb449SAndreas Boehler $query = "SELECT calendardata, uid, componenttype, uri FROM calendarobjects WHERE calendarid=". 356f69bb449SAndreas Boehler $this->sqlite->quote_string($calid); 357f69bb449SAndreas Boehler $res = $this->sqlite->query($query); 358f69bb449SAndreas Boehler $arr = $this->sqlite->res2arr($res); 359f69bb449SAndreas Boehler return $arr; 360f69bb449SAndreas Boehler } 361f69bb449SAndreas Boehler 362a1a3b679SAndreas Boehler public function editCalendarEntryForPage($id, $user, $params) 363a1a3b679SAndreas Boehler { 364bd883736SAndreas Boehler $settings = $this->getPersonalSettings($user); 365bd883736SAndreas Boehler if($settings['timezone'] !== '' && $settings['timezone'] !== 'local') 366bd883736SAndreas Boehler $timezone = new \DateTimeZone($settings['timezone']); 367a25c89eaSAndreas Boehler elseif($settings['timezone'] === 'local') 368a25c89eaSAndreas Boehler $timezone = new \DateTimeZone($params['detectedtz']); 369bd883736SAndreas Boehler else 370bd883736SAndreas Boehler $timezone = new \DateTimeZone('UTC'); 371b269830cSAndreas Boehler $startDate = explode('-', $params['eventfrom']); 372b269830cSAndreas Boehler $startTime = explode(':', $params['eventfromtime']); 373b269830cSAndreas Boehler $endDate = explode('-', $params['eventto']); 374b269830cSAndreas Boehler $endTime = explode(':', $params['eventtotime']); 37555a741c0SAndreas Boehler $uid = $params['uid']; 37655a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 377a1a3b679SAndreas Boehler require_once('vendor/autoload.php'); 378a1a3b679SAndreas Boehler if(!isset($event['calendardata'])) 379a1a3b679SAndreas Boehler return false; 38055a741c0SAndreas Boehler $uri = $event['uri']; 38155a741c0SAndreas Boehler $calid = $event['calendarid']; 382a1a3b679SAndreas Boehler $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 383b269830cSAndreas Boehler $vevent = $vcal->VEVENT; 384b269830cSAndreas Boehler $vevent->summary = $params['eventname']; 385b269830cSAndreas Boehler $dtStamp = new \DateTime(null, new \DateTimeZone('UTC')); 3860eebc909SAndreas Boehler $description = $params['eventdescription']; 3870eebc909SAndreas Boehler $vevent->remove('DESCRIPTION'); 388b269830cSAndreas Boehler $vevent->remove('DTSTAMP'); 389b269830cSAndreas Boehler $vevent->remove('LAST-MODIFIED'); 390b269830cSAndreas Boehler $vevent->add('DTSTAMP', $dtStamp); 391b269830cSAndreas Boehler $vevent->add('LAST-MODIFIED', $dtStamp); 3920eebc909SAndreas Boehler if($description !== '') 3930eebc909SAndreas Boehler $vevent->add('DESCRIPTION', $description); 394b269830cSAndreas Boehler $dtStart = new \DateTime(); 395a25c89eaSAndreas Boehler $dtStart->setTimezone($timezone); 396b269830cSAndreas Boehler $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2])); 397b269830cSAndreas Boehler if($params['allday'] != '1') 398b269830cSAndreas Boehler $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0); 399b269830cSAndreas Boehler $dtEnd = new \DateTime(); 400a25c89eaSAndreas Boehler $dtEnd->setTimezone($timezone); 401b269830cSAndreas Boehler $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2])); 402b269830cSAndreas Boehler if($params['allday'] != '1') 403b269830cSAndreas Boehler $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0); 404b269830cSAndreas Boehler // According to the VCal spec, we need to add a whole day here 405b269830cSAndreas Boehler if($params['allday'] == '1') 406b269830cSAndreas Boehler $dtEnd->add(new \DateInterval('P1D')); 407b269830cSAndreas Boehler $vevent->remove('DTSTART'); 408b269830cSAndreas Boehler $vevent->remove('DTEND'); 409b269830cSAndreas Boehler $dtStartEv = $vevent->add('DTSTART', $dtStart); 410b269830cSAndreas Boehler $dtEndEv = $vevent->add('DTEND', $dtEnd); 411b269830cSAndreas Boehler if($params['allday'] == '1') 412b269830cSAndreas Boehler { 413b269830cSAndreas Boehler $dtStartEv['VALUE'] = 'DATE'; 414b269830cSAndreas Boehler $dtEndEv['VALUE'] = 'DATE'; 415b269830cSAndreas Boehler } 416a1a3b679SAndreas Boehler $now = new DateTime(); 417a1a3b679SAndreas Boehler $eventStr = $vcal->serialize(); 418a1a3b679SAndreas Boehler 419a1a3b679SAndreas Boehler $query = "UPDATE calendarobjects SET calendardata=".$this->sqlite->quote_string($eventStr). 420a1a3b679SAndreas Boehler ", lastmodified=".$this->sqlite->quote_string($now->getTimestamp()). 421a1a3b679SAndreas Boehler ", firstoccurence=".$this->sqlite->quote_string($dtStart->getTimestamp()). 422a1a3b679SAndreas Boehler ", lastoccurence=".$this->sqlite->quote_string($dtEnd->getTimestamp()). 423a1a3b679SAndreas Boehler ", size=".strlen($eventStr). 424a1a3b679SAndreas Boehler ", etag=".$this->sqlite->quote_string(md5($eventStr)). 42555a741c0SAndreas Boehler " WHERE uid=".$this->sqlite->quote_string($uid); 426a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 42755a741c0SAndreas Boehler if($res !== false) 42855a741c0SAndreas Boehler { 42955a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'modified'); 430a1a3b679SAndreas Boehler return true; 431a1a3b679SAndreas Boehler } 43255a741c0SAndreas Boehler return false; 43355a741c0SAndreas Boehler } 434a1a3b679SAndreas Boehler 435a1a3b679SAndreas Boehler public function deleteCalendarEntryForPage($id, $params) 436a1a3b679SAndreas Boehler { 437a1a3b679SAndreas Boehler $uid = $params['uid']; 43855a741c0SAndreas Boehler $event = $this->getEventWithUid($uid); 4392c14b82bSAndreas Boehler $calid = $event['calendarid']; 44055a741c0SAndreas Boehler $uri = $event['uri']; 441a1a3b679SAndreas Boehler $query = "DELETE FROM calendarobjects WHERE uid=".$this->sqlite->quote_string($uid); 442a1a3b679SAndreas Boehler $res = $this->sqlite->query($query); 44355a741c0SAndreas Boehler if($res !== false) 44455a741c0SAndreas Boehler { 44555a741c0SAndreas Boehler $this->updateSyncTokenLog($calid, $uri, 'deleted'); 44655a741c0SAndreas Boehler } 447a1a3b679SAndreas Boehler return true; 448a1a3b679SAndreas Boehler } 449a1a3b679SAndreas Boehler 45055a741c0SAndreas Boehler public function getSyncTokenForCalendar($calid) 45155a741c0SAndreas Boehler { 452b269830cSAndreas Boehler $row = $this->getCalendarSettings($calid); 45355a741c0SAndreas Boehler if(isset($row['synctoken'])) 45455a741c0SAndreas Boehler return $row['synctoken']; 45555a741c0SAndreas Boehler return false; 45655a741c0SAndreas Boehler } 45755a741c0SAndreas Boehler 45855a741c0SAndreas Boehler public function operationNameToOperation($operationName) 45955a741c0SAndreas Boehler { 46055a741c0SAndreas Boehler switch($operationName) 46155a741c0SAndreas Boehler { 46255a741c0SAndreas Boehler case 'added': 46355a741c0SAndreas Boehler return 1; 46455a741c0SAndreas Boehler break; 46555a741c0SAndreas Boehler case 'modified': 46655a741c0SAndreas Boehler return 2; 46755a741c0SAndreas Boehler break; 46855a741c0SAndreas Boehler case 'deleted': 46955a741c0SAndreas Boehler return 3; 47055a741c0SAndreas Boehler break; 47155a741c0SAndreas Boehler } 47255a741c0SAndreas Boehler return false; 47355a741c0SAndreas Boehler } 47455a741c0SAndreas Boehler 47555a741c0SAndreas Boehler private function updateSyncTokenLog($calid, $uri, $operation) 47655a741c0SAndreas Boehler { 47755a741c0SAndreas Boehler $currentToken = $this->getSyncTokenForCalendar($calid); 47855a741c0SAndreas Boehler $operationCode = $this->operationNameToOperation($operation); 47955a741c0SAndreas Boehler if(($operationCode === false) || ($currentToken === false)) 48055a741c0SAndreas Boehler return false; 48155a741c0SAndreas Boehler $values = array($uri, 48255a741c0SAndreas Boehler $currentToken, 48355a741c0SAndreas Boehler $calid, 48455a741c0SAndreas Boehler $operationCode 48555a741c0SAndreas Boehler ); 48655a741c0SAndreas Boehler $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(". 48755a741c0SAndreas Boehler $this->sqlite->quote_and_join($values, ',').")"; 48855a741c0SAndreas Boehler $res = $this->sqlite->query($query); 48955a741c0SAndreas Boehler if($res === false) 49055a741c0SAndreas Boehler return false; 49155a741c0SAndreas Boehler $currentToken++; 49255a741c0SAndreas Boehler $query = "UPDATE calendars SET synctoken=".$this->sqlite->quote_string($currentToken)." WHERE id=". 49355a741c0SAndreas Boehler $this->sqlite->quote_string($calid); 49455a741c0SAndreas Boehler $res = $this->sqlite->query($query); 49555a741c0SAndreas Boehler return ($res !== false); 49655a741c0SAndreas Boehler } 49755a741c0SAndreas Boehler 498b269830cSAndreas Boehler public function getSyncUrlForPage($id, $user = null) 499b269830cSAndreas Boehler { 500b269830cSAndreas Boehler if(is_null($user)) 501b269830cSAndreas Boehler $user = $_SERVER['REMOTE_USER']; 502b269830cSAndreas Boehler 503b269830cSAndreas Boehler $calid = $this->getCalendarIdForPage($id); 504b269830cSAndreas Boehler if($calid === false) 505b269830cSAndreas Boehler return false; 506b269830cSAndreas Boehler 507b269830cSAndreas Boehler $calsettings = $this->getCalendarSettings($calid); 508b269830cSAndreas Boehler if(!isset($calsettings['uri'])) 509b269830cSAndreas Boehler return false; 510b269830cSAndreas Boehler 511b269830cSAndreas Boehler $syncurl = DOKU_URL.'lib/plugins/davcal/calendarserver.php/calendars/'.$user.'/'.$calsettings['uri']; 512b269830cSAndreas Boehler return $syncurl; 513b269830cSAndreas Boehler } 514b269830cSAndreas Boehler 515f69bb449SAndreas Boehler public function getPrivateURLForPage($id) 516f69bb449SAndreas Boehler { 517f69bb449SAndreas Boehler $calid = $this->getCalendarIdForPage($id); 518f69bb449SAndreas Boehler if($calid === false) 519f69bb449SAndreas Boehler return false; 520f69bb449SAndreas Boehler 521f69bb449SAndreas Boehler return $this->getPrivateURLForCalendar($calid); 522f69bb449SAndreas Boehler } 523f69bb449SAndreas Boehler 524f69bb449SAndreas Boehler public function getPrivateURLForCalendar($calid) 525f69bb449SAndreas Boehler { 526f69bb449SAndreas Boehler $query = "SELECT url FROM calendartoprivateurlmapping WHERE calid=".$this->sqlite->quote_string($calid); 527f69bb449SAndreas Boehler $res = $this->sqlite->query($query); 528f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 529f69bb449SAndreas Boehler if(!isset($row['url'])) 530f69bb449SAndreas Boehler { 531f69bb449SAndreas Boehler $url = uniqid("dokuwiki-").".ics"; 532f69bb449SAndreas Boehler $values = array( 533f69bb449SAndreas Boehler $url, 534f69bb449SAndreas Boehler $calid 535f69bb449SAndreas Boehler ); 536f69bb449SAndreas Boehler $query = "INSERT INTO calendartoprivateurlmapping (url, calid) VALUES(". 537f69bb449SAndreas Boehler $this->sqlite->quote_and_join($values, ", ").")"; 538f69bb449SAndreas Boehler $res = $this->sqlite->query($query); 539f69bb449SAndreas Boehler if($res === false) 540f69bb449SAndreas Boehler return false; 541f69bb449SAndreas Boehler } 542f69bb449SAndreas Boehler else 543f69bb449SAndreas Boehler { 544f69bb449SAndreas Boehler $url = $row['url']; 545f69bb449SAndreas Boehler } 54670d9aa2aSAndreas Boehler return DOKU_URL.'lib/plugins/davcal/ics.php/'.$url; 547f69bb449SAndreas Boehler } 548f69bb449SAndreas Boehler 549f69bb449SAndreas Boehler public function getCalendarForPrivateURL($url) 550f69bb449SAndreas Boehler { 551f69bb449SAndreas Boehler $query = "SELECT calid FROM calendartoprivateurlmapping WHERE url=".$this->sqlite->quote_string($url); 552f69bb449SAndreas Boehler $res = $this->sqlite->query($query); 553f69bb449SAndreas Boehler $row = $this->sqlite->res2row($res); 554f69bb449SAndreas Boehler if(!isset($row['calid'])) 555f69bb449SAndreas Boehler return false; 556f69bb449SAndreas Boehler return $row['calid']; 557f69bb449SAndreas Boehler } 558f69bb449SAndreas Boehler 559f69bb449SAndreas Boehler public function getCalendarAsICSFeed($calid) 560f69bb449SAndreas Boehler { 561f69bb449SAndreas Boehler $calSettings = $this->getCalendarSettings($calid); 562f69bb449SAndreas Boehler if($calSettings === false) 563f69bb449SAndreas Boehler return false; 564f69bb449SAndreas Boehler $events = $this->getAllCalendarEvents($calid); 565f69bb449SAndreas Boehler if($events === false) 566f69bb449SAndreas Boehler return false; 567f69bb449SAndreas Boehler 568f69bb449SAndreas Boehler $out = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//DAVCal//DAVCal for DokuWiki//EN\nCALSCALE:GREGORIAN\nX-WR-CALNAME:"; 569f69bb449SAndreas Boehler $out .= $calSettings['displayname']."\n"; 570f69bb449SAndreas Boehler foreach($events as $event) 571f69bb449SAndreas Boehler { 572f69bb449SAndreas Boehler $out .= rtrim($event['calendardata']); 573f69bb449SAndreas Boehler $out .= "\n"; 574f69bb449SAndreas Boehler } 575f69bb449SAndreas Boehler $out .= "END:VCALENDAR\n"; 576f69bb449SAndreas Boehler return $out; 577f69bb449SAndreas Boehler } 578f69bb449SAndreas Boehler 579a1a3b679SAndreas Boehler} 580