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 getCalendarIdForPage($id = null) 51 { 52 if(is_null($id)) 53 { 54 global $ID; 55 $id = $ID; 56 } 57 58 $query = "SELECT calid FROM pagetocalendarmapping WHERE page=".$this->sqlite->quote_string($id); 59 $res = $this->sqlite->query($query); 60 $row = $this->sqlite->res2row($res); 61 if(isset($row['calid'])) 62 return $row['calid']; 63 else 64 return false; 65 } 66 67 public function getCalendarIdToPageMapping() 68 { 69 $query = "SELECT calid, page FROM pagetocalendarmapping"; 70 $res = $this->sqlite->query($query); 71 $arr = $this->sqlite->res2arr($res); 72 return $arr; 73 } 74 75 public function getCalendarIdsForUser($principalUri) 76 { 77 $user = explode('/', $principalUri); 78 $user = end($user); 79 $mapping = $this->getCalendarIdToPageMapping(); 80 $calids = array(); 81 foreach($mapping as $row) 82 { 83 $id = $row['calid']; 84 $page = $row['page']; 85 $acl = auth_quickaclcheck($page); 86 if($acl >= AUTH_READ) 87 { 88 $write = $acl > AUTH_READ; 89 $calids[$id] = array('readonly' => !$write); 90 } 91 } 92 return $calids; 93 } 94 95 public function createCalendarForPage($name, $description, $id = null, $userid = null) 96 { 97 if(is_null($id)) 98 { 99 global $ID; 100 $id = $ID; 101 } 102 if(is_null($userid)) 103 $userid = $_SERVER['REMOTE_USER']; 104 $values = array('principals/'.$userid, 105 $name, 106 str_replace(array('/', ' ', ':'), '_', $id), 107 $description, 108 'VEVENT,VTODO', 109 0, 110 1); 111 $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) VALUES (".$this->sqlite->quote_and_join($values, ',').");"; 112 $res = $this->sqlite->query($query); 113 if($res === false) 114 return false; 115 $query = "SELECT id FROM calendars WHERE principaluri=".$this->sqlite->quote_string($values[0])." AND ". 116 "displayname=".$this->sqlite->quote_string($values[1])." AND ". 117 "uri=".$this->sqlite->quote_string($values[2])." AND ". 118 "description=".$this->sqlite->quote_string($values[3]); 119 $res = $this->sqlite->query($query); 120 $row = $this->sqlite->res2row($res); 121 if(isset($row['id'])) 122 { 123 $values = array($id, $row['id']); 124 $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 125 $res = $this->sqlite->query($query); 126 return ($res !== false); 127 } 128 129 return false; 130 } 131 132 public function addCalendarEntryToCalendarForPage($id, $user, $params) 133 { 134 require_once('vendor/autoload.php'); 135 $vcalendar = new \Sabre\VObject\Component\VCalendar(); 136 $event = $vcalendar->add('VEVENT'); 137 $event->summary = $params['eventname']; 138 $dtStart = new \DateTime($params['eventfrom'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 139 $dtEnd = new \DateTime($params['eventto'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 140 $event->DTSTART = $dtStart; 141 $event->DTEND = $dtEnd; 142 $calid = $this->getCalendarIdForPage($id); 143 $uri = uniqid('dokuwiki-').'.ics'; 144 $now = new DateTime(); 145 $eventStr = $vcalendar->serialize(); 146 147 $values = array($calid, 148 $uri, 149 $eventStr, 150 $now->getTimestamp(), 151 'VEVENT', 152 $event->DTSTART->getDateTime()->getTimeStamp(), 153 $event->DTEND->getDateTime()->getTimeStamp(), 154 strlen($eventStr), 155 md5($eventStr), 156 uniqid() 157 ); 158 159 $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (".$this->sqlite->quote_and_join($values, ',').")"; 160 $res = $this->sqlite->query($query); 161 if($res !== false) 162 { 163 $this->updateSyncTokenLog($calid, $uri, 'added'); 164 return true; 165 } 166 return false; 167 } 168 169 public function getEventsWithinDateRange($id, $user, $startDate, $endDate) 170 { 171 $data = array(); 172 require_once('vendor/autoload.php'); 173 $calid = $this->getCalendarIdForPage($id); 174 $startTs = new \DateTime($startDate); 175 $endTs = new \DateTime($endDate); 176 $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid=". 177 $this->sqlite->quote_string($calid)." AND firstoccurence > ". 178 $this->sqlite->quote_string($startTs->getTimestamp())." AND firstoccurence < ". 179 $this->sqlite->quote_string($endTs->getTimestamp()); 180 $res = $this->sqlite->query($query); 181 $arr = $this->sqlite->res2arr($res); 182 foreach($arr as $row) 183 { 184 if(isset($row['calendardata'])) 185 { 186 $vcal = \Sabre\VObject\Reader::read($row['calendardata']); 187 $start = $vcal->VEVENT->DTSTART->getDateTime(); 188 $end = $vcal->VEVENT->DTEND->getDateTime(); 189 $summary = (string)$vcal->VEVENT->summary; 190 $data[] = array("title" => $summary, "start" => $start->format(\DateTime::W3C), 191 "end" => $end->format(\DateTime::W3C), 192 "id" => $row['uid']); 193 } 194 } 195 return $data; 196 } 197 198 public function getEventWithUid($uid) 199 { 200 $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid=". 201 $this->sqlite->quote_string($uid); 202 $res = $this->sqlite->query($query); 203 $row = $this->sqlite->res2row($res); 204 return $row; 205 } 206 207 public function editCalendarEntryForPage($id, $user, $params) 208 { 209 $uid = $params['uid']; 210 $event = $this->getEventWithUid($uid); 211 require_once('vendor/autoload.php'); 212 if(!isset($event['calendardata'])) 213 return false; 214 $uri = $event['uri']; 215 $calid = $event['calendarid']; 216 $vcal = \Sabre\VObject\Reader::read($event['calendardata']); 217 $vcal->VEVENT->summary = $params['eventname']; 218 $dtStart = new \DateTime($params['eventfrom'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 219 $dtEnd = new \DateTime($params['eventto'], new \DateTimeZone('Europe/Vienna')); // FIXME: Timezone 220 $vcal->VEVENT->DTSTART = $dtStart; 221 $vcal->VEVENT->DTEND = $dtEnd; 222 $now = new DateTime(); 223 $eventStr = $vcal->serialize(); 224 225 $query = "UPDATE calendarobjects SET calendardata=".$this->sqlite->quote_string($eventStr). 226 ", lastmodified=".$this->sqlite->quote_string($now->getTimestamp()). 227 ", firstoccurence=".$this->sqlite->quote_string($dtStart->getTimestamp()). 228 ", lastoccurence=".$this->sqlite->quote_string($dtEnd->getTimestamp()). 229 ", size=".strlen($eventStr). 230 ", etag=".$this->sqlite->quote_string(md5($eventStr)). 231 " WHERE uid=".$this->sqlite->quote_string($uid); 232 $res = $this->sqlite->query($query); 233 if($res !== false) 234 { 235 $this->updateSyncTokenLog($calid, $uri, 'modified'); 236 return true; 237 } 238 return false; 239 } 240 241 public function deleteCalendarEntryForPage($id, $params) 242 { 243 $uid = $params['uid']; 244 $event = $this->getEventWithUid($uid); 245 $calid = $event['calendarid']; 246 $uri = $event['uri']; 247 $query = "DELETE FROM calendarobjects WHERE uid=".$this->sqlite->quote_string($uid); 248 $res = $this->sqlite->query($query); 249 if($res !== false) 250 { 251 $this->updateSyncTokenLog($calid, $uri, 'deleted'); 252 } 253 return true; 254 } 255 256 public function getSyncTokenForCalendar($calid) 257 { 258 $query = "SELECT synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid); 259 $res = $this->sqlite->query($query); 260 $row = $this->sqlite->res2row($res); 261 if(isset($row['synctoken'])) 262 return $row['synctoken']; 263 return false; 264 } 265 266 public function operationNameToOperation($operationName) 267 { 268 switch($operationName) 269 { 270 case 'added': 271 return 1; 272 break; 273 case 'modified': 274 return 2; 275 break; 276 case 'deleted': 277 return 3; 278 break; 279 } 280 return false; 281 } 282 283 private function updateSyncTokenLog($calid, $uri, $operation) 284 { 285 $currentToken = $this->getSyncTokenForCalendar($calid); 286 $operationCode = $this->operationNameToOperation($operation); 287 if(($operationCode === false) || ($currentToken === false)) 288 return false; 289 $values = array($uri, 290 $currentToken, 291 $calid, 292 $operationCode 293 ); 294 $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(". 295 $this->sqlite->quote_and_join($values, ',').")"; 296 $res = $this->sqlite->query($query); 297 if($res === false) 298 return false; 299 $currentToken++; 300 $query = "UPDATE calendars SET synctoken=".$this->sqlite->quote_string($currentToken)." WHERE id=". 301 $this->sqlite->quote_string($calid); 302 $res = $this->sqlite->query($query); 303 return ($res !== false); 304 } 305 306} 307