xref: /plugin/davcal/helper.php (revision a495d34c25233615fa25fba79abef99239c1dd50)
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