xref: /plugin/davcal/helper.php (revision 55a741c0ad08b9f9e3b9d9e51875cfdf1f79b2c2)
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      $uri = $event['uri'];
246      $query = "DELETE FROM calendarobjects WHERE uid=".$this->sqlite->quote_string($uid);
247      $res = $this->sqlite->query($query);
248      if($res !== false)
249      {
250          $this->updateSyncTokenLog($calid, $uri, 'deleted');
251      }
252      return true;
253  }
254
255  public function getSyncTokenForCalendar($calid)
256  {
257      $query = "SELECT synctoken FROM calendars WHERE id=".$this->sqlite->quote_string($calid);
258      $res = $this->sqlite->query($query);
259      $row = $this->sqlite->res2row($res);
260      if(isset($row['synctoken']))
261          return $row['synctoken'];
262      return false;
263  }
264
265  public function operationNameToOperation($operationName)
266  {
267      switch($operationName)
268      {
269          case 'added':
270              return 1;
271          break;
272          case 'modified':
273              return 2;
274          break;
275          case 'deleted':
276              return 3;
277          break;
278      }
279      return false;
280  }
281
282  private function updateSyncTokenLog($calid, $uri, $operation)
283  {
284      $currentToken = $this->getSyncTokenForCalendar($calid);
285      $operationCode = $this->operationNameToOperation($operation);
286      if(($operationCode === false) || ($currentToken === false))
287          return false;
288      $values = array($uri,
289                      $currentToken,
290                      $calid,
291                      $operationCode
292      );
293      $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(".
294               $this->sqlite->quote_and_join($values, ',').")";
295      $res = $this->sqlite->query($query);
296      if($res === false)
297        return false;
298      $currentToken++;
299      $query = "UPDATE calendars SET synctoken=".$this->sqlite->quote_string($currentToken)." WHERE id=".
300               $this->sqlite->quote_string($calid);
301      $res = $this->sqlite->query($query);
302      return ($res !== false);
303  }
304
305}
306