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