1<?php 2/** 3 * Helper Class for the tagrevisions plugin 4 * This helper does the actual work. 5 * 6 * Configurable in DokuWiki's configuration 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12class helper_plugin_davcal extends DokuWiki_Plugin { 13 14 protected $sqlite = null; 15 16 /** 17 * Constructor to load the configuration 18 */ 19 public function helper_plugin_davcal() { 20 $this->sqlite =& plugin_load('helper', 'sqlite'); 21 if(!$this->sqlite) 22 { 23 msg('This plugin requires the sqlite plugin. Please install it.'); 24 return; 25 } 26 27 if(!$this->sqlite->init('davcal', DOKU_PLUGIN.'davcal/db/')) 28 { 29 return; 30 } 31 } 32 33 public function setCalendarNameForPage($name, $description, $id = null, $userid = null) 34 { 35 if(is_null($id)) 36 { 37 global $ID; 38 $id = $ID; 39 } 40 if(is_null($userid)) 41 $userid = $_SERVER['REMOTE_USER']; 42 $calid = $this->getCalendarIdForPage($id); 43 if($calid === false) 44 return $this->createCalendarForPage($name, $description, $id, $userid); 45 46 // Update the calendar name here 47 48 } 49 50 public function savePersonalSettings($settings, $userid = null) 51 { 52 if(is_null($userid)) 53 $userid = $_SERVER['REMOTE_USER']; 54 $this->sqlite->query("BEGIN TRANSACTION"); 55 56 foreach($settings as $key => $value) 57 { 58 $query = "INSERT OR REPLACE INTO calendarsettings (userid, key, value) VALUES (". 59 $this->sqlite->quote_string($userid).", ". 60 $this->sqlite->quote_string($key).", ". 61 $this->sqlite->quote_string($value).")"; 62 $res = $this->sqlite->query($query); 63 if($res === false) 64 return false; 65 } 66 $this->sqlite->query("COMMIT TRANSACTION"); 67 return true; 68 } 69 70 public function getPersonalSettings($userid = null) 71 { 72 if(is_null($userid)) 73 $userid = $_SERVER['REMOTE_USER']; 74 75 $settings = array(); 76 $query = "SELECT key, value FROM calendarsettings WHERE userid=".$this->sqlite->quote_string($userid); 77 $res = $this->sqlite->query($query); 78 $arr = $this->sqlite->res2arr($res); 79 foreach($arr as $row) 80 { 81 $settings[$row['key']] = $row['value']; 82 } 83 return $settings; 84 } 85 86 public function getCalendarIdForPage($id = null) 87 { 88 if(is_null($id)) 89 { 90 global $ID; 91 $id = $ID; 92 } 93 94 $query = "SELECT calid FROM pagetocalendarmapping WHERE page=".$this->sqlite->quote_string($id); 95 $res = $this->sqlite->query($query); 96 $row = $this->sqlite->res2row($res); 97 if(isset($row['calid'])) 98 return $row['calid']; 99 else 100 return false; 101 } 102 103 public function getCalendarIdToPageMapping() 104 { 105 $query = "SELECT calid, page FROM pagetocalendarmapping"; 106 $res = $this->sqlite->query($query); 107 $arr = $this->sqlite->res2arr($res); 108 return $arr; 109 } 110 111 public function getCalendarIdsForUser($principalUri) 112 { 113 $user = explode('/', $principalUri); 114 $user = end($user); 115 $mapping = $this->getCalendarIdToPageMapping(); 116 $calids = array(); 117 foreach($mapping as $row) 118 { 119 $id = $row['calid']; 120 $page = $row['page']; 121 $acl = auth_quickaclcheck($page); 122 if($acl >= AUTH_READ) 123 { 124 $write = $acl > AUTH_READ; 125 $calids[$id] = array('readonly' => !$write); 126 } 127 } 128 return $calids; 129 } 130 131 public function createCalendarForPage($name, $description, $id = null, $userid = null) 132 { 133 if(is_null($id)) 134 { 135 global $ID; 136 $id = $ID; 137 } 138 if(is_null($userid)) 139 $userid = $_SERVER['REMOTE_USER']; 140 $values = array('principals/'.$userid, 141 $name, 142 str_replace(array('/', ' ', ':'), '_', $id), 143 $description, 144 'VEVENT,VTODO', 145 0, 146 1); 147 $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) VALUES (".$this->sqlite->quote_and_join($values, ',').");"; 148 $res = $this->sqlite->query($query); 149 if($res === false) 150 return false; 151 $query = "SELECT id FROM calendars WHERE principaluri=".$this->sqlite->quote_string($values[0])." AND ". 152 "displayname=".$this->sqlite->quote_string($values[1])." AND ". 153 "uri=".$this->sqlite->quote_string($values[2])." AND ". 154 "description=".$this->sqlite->quote_string($values[3]); 155 $res = $this->sqlite->query($query); 156 $row = $this->sqlite->res2row($res); 157 if(isset($row['id'])) 158 { 159 $values = array($id, $row['id']); 160 $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 161 $res = $this->sqlite->query($query); 162 return ($res !== false); 163 } 164 165 return false; 166 } 167 168 public function addCalendarEntryToCalendarForPage($id, $user, $params) 169 { 170 require_once('vendor/autoload.php'); 171 $vcalendar = new \Sabre\VObject\Component\VCalendar(); 172 $event = $vcalendar->add('VEVENT'); 173 $event->summary = $params['eventname']; 174 $dtStart = new \DateTime($params['eventfrom'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 175 $dtEnd = new \DateTime($params['eventto'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 176 $event->DTSTART = $dtStart; 177 $event->DTEND = $dtEnd; 178 $calid = $this->getCalendarIdForPage($id); 179 $uri = uniqid('dokuwiki-').'.ics'; 180 $now = new DateTime(); 181 $eventStr = $vcalendar->serialize(); 182 183 $values = array($calid, 184 $uri, 185 $eventStr, 186 $now->getTimestamp(), 187 'VEVENT', 188 $event->DTSTART->getDateTime()->getTimeStamp(), 189 $event->DTEND->getDateTime()->getTimeStamp(), 190 strlen($eventStr), 191 md5($eventStr), 192 uniqid() 193 ); 194 195 $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 196 $res = $this->sqlite->query($query); 197 if($res !== false) 198 { 199 $this->updateSyncTokenLog($calid, $uri, 'added'); 200 return true; 201 } 202 return false; 203 } 204 205 public function getEventsWithinDateRange($id, $user, $startDate, $endDate) 206 { 207 $data = array(); 208 require_once('vendor/autoload.php'); 209 $calid = $this->getCalendarIdForPage($id); 210 $startTs = new \DateTime($startDate); 211 $endTs = new \DateTime($endDate); 212 $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid=". 213 $this->sqlite->quote_string($calid)." AND firstoccurence > ". 214 $this->sqlite->quote_string($startTs->getTimestamp())." AND firstoccurence < ". 215 $this->sqlite->quote_string($endTs->getTimestamp()); 216 $res = $this->sqlite->query($query); 217 $arr = $this->sqlite->res2arr($res); 218 foreach($arr as $row) 219 { 220 if(isset($row['calendardata'])) 221 { 222 $vcal = \Sabre\VObject\Reader::read($row['calendardata']); 223 $start = $vcal->VEVENT->DTSTART->getDateTime(); 224 $end = $vcal->VEVENT->DTEND->getDateTime(); 225 $summary = (string)$vcal->VEVENT->summary; 226 $data[] = array("title" => $summary, "start" => $start->format(\DateTime::W3C), 227 "end" => $end->format(\DateTime::W3C), 228 "id" => $row['uid']); 229 } 230 } 231 return $data; 232 } 233 234 public function getEventWithUid($uid) 235 { 236 $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid=". 237 $this->sqlite->quote_string($uid); 238 $res = $this->sqlite->query($query); 239 $row = $this->sqlite->res2row($res); 240 return $row; 241 } 242 243 public function editCalendarEntryForPage($id, $user, $params) 244 { 245 $uid = $params['uid']; 246 $event = $this->getEventWithUid($uid); 247 require_once('vendor/autoload.php'); 248 if(!isset($event['calendardata'])) 249 return false; 250 $uri = $event['uri']; 251 $calid = $event['calendarid']; 252 $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 253 $vcal->VEVENT->summary = $params['eventname']; 254 $dtStart = new \DateTime($params['eventfrom'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 255 $dtEnd = new \DateTime($params['eventto'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 256 $vcal->VEVENT->DTSTART = $dtStart; 257 $vcal->VEVENT->DTEND = $dtEnd; 258 $now = new DateTime(); 259 $eventStr = $vcal->serialize(); 260 261 $query = "UPDATE calendarobjects SET calendardata=".$this->sqlite->quote_string($eventStr). 262 ", lastmodified=".$this->sqlite->quote_string($now->getTimestamp()). 263 ", firstoccurence=".$this->sqlite->quote_string($dtStart->getTimestamp()). 264 ", lastoccurence=".$this->sqlite->quote_string($dtEnd->getTimestamp()). 265 ", size=".strlen($eventStr). 266 ", etag=".$this->sqlite->quote_string(md5($eventStr)). 267 " WHERE uid=".$this->sqlite->quote_string($uid); 268 $res = $this->sqlite->query($query); 269 if($res !== false) 270 { 271 $this->updateSyncTokenLog($calid, $uri, 'modified'); 272 return true; 273 } 274 return false; 275 } 276 277 public function deleteCalendarEntryForPage($id, $params) 278 { 279 $uid = $params['uid']; 280 $event = $this->getEventWithUid($uid); 281 $calid = $event['calendarid']; 282 $uri = $event['uri']; 283 $query = "DELETE FROM calendarobjects WHERE uid=".$this->sqlite->quote_string($uid); 284 $res = $this->sqlite->query($query); 285 if($res !== false) 286 { 287 $this->updateSyncTokenLog($calid, $uri, 'deleted'); 288 } 289 return true; 290 } 291 292 public function getSyncTokenForCalendar($calid) 293 { 294 $query = "SELECT synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid); 295 $res = $this->sqlite->query($query); 296 $row = $this->sqlite->res2row($res); 297 if(isset($row['synctoken'])) 298 return $row['synctoken']; 299 return false; 300 } 301 302 public function operationNameToOperation($operationName) 303 { 304 switch($operationName) 305 { 306 case 'added': 307 return 1; 308 break; 309 case 'modified': 310 return 2; 311 break; 312 case 'deleted': 313 return 3; 314 break; 315 } 316 return false; 317 } 318 319 private function updateSyncTokenLog($calid, $uri, $operation) 320 { 321 $currentToken = $this->getSyncTokenForCalendar($calid); 322 $operationCode = $this->operationNameToOperation($operation); 323 if(($operationCode === false) || ($currentToken === false)) 324 return false; 325 $values = array($uri, 326 $currentToken, 327 $calid, 328 $operationCode 329 ); 330 $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(". 331 $this->sqlite->quote_and_join($values, ',').")"; 332 $res = $this->sqlite->query($query); 333 if($res === false) 334 return false; 335 $currentToken++; 336 $query = "UPDATE calendars SET synctoken=".$this->sqlite->quote_string($currentToken)." WHERE id=". 337 $this->sqlite->quote_string($calid); 338 $res = $this->sqlite->query($query); 339 return ($res !== false); 340 } 341 342} 343